svn commit: r495677 [4/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/cache/CachingHelper.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/cache/CachingHelper.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/cache/CachingHelper.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/cache/CachingHelper.java Fri Jan 12 10:19:39 2007
@@ -17,17 +17,15 @@
 
 import java.util.Properties;
 
-import org.apache.ojb.broker.PersistenceBrokerInternal;
 import org.apache.ojb.broker.metadata.ObjectCacheDescriptor;
 import org.apache.ojb.broker.util.ClassHelper;
 import org.apache.ojb.broker.util.logging.Logger;
 import org.apache.ojb.broker.util.logging.LoggerFactory;
 
 /**
- * Helper class encapsulates methods to create {@link CachingStrategy}
- * and {@link ObjectCacheExt} instances.
+ * Helper class encapsulates methods to create cache {@link Connector} instances
+ * and if needed {@link CachingPipe} and {@link ObjectCache} instances.
  *
- * @author <a href="mailto:[email protected]">Armin Waibel</a>
  * @version $Id$
  */
 public class CachingHelper
@@ -35,67 +33,80 @@
     private static Logger log = LoggerFactory.getLogger(CachingHelper.class);
 
     private static final Class DEFAULT_OBJECT_CACHE_CLASS = ObjectCacheEmptyImpl.class;
-    private static final Class DEFAULT_CACHING_STRATEGY_CLASS = CachingStrategyDefaultImpl.class;
+    private static final Class DEFAULT_CACHING_STRATEGY_CLASS = CachingPipeNoopImpl.class;
 
-    public static CachingStrategy newCachingStrategy(PersistenceBrokerInternal broker,
-                                                   ObjectCacheDescriptor cacheDescriptor,
-                                                   ObjectCacheExt oc)
+    /**
+     * Returns a new caching {@link Connector} instance.
+     *
+     * @param ocd The {@link org.apache.ojb.broker.metadata.ObjectCacheDescriptor} to create the Connector.
+     * @return The new cache connector.
+     */
+    public static Connector newConnector(ObjectCacheDescriptor ocd)
     {
-        Properties confProp = cacheDescriptor.getAttributes();
-        Class cacheStrategy = cacheDescriptor.getCachingStrategy() != null
-                ? cacheDescriptor.getCachingStrategy() : DEFAULT_CACHING_STRATEGY_CLASS;
+        CachingPipe cs = newCachingPreparer(ocd);
+        ObjectCache oc = newObjectCache(ocd);
+        return new Connector(ocd, oc, cs);
+    }
+
+    /**
+     * Returns a new {@link CachingPipe}.
+     *
+     * @param ocd The {@link org.apache.ojb.broker.metadata.ObjectCacheDescriptor}.
+     * @return A new {@link CachingPipe}.
+     */
+    public static CachingPipe newCachingPreparer(ObjectCacheDescriptor ocd)
+    {
+        Class cacheStrategy = ocd.getCachingPreparer() != null
+                ? ocd.getCachingPreparer() : DEFAULT_CACHING_STRATEGY_CLASS;
         if(log.isDebugEnabled())
         {
-            log.debug("Create new 'CachingStrategy' instance: " + cacheStrategy + ", using properties: " + confProp);
+            log.debug("Create new 'CachingPipe' instance: " + cacheStrategy + ", using properties: " + ocd.getAttributes());
         }
-        return createNewStrategy(cacheStrategy, broker, oc, cacheDescriptor);
+        return createNewStrategy(cacheStrategy, ocd);
     }
 
-    public static ObjectCacheExt newObjectCache(ObjectCacheDescriptor cacheDescriptor)
+    /**
+     * Returns a new {@link ObjectCache}.
+     *
+     * @param ocd The {@link org.apache.ojb.broker.metadata.ObjectCacheDescriptor}.
+     * @return A new {@link ObjectCache}.
+     */
+    public static ObjectCache newObjectCache(ObjectCacheDescriptor ocd)
     {
-        Properties confProp = cacheDescriptor.getAttributes();
-        Class cacheClass = (cacheDescriptor.getObjectCache() != null)
-                ? cacheDescriptor.getObjectCache() : DEFAULT_OBJECT_CACHE_CLASS;
+        Properties confProp = ocd.getAttributes();
+        Class cacheClass = (ocd.getObjectCache() != null)
+                ? ocd.getObjectCache() : DEFAULT_OBJECT_CACHE_CLASS;
         ObjectCache newCache;
 
         if(log.isDebugEnabled())
         {
-            log.debug("Create new 'ObjectCacheExt' instance: " + cacheClass + ", using properties: " + confProp);
+            log.debug("Create new 'ObjectCache' instance: " + cacheClass + ", using properties: " + confProp);
         }
         try
         {
             newCache = (ObjectCache) ClassHelper.newInstance(cacheClass,
-                    new Class[]{ObjectCacheDescriptor.class}, new Object[]{cacheDescriptor});
+                    new Class[]{ObjectCacheDescriptor.class}, new Object[]{ocd});
         }
         catch(Exception e)
         {
-            log.error("ObjectCache instantiation failed for '" + cacheClass + "' using descriptor " + cacheDescriptor, e);
+            log.error("ObjectCache instantiation failed for '" + cacheClass + "' using descriptor " + ocd, e);
             throw new RuntimeCacheException(e);
         }
-
-        if(newCache instanceof ObjectCacheExt)
-        {
-            return (ObjectCacheExt) newCache;
-        }
-        else
-        {
-            return new ObjectCacheWrapper(newCache);
-        }
+        return newCache;
     }
 
-    private static CachingStrategy createNewStrategy(Class target, PersistenceBrokerInternal broker,
-                                                   ObjectCacheExt oc, ObjectCacheDescriptor ocd)
+    private static CachingPipe createNewStrategy(Class target, ObjectCacheDescriptor ocd)
     {
-        CachingStrategy result;
+        CachingPipe result;
         try
         {
-            result = (CachingStrategy) ClassHelper.newInstance(target,
-                    new Class[]{PersistenceBrokerInternal.class, ObjectCacheExt.class, ObjectCacheDescriptor.class},
-                    new Object[]{broker, oc, ocd});
+            result = (CachingPipe) ClassHelper.newInstance(target,
+                    new Class[]{ObjectCacheDescriptor.class},
+                    new Object[]{ocd});
         }
         catch(Exception e)
         {
-            log.error("CachingStrategy instantiation failed for '" + target + "' using properties " + ocd.getAttributes());
+            log.error("CachingPipe instantiation failed for '" + target + "' using properties " + ocd.getAttributes());
             throw new RuntimeCacheException(e);
         }
         return result;

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/cache/CachingManager.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/cache/CachingManager.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/cache/CachingManager.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/cache/CachingManager.java Fri Jan 12 10:19:39 2007
@@ -20,7 +20,6 @@
 import java.util.Map;
 
 import org.apache.ojb.broker.ConfigurationException;
-import org.apache.ojb.broker.PersistenceConfiguration;
 import org.apache.ojb.broker.metadata.ObjectCacheDescriptor;
 import org.apache.ojb.broker.util.logging.Logger;
 import org.apache.ojb.broker.util.logging.LoggerFactory;
@@ -30,146 +29,118 @@
  * one {@link org.apache.ojb.broker.PersistenceConfiguration}.
  * The <em>CachingManager</em> is responsible
  * <br/>
- * - to lookup the assigned {@link ObjectCacheExt} for
+ * - to lookup the assigned caching {@link Connector} for
  * given persistent object class.
  * <br/>
- * - to provide methods to clear the different caches based on
- * the persistent object class
+ * - to provide method to clear all application caches managed
+ * by this instance.
  *
- * @author <a href="mailto:[email protected]">Armin Waibel</a>
  * @version $Id$
- * @see ObjectCacheExt
- * @see ObjectCache
  */
 public class CachingManager
 {
     private Logger log = LoggerFactory.getLogger(CachingManager.class);
-    protected static final Class DEFAULT_KEY = CachingManager.class;
+    private final Object sync = new Object();
+    private final ObjectCacheDescriptor connectionLevelDescriptor;
 
-    private Map cachesForDescriptors;
-    private PersistenceConfiguration pc;
+    private Map connectors;
 
-    public CachingManager(PersistenceConfiguration pc)
+    public CachingManager(ObjectCacheDescriptor connectionLevelDescriptor)
     {
-        this.pc = pc;
-        this.cachesForDescriptors = new HashMap();
-        init();
+        reset();
+        this.connectionLevelDescriptor = connectionLevelDescriptor;
+        addConnector(connectionLevelDescriptor, CachingHelper.newConnector(connectionLevelDescriptor));
     }
 
-    protected void init()
+    public void addConnector(ObjectCacheDescriptor ocd, Connector connector) throws ConfigurationException
     {
-        ObjectCacheDescriptor ocd = pc.getJdbcConnectionDescriptor().getObjectCacheDescriptor();
-        addCacheFor(ocd, CachingHelper.newObjectCache(ocd));
-    }
-
-    public synchronized void addCacheFor(ObjectCacheDescriptor ocd, ObjectCacheExt cache) throws ConfigurationException
-    {
-        if(cachesForDescriptors.containsKey(ocd))
+        synchronized(sync)
         {
-            throw new ConfigurationException("Can't add ObjectCacheExt instance '"
-                    + cache + "', descriptor is already added: " + ocd);
+            if(connectors.containsKey(ocd))
+            {
+                throw new RuntimeCacheException("Can't add duplicate cache connector instance '"
+                        + connector + "', descriptor is: " + ocd);
+            }
+            connectors.put(ocd, connector);
         }
-        cachesForDescriptors.put(ocd, cache);
+        if(log.isDebugEnabled()) log.debug("Add cache connector for '" + ocd + "'");
     }
 
-    public synchronized ObjectCacheExt removeCacheFor(ObjectCacheExt ocd)
+    public Connector removeConnector(ObjectCacheDescriptor ocd)
     {
-        log.info("Remove ObjectCacheExt represented by key '" + ocd + "'");
-        return (ObjectCacheExt) cachesForDescriptors.remove(ocd);
+        if(log.isDebugEnabled()) log.debug("Remove cache connector associated with '" + ocd + "'");
+        synchronized(sync)
+        {
+            return (Connector) connectors.remove(ocd);
+        }
     }
 
-    public synchronized ObjectCacheExt getCacheFor(ObjectCacheDescriptor ocd)
+    public Connector getConnector(ObjectCacheDescriptor ocd)
     {
-        ObjectCacheExt result;
-        if(ocd == null || ocd.getObjectCache() == null)
+        Connector result;
+        if(ocd == null)
         {
-            ObjectCacheDescriptor defaultOcd = pc.getJdbcConnectionDescriptor().getObjectCacheDescriptor();
-            result = (ObjectCacheExt) cachesForDescriptors.get(defaultOcd);
+            ocd = connectionLevelDescriptor;
             if(log.isDebugEnabled())
             {
-                log.debug("No cache definition found, use cache " + result
-                        + " defined in connection descriptor for " + ocd);
+                log.debug("Use connection level cache connector defined in connection descriptor: " + ocd);
             }
         }
-        else
+        result = (Connector) connectors.get(ocd);
+        if(result == null)
         {
-            result = (ObjectCacheExt) cachesForDescriptors.get(ocd);
-            if(result == null)
+            try
             {
-                result = CachingHelper.newObjectCache(ocd);
-                addCacheFor(ocd, result);
+                result = CachingHelper.newConnector(ocd);
+                addConnector(ocd, result);
             }
-            if(log.isDebugEnabled())
+            catch(RuntimeCacheException ignore)
             {
-                log.debug("Use cache " + result + " for " + ocd);
+                // ignore, could only happen when concurrency issue occur
+                log.warn("Possible concurrency issue: Can't add caching Connector instance for " + ocd
+                        + ". Normally this doesn't have an effect, OJB will add the Connector next time.", ignore);
             }
         }
         return result;
     }
 
-    public synchronized void clearCaches()
+    /**
+     * Evict all application caches managed by this caching manager instance.
+     * This is different to method {@link #reset()}.
+     */
+    public void evictAll()
     {
-        if(!cachesForDescriptors.isEmpty())
+        synchronized(sync)
         {
-            if(log.isDebugEnabled())
-            {
-                log.debug("Start clearing all used ObjectCacheExt instances");
-            }
-            Iterator it = cachesForDescriptors.entrySet().iterator();
-            while(it.hasNext())
+            if(!connectors.isEmpty())
             {
-                Map.Entry entry = (Map.Entry) it.next();
                 if(log.isDebugEnabled())
                 {
-                    log.debug("Clear cache for descriptor: " + entry.getKey() + ", cache instance is: " + entry.getValue());
+                    log.debug("Start clearing all used ObjectCache instances");
+                }
+                Iterator it = connectors.entrySet().iterator();
+                while(it.hasNext())
+                {
+                    Map.Entry entry = (Map.Entry) it.next();
+                    if(log.isDebugEnabled())
+                    {
+                        log.debug("Clear cache for descriptor: " + entry.getKey());
+                    }
+                    ((Connector) entry.getValue()).applicationCache.clear();
                 }
-                ((ObjectCacheExt) entry.getValue()).clear();
             }
         }
     }
 
-    public void clearCacheFor(ObjectCacheDescriptor ocd)
+    /**
+     * This method reset this class to initial state by throwing away all
+     * managed {@link Connector} instances. This is different to method {@link #evictAll()}.
+     */
+    public void reset()
     {
-        ObjectCacheExt cache = getCacheFor(ocd);
-        boolean def = false;
-        if(cache == null)
+        synchronized(sync)
         {
-            cache = getCacheFor(pc.getJdbcConnectionDescriptor().getObjectCacheDescriptor());
-            def = true;
-        }
-        cache.clear();
-        if(log.isDebugEnabled())
-        {
-            String msg;
-            if(def)
-            {
-                msg = "Cleared cache defined on connection level, because descriptor "
-                        + ocd + " doesn't match a cache on class level";
-            }
-            else
-            {
-                msg = "Cleared specific cache on class level: " + ocd;
-            }
-            log.debug(msg);
-        }
-    }
-
-    public synchronized void registerForObjectInvalidation(CachingManager manager, boolean viceVersa)
-    {
-        Iterator it = cachesForDescriptors.entrySet().iterator();
-        Map.Entry entry;
-        while(it.hasNext())
-        {
-            entry = (Map.Entry) it.next();
-            ObjectCacheDescriptor key = (ObjectCacheDescriptor) entry.getKey();
-            ObjectCacheExt registry = (ObjectCacheExt) entry.getValue();
-
-            ObjectCacheExt listener = manager.getCacheFor(key);
-            registry.addInvalidationListener(listener);
-            if(viceVersa)
-            {
-                listener.addInvalidationListener(registry);
-            }
+            connectors = new HashMap();
         }
     }
 }

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/cache/InvalidationListener.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/cache/InvalidationListener.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/cache/InvalidationListener.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/cache/InvalidationListener.java Fri Jan 12 10:19:39 2007
@@ -28,15 +28,16 @@
  * take care of objects removed from the cache
  * </li>
  * </ul>
- * To register this listener use {@link ObjectCacheExt#addInvalidationListener(InvalidationListener)}.
+ * To register this listener use method {@link InvalidationRegistry#addInvalidationListener(InvalidationListener)}.
  *
- * @author <a href="mailto:[email protected]">Armin Waibel</a>
  * @version $Id$
  */
 public interface InvalidationListener
 {
     /**
-     * Invalidate the assigned object.
+     * Invalidate the assigned object. The invalidation doesn't cascade, thus if this listener is
+     * itself a {@link InvalidationRegistry} the invalidation doesn't notify the registered listener.
+     * This non-cascading behavior is needed to avoid deadlocks and endless invalidation loops.
      *
      * @param oid The {@link org.apache.ojb.broker.Identity} of the object to invalidate.
      */

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/cache/MaterializationCache.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/cache/MaterializationCache.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/cache/MaterializationCache.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/cache/MaterializationCache.java Fri Jan 12 10:19:39 2007
@@ -117,14 +117,14 @@
      * Lookup an object from cache.
      *
      * @param oid The {@link org.apache.ojb.broker.Identity} object.
-     * @return The cached {@link ObjectEntry} or <em>null</em>.
+     * @return The cached {@link SessionEntry} or <em>null</em>.
      */
-    public ObjectEntry lookup(Identity oid)
+    public SessionEntry lookup(Identity oid)
     {
-        ObjectEntry result = null;
+        SessionEntry result = null;
         if(enabledReadCache)
         {
-            result = (ObjectEntry) objectBuffer.get(oid);
+            result = (SessionEntry) objectBuffer.get(oid);
         }
         return result;
     }

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCache.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCache.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCache.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCache.java Fri Jan 12 10:19:39 2007
@@ -18,40 +18,34 @@
 import org.apache.ojb.broker.Identity;
 
 /**
- * The <code>ObjectCache</code> stores all Objects loaded by the
- * {@link org.apache.ojb.broker.PersistenceBroker} from a DB.
- * When the PersistenceBroker tries to get an Object by its Primary key values
- * it first lookups the cache if the object has been already loaded and cached.
+ * The <code>ObjectCache</code> stores cacheable objects assigned with
+ * a single {@link org.apache.ojb.broker.PersistenceConfiguration} - it's
+ * the so called "application cache" of OJB.
+ * <br/>
+ * It's different from the
+ * {@link SessionCache} which only manage objects of the same
+ * session/{@link org.apache.ojb.broker.PersistenceBroker} instance.
  * <p>
- * Using an ObjectCache has several advantages:
- * - it increases performance as it reduces DB lookups.
- * - it allows to perform circular lookups (as by crossreferenced objects)
- * that would result in non-terminating loops without such a cache.
- * - it maintains the uniqueness of objects as any Db row will be mapped to
- * exactly one object.
- * </p>
- * <p>
- * This interface allows to have user-defined Cache implementations.
- * To make the <code>ObjectCache</code> implementation work, a
- * constructor with {@link java.util.Properties} as argument is needed.
+ * This interface allows to have user-defined cache implementations.
+ * To make the <code>ObjectCache</code> implementation work, please check
+ * which constructor arguments are needed.
  * </p>
+ * NOTE: All implementations have to be <em>thread-safe</em>!
  *
  * @version $Id$
  */
-public interface ObjectCache
+public interface ObjectCache extends InvalidationRegistry, InvalidationListener
 {
     /**
-     * For internal use - Used to cache new objects (not already cached) by it's
-     * {@link org.apache.ojb.broker.Identity}. This method was used to
+     * Used to cache new objects (not already cached) by it's
+     * {@link org.apache.ojb.broker.Identity}. This method is used to
      * cache new materialized objects and should work as a "atomic" method
-     * , the check ("if already cached check") and the put of the object
-     * have to be atomic to avoid concurrency issues.
-     * </p>
-     * <p>
-     * Currently it's not mandatory that all <em>ObjectCache</em> implementations
-     * support this method, so in some cases it's allowed to delegate this
-     * method call to the standard {@link #cache(org.apache.ojb.broker.Identity, Object) cache method}.
-     * </p>
+     * , the check ("if already cached") and the put of the object
+     * have to be atomic to avoid concurrency issues. This method
+     * should never replace already existing cached objects.
+     * <br/>
+     * NOTE: If it's not possible to implement an atomic version of this method,
+     * implement it as NOOP and return <em>false</em>.
      *
      * @param oid Identity of the object to cache.
      * @param obj The object to cache.
@@ -61,6 +55,7 @@
 
     /**
      * Cache the object.
+     *
      * @param oid The {@link org.apache.ojb.broker.Identity} of the object.
      * @param obj The object to cache.
      */
@@ -68,6 +63,7 @@
 
     /**
      * Lookup an cached object.
+     *
      * @param oid The {@link org.apache.ojb.broker.Identity} of the wanted object.
      * @return The matching object or <em>null</em> if no object was found
      * for given {@link org.apache.ojb.broker.Identity}.
@@ -76,6 +72,7 @@
 
     /**
      * Removes an Object from the cache.
+     *
      * @param oid Identity of the object to be removed.
      */
     public void remove(Identity oid);

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCacheDefaultImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCacheDefaultImpl.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCacheDefaultImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCacheDefaultImpl.java Fri Jan 12 10:19:39 2007
@@ -90,7 +90,7 @@
     protected static final String PROP_USE_SOFT_REFERENCES = "useSoftReferences";
     protected static final String PROP_MAX_ENTRY = "maxEntry";
 
-    private final Object dummy = new Object();
+    private final Object sync = new Object();
 
     /**
      * Map held all cached objects
@@ -157,7 +157,7 @@
         boolean result = false;
         // perform queue before check for key in objectTable
         processQueue();
-        synchronized(dummy)
+        synchronized(sync)
         {
             if(!objectTable.containsKey(oid))
             {
@@ -174,13 +174,13 @@
      * I'm using soft-references to allow gc reclaim unused objects
      * even if they are still cached.
      */
-    public void cache(Identity oid, Object obj)
+    public void doCache(Identity oid, Object obj)
     {
         //processQueue();
         if ((obj != null))
         {
             CacheEntry entry = buildEntry(obj, oid);
-            synchronized (dummy)
+            synchronized (sync)
             {
                 objectTable.put(oid, entry);
             }
@@ -221,7 +221,7 @@
         //processQueue();
         if (oid != null)
         {
-            synchronized (dummy)
+            synchronized (sync)
             {
                 objectTable.remove(oid);
             }
@@ -233,7 +233,7 @@
         if (useSoftReferences)
         {
             CacheEntry entry;
-            synchronized(dummy)
+            synchronized(sync)
             {
                 while ((entry = (CacheEntry) queue.poll()) != null)
                 {

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCacheEmptyImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCacheEmptyImpl.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCacheEmptyImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCacheEmptyImpl.java Fri Jan 12 10:19:39 2007
@@ -76,7 +76,7 @@
     /**
      * @see org.apache.ojb.broker.cache.ObjectCache#cache(Identity, Object)
      */
-    public void cache(Identity oid, Object obj)
+    public void doCache(Identity oid, Object obj)
     {
         //do nothing
     }

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCacheJCSImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCacheJCSImpl.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCacheJCSImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCacheJCSImpl.java Fri Jan 12 10:19:39 2007
@@ -169,7 +169,7 @@
     /**
      * makes object obj persistent to the Objectcache under the key oid.
      */
-    public void cache(Identity oid, Object obj)
+    public void doCache(Identity oid, Object obj)
     {
         try
         {

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCacheOSCacheImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCacheOSCacheImpl.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCacheOSCacheImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/cache/ObjectCacheOSCacheImpl.java Fri Jan 12 10:19:39 2007
@@ -31,7 +31,7 @@
  * <pre>
  * &lt;object-cache class="org.apache.ojb.broker.cache.ObjectCacheOSCacheImpl"
  *    timeout="900"
- *    strategy="org.apache.ojb.broker.cache.CachingStrategyTwoLevelImpl" &gt;
+ *    strategy="org.apache.ojb.broker.cache.CachingPipeFlatCopyImpl" &gt;
  *    &lt;!-- attributes used by OsCache --&gt;
  *    &lt;attribute attribute-name="cache.cron" attribute-value="0 2 * * *" /&gt;
  *    &lt;attribute attribute-name="flushOnPut" attribute-value="false" /&gt;
@@ -147,7 +147,7 @@
         return oid.toString() + DOT + region;
     }
 
-    public void cache(Identity oid, Object obj)
+    public void doCache(Identity oid, Object obj)
     {
         try
         {

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/cache/RuntimeCacheException.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/cache/RuntimeCacheException.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/cache/RuntimeCacheException.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/cache/RuntimeCacheException.java Fri Jan 12 10:19:39 2007
@@ -16,6 +16,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+/**
+ * This exception reports a caching issue.
+ */
 public class RuntimeCacheException extends OJBRuntimeException
 {
     public RuntimeCacheException()

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/cache/SessionCache.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/cache/SessionCache.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/cache/SessionCache.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/cache/SessionCache.java Fri Jan 12 10:19:39 2007
@@ -18,25 +18,29 @@
  */
 
 /**
- * Used for persistence capable object caching. Each {@link org.apache.ojb.broker.PersistenceBroker}
- * instance use its own <em>session cache</em> instance. The <em>session cache</em>
- * is used to solve three tasks:
+ * This is OJB's central class for session based object caching. Each
+ * {@link org.apache.ojb.broker.PersistenceBroker} instance use its own <em>session cache</em>
+ * instance. The <em>session cache</em> is used to solve three tasks:
  * <ul>
  * <li>
  * when materialize objects with circular
  * references the <em>session cache</em> helps to avoid endless recursion
  * and is responsible to push only full materialized (dependent on the persistent
- * object metadata settings) objects to higher level caches (second level cache).
+ * object metadata settings) objects to the higher level cache (normaly the application cache).
+ * So it's possible to prevent objects cached in the session cache but it's not possible to
+ * disable the materialization cache while object materialization.
  * <br/>
  * It represents a kind of <em>"materialization cache"</em>.
  * </li>
  * <li>
  * it cache persistent capable objects as long as the superior
- * {@link org.apache.ojb.broker.PersistenceBroker} instance is <em>open</em>.
+ * {@link org.apache.ojb.broker.PersistenceBroker} instance is <em>open</em>
+ * or the cache is evicted by hand (except objects with cache level {@link #LEVEL_MATERIALIZE}).
  * </li>
  * <li>
- * represents a interface to higher level caches, so called
- * second level cache implementations.
+ * manages the access to higher level caches, the so called
+ * 'application cache' implementation (like a 'second level cache') represented by the
+ * {@link ObjectCache} interface.
  * </li>
  * </ul>
  *
@@ -46,26 +50,29 @@
 {
     /*
     arminw:
-    NOTE: Never change the order of the TYPE_X, BLOCK_X and LEVEL_X constants, because in code
+    NOTE: Never change the values/order of the TYPE_X, BLOCK_X and LEVEL_X constants, because in code
     checks like "if(level > LEVEL_MATERIALIZE)" are done.
     */
 
-
     /**
      * Object to cache has unkown source and state.
      */
     public static final byte TYPE_UNKNOWN = 0;
     /**
-     * Object to cache was read from cache and not changed
+     * Object to cache is read from cache and not changed
      * (e.g. from a second-level cache).
      */
     public static final byte TYPE_CACHED_READ = 1;
     /**
-     * Object to cache was updated or inserted.
+     * Object to cache is inserted.
+     */
+    public static final byte TYPE_INSERT = 2;
+    /**
+     * Object to cache is updated.
      */
-    public static final byte TYPE_WRITE = 2;
+    public static final byte TYPE_UPDATE = 3;
     /**
-     * Object to cache was new materialized from the persistence
+     * Object to cache is new materialized from the persistence
      * storage.
      */
     public static final byte TYPE_NEW_MATERIALIZED = 4;
@@ -109,14 +116,14 @@
      * Indicate that the operation only take effect while
      * persistent object materialization - affect only the object
      * materialization cache.
-     * Higher level caches (e.g. session cache or a second level cache)
+     * Higher level caches (e.g. session cache or a application cache)
      * are ignored.
      */
     public static final int LEVEL_MATERIALIZE = 23;
     /**
      * Indicate that the operation affect the
      * session cache and lower level caches (e.g. a object materialization cache).
-     * Higher level caches (e.g. a second level cache) are ignored.
+     * Higher level caches (e.g. the application cache) are ignored.
      */
     public static final int LEVEL_SESSION = 27;
     /**
@@ -130,7 +137,7 @@
      * @param obj The object to cache.
      * @param oid The object {@link org.apache.ojb.broker.Identity}.
      * @param type The type of the object: {@link #TYPE_CACHED_READ}, {@link #TYPE_NEW_MATERIALIZED}
-     * , {@link #TYPE_WRITE}, {@link #TYPE_UNKNOWN}.
+     * , {@link #TYPE_INSERT}, {@link #TYPE_UPDATE}, {@link #TYPE_UNKNOWN}.
      * @param level The cache level of the object to cache:
      * {@link #LEVEL_DEEP}, {@link #LEVEL_SESSION}, {@link #LEVEL_MATERIALIZE}.
      * @return New instance of a {@link SessionEntry}.
@@ -138,20 +145,21 @@
     public SessionEntry newEntry(Object obj, Identity oid, byte type, int level);
 
     /**
-     * For internal use only! This methods puts the specified object to session cache
-     * without any further checks (if not <em>blocked</em> from being cached).
+     * Intended for internal use! This methods puts the specified object to session cache
+     * without any <em>cache level</em> check, only the <em>block level</em> of the session cache
+     * is checked.
      *
      * @param entry The {@link SessionEntry} to cache.
      */
     public void putToSessionCache(SessionEntry entry);
 
     /**
-     * This method must to be used by all OJB classes to cache objects.
+     * This method have to be used by all OJB classes to cache objects.
      *
      * @param oid The {@link org.apache.ojb.broker.Identity} of the object.
      * @param obj The object to cache.
      * @param type The type of the object: {@link #TYPE_CACHED_READ}, {@link #TYPE_NEW_MATERIALIZED}
-     * , {@link #TYPE_WRITE}, {@link #TYPE_UNKNOWN}.
+     * , {@link #TYPE_INSERT}, {@link #TYPE_UPDATE}, {@link #TYPE_UNKNOWN}.
      * @param level The cache level this operation should take effect:
      * {@link #LEVEL_DEEP}, {@link #LEVEL_SESSION}, {@link #LEVEL_MATERIALIZE}.
      */
@@ -195,6 +203,16 @@
     public void evict(Identity oid, int level);
 
     /**
+     * Evict the specified object completely from cache.
+     * A convenience method for {@link #evict(org.apache.ojb.broker.Identity, int)}
+     * with level {@link #LEVEL_DEEP}.
+     *
+     * @param oid the {@link org.apache.ojb.broker.Identity} of the object
+     * to evict from the cache.
+     */
+    public void evict(Identity oid);
+
+    /**
      * Evict all objects of the specified class from the cache.
      *
      * @param objectClass the class of persistent objects
@@ -205,6 +223,16 @@
     public void evict(Class objectClass, int level);
 
     /**
+     * Evict all objects of the specified class completely from cache.
+     * A convenience method for {@link #evict(Class, int)}
+     * with level {@link #LEVEL_DEEP}.
+     *
+     * @param objectClass the class of persistent objects
+     * to evict from the cache.
+     */
+    public void evict(Class objectClass);
+
+    /**
      * Evict all objects from the cache.
      *
      * @param level The cache level this operation should take effect:
@@ -213,6 +241,13 @@
     public void evictAll(int level);
 
     /**
+     * Evict all objects from the cache.
+     * A convenience method for {@link #evictAll(int)}
+     * with level {@link #LEVEL_DEEP}.
+     */
+    public void evictAll();
+
+    /**
      * Reset the session cache:
      * <br/>
      * - evict all cached objects in materialization and session cache
@@ -224,20 +259,36 @@
     public void reset();
 
     /**
-     * Return the used second level cache instance for the specified class
-     * (of a persistence capable object).
+     * Returns the {@link Connector} which encapsulates the
+     * application cache and {@link CachingPipe} of the
+     * specified object class (of a persistence capable object). If the specifed
+     * class isn't a top-level class OJB resolve the top-level class internally.
      *
      * @param objectClass The class of the persistence capable
-     * object, see {@link org.apache.ojb.broker.PersistenceBroker#getTopLevelClass(Class)}.
-     * If <em>null</em> was set, the second level cache defined in the
+     * object.
+     * If <em>null</em> was set, the connection level connector instance defined in the
      * {@link org.apache.ojb.broker.metadata.JdbcConnectionDescriptor} is returned.
-     * @return The second level cache for specified top-level class or <em>null</em> if not set.
+     * @return The {@link Connector} of specified (top-level) class.
      */
-    public CachingStrategy getCachingStrategy(Class objectClass);
+    public Connector getConnector(Class objectClass);
+
+//    /**
+//     * Returns the {@link Connector} which encapsulates the
+//     * second level (application) cache and {@link CachingPipe} of the
+//     * specified object class (of a persistence capable object). If the specifed
+//     * class isn't a top-level class OJB resolve the top-level class internally.
+//     *
+//     * @param cld The descriptor of the persistence capable
+//     * object.
+//     * If <em>null</em> was set, the connection level connector instance defined in the
+//     * {@link org.apache.ojb.broker.metadata.JdbcConnectionDescriptor} is returned.
+//     * @return The {@link Connector} of specified (top-level) class.
+//     */
+//    public Connector getConnector(ClassDescriptor cld);
 
     /**
      * Block objects from being cached or lookup (this affects the session
-     * cache and the second level cache, the materialization cache will
+     * cache and the application cache, the materialization cache will
      * never be blocked).
      * The possible types are {@link #BLOCK_ALL}, {@link #BLOCK_WRITE},
      * {@link #BLOCK_LOOKUP}, {@link #BLOCK_NONE}.
@@ -260,6 +311,7 @@
     /**
      * Remove the object caching block, convenience method for
      * <em>setBlock(BLOCK_NONE)</em>.
+     *
      * @see #setBlock(int)
      */
     public void unBlock();
@@ -302,5 +354,5 @@
      * must be called in conjunction with {@link #enableMaterializationCache()} when
      * an exception occur.
      */
-    public void clearMaterializationCache();   
+    public void clearMaterializationCache();
 }

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/cache/SessionCacheImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/cache/SessionCacheImpl.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/cache/SessionCacheImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/cache/SessionCacheImpl.java Fri Jan 12 10:19:39 2007
@@ -4,12 +4,14 @@
 import java.util.Iterator;
 import java.util.Map;
 
+import org.apache.commons.lang.SystemUtils;
+import org.apache.commons.lang.builder.ToStringBuilder;
 import org.apache.ojb.broker.Identity;
 import org.apache.ojb.broker.PBStateEvent;
 import org.apache.ojb.broker.PBStateListener;
 import org.apache.ojb.broker.PersistenceBrokerInternal;
+import org.apache.ojb.broker.metadata.ClassDescriptor;
 import org.apache.ojb.broker.metadata.ObjectCacheDescriptor;
-import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
 import org.apache.ojb.broker.util.logging.Logger;
 import org.apache.ojb.broker.util.logging.LoggerFactory;
 
@@ -29,7 +31,6 @@
  */
 
 /**
- * @author <a href="mailto:[email protected]">Armin Waibel</a>
  * @version $Id$
  */
 public class SessionCacheImpl implements SessionCache, PBStateListener
@@ -40,7 +41,6 @@
     private MaterializationCache materializationCache;
     private CachingManager cachingManager;
     private Map sessionCacheMap;
-    private Map cacheStrategies;
     private int blockState;
 
     public SessionCacheImpl(final PersistenceBrokerInternal broker)
@@ -54,85 +54,38 @@
     public void reset()
     {
         this.sessionCacheMap = new HashMap(200);
-        this.cacheStrategies = new HashMap(50);
         this.materializationCache = new MaterializationCache(this);
         this.blockState = BLOCK_NONE;
     }
 
-    /**
-     * Returns a {@link CachingStrategy} instance for the specified persistence
-     * capable object class. If <em>null</em> is specified, the {@link CachingStrategy}
-     * defined on connection level (see {@link org.apache.ojb.broker.metadata.JdbcConnectionDescriptor})
-     * will be returned.
-     *
-     * @param objectClass The class of a persistence capable object or <em>null</em>.
-     * @return A instance of the associated {@link CachingStrategy}.
-     */
-    public CachingStrategy getCachingStrategy(Class objectClass)
+    void pushToApplicationCache()
     {
-        CachingStrategy cs;
-        if(objectClass == null)
-        {
-            cs = getCachingStrategyConnectionLevel();
-        }
-        else
+        SessionEntry entry;
+        Connector connector = null;
+        Class lastClass = null;
+        for(Iterator iterator = sessionCacheMap.entrySet().iterator(); iterator.hasNext();)
         {
-            cs = (CachingStrategy) cacheStrategies.get(objectClass);
-            if(cs == null)
+            entry = (SessionEntry) ((Map.Entry) iterator.next()).getValue();
+            if(entry.getLevel() == LEVEL_DEEP && (entry.getType() == TYPE_UPDATE || entry.getType() == TYPE_INSERT))
             {
-                Class top = broker.getConfiguration().getModel().getTopLevelClass(objectClass);
-                ObjectCacheDescriptor ocd = broker.getClassDescriptor(top).getObjectCacheDescriptor();
-                if(ocd == null)
+                Class current = entry.getIdentity().getObjectsTopLevelClass();
+                if(!current.equals(lastClass))
                 {
-                    cs = getCachingStrategyConnectionLevel();
-                    cacheStrategies.put(objectClass, cs);
+                    connector = getConnector(current, false);
+                    lastClass = current;
                 }
-                else
+                try
                 {
-                    cs = newStrategy(ocd);
-                    cacheStrategies.put(objectClass, cs);
+                    if(!connector.ocd.isExcluded(entry.getIdentity().getObjectsRealClass()))
+                    {
+                        connector.cache(broker, entry.getIdentity(), entry.getObject());
+                    }
                 }
-            }
-        }
-        return cs;
-    }
-
-    private CachingStrategy getCachingStrategyConnectionLevel()
-    {
-        CachingStrategy cs = (CachingStrategy) cacheStrategies.get(JdbcConnectionDescriptor.class);
-        if(cs == null)
-        {
-            ObjectCacheDescriptor ocd = broker.getConfiguration().getJdbcConnectionDescriptor().getObjectCacheDescriptor();
-            cs = newStrategy(ocd);
-            cacheStrategies.put(JdbcConnectionDescriptor.class, cs);
-        }
-        return cs;
-    }
-
-    private CachingStrategy newStrategy(ObjectCacheDescriptor ocd)
-    {
-        ObjectCacheExt oc;
-        if(ocd == null)
-        {
-            ocd = broker.getConfiguration().getJdbcConnectionDescriptor().getObjectCacheDescriptor();
-        }
-        oc = cachingManager.getCacheFor(ocd);
-        return CachingHelper.newCachingStrategy(broker, ocd, oc);
-    }
-
-    public void pushToApplicationCache()
-    {
-        SessionEntry entry;
-        CachingStrategy cs;
-        for(Iterator iterator = sessionCacheMap.values().iterator(); iterator.hasNext();)
-        {
-            entry = (SessionEntry) iterator.next();
-            if(entry.getLevel() == LEVEL_DEEP && entry.getType() == TYPE_WRITE)
-            {
-                cs = getCachingStrategy(entry.getIdentity().getObjectsTopLevelClass());
-                if(!cs.getObjectCacheDescriptor().isExcluded(entry.getIdentity().getObjectsRealClass()))
+                catch(NullPointerException e)
                 {
-                    cs.cache(entry.getIdentity(), entry, false);
+                    String eol = SystemUtils.LINE_SEPARATOR;
+                    log.error("Unexpected NPE while put an object to application cache."
+                            + eol + "SessionEntry: " + entry, e);
                 }
                 /*
                 change type to prevent multiple push of the same object
@@ -168,17 +121,17 @@
 
     public Object lookup(Identity oid, int level)
     {
-        ObjectEntry result;
-        result = materializationCache.lookup(oid);
+        SessionEntry result = materializationCache.lookup(oid);
         if(result == null
                 && blockState != BLOCK_LOOKUP
                 && blockState != BLOCK_ALL
                 && level > LEVEL_MATERIALIZE)
         {
-            result = (ObjectEntry) sessionCacheMap.get(oid);
+            result = (SessionEntry) sessionCacheMap.get(oid);
             if(result == null && level == LEVEL_DEEP)
             {
-                result = getCachingStrategy(oid.getObjectsTopLevelClass()).lookup(oid);
+                // directly return the object from application cache
+                return getConnector(oid.getObjectsTopLevelClass(), false).lookup(broker, oid);
             }
         }
         return result != null ? result.getObject() : null;
@@ -194,6 +147,17 @@
         if(blockState < BLOCK_WRITE)
         {
             sessionCacheMap.put(entry.getIdentity(), entry);
+            // new materialized objects will be immediately put to the application cache
+            if(entry.getType() == TYPE_NEW_MATERIALIZED && entry.getLevel() == LEVEL_DEEP)
+            {
+                Connector con = getConnector(entry.getIdentity().getObjectsTopLevelClass(), false);
+                con.cacheIfNew(broker, entry.getIdentity(), entry.getObject());
+                /*
+                change type to prevent multiple put of the same object
+                to application cache
+                */
+                entry.setType(TYPE_CACHED_READ);
+            }
         }
     }
 
@@ -205,19 +169,9 @@
         }
         else
         {
-            if(blockState < BLOCK_WRITE && entry.getLevel() > LEVEL_MATERIALIZE)
+            if(entry.getLevel() > LEVEL_MATERIALIZE)
             {
                 putToSessionCache(entry);
-                if(entry.getType() == TYPE_NEW_MATERIALIZED && entry.getLevel() == LEVEL_DEEP)
-                {
-                    CachingStrategy cs = getCachingStrategy(entry.getIdentity().getObjectsTopLevelClass());
-                    cs.cache(entry.getIdentity(), entry, false);
-                    /*
-                    change type to prevent multiple put of the same object
-                    to application cache
-                    */
-                    entry.setType(TYPE_CACHED_READ);
-                }
             }
         }
     }
@@ -235,7 +189,7 @@
             sessionCacheMap.remove(oid);
             if(level == LEVEL_DEEP)
             {
-                getCachingStrategy(oid.getObjectsTopLevelClass()).remove(oid);
+                getConnector(oid.getObjectsTopLevelClass(), false).applicationCache.remove(oid);
             }
         }
     }
@@ -248,7 +202,7 @@
             sessionCacheMap.clear();
             if(level == LEVEL_DEEP)
             {
-                cachingManager.clearCaches();
+                cachingManager.evictAll();
             }
         }
     }
@@ -271,7 +225,7 @@
             }
             if(level == LEVEL_DEEP)
             {
-                getCachingStrategy(topLevelClass).clear();
+                getConnector(objectClass, true).applicationCache.clear();
             }
         }
     }
@@ -296,6 +250,49 @@
         return new SessionEntryImpl(obj, oid, type, level);
     }
 
+    public void evict(Identity oid)
+    {
+        evict(oid, SessionCache.LEVEL_DEEP);
+    }
+
+    public void evict(Class objectClass)
+    {
+        evict(objectClass, SessionCache.LEVEL_DEEP);
+    }
+
+    public void evictAll()
+    {
+        evictAll(SessionCache.LEVEL_DEEP);
+    }
+
+    public Connector getConnector(ObjectCacheDescriptor ocd)
+    {
+        return cachingManager.getConnector(ocd);
+    }
+
+    public Connector getConnector(Class objectClass)
+    {
+        return getConnector(objectClass, true);
+    }
+
+    Connector getConnector(final Class objectClass, final boolean resolveTopLevelClass)
+    {
+        ClassDescriptor cld;
+        if(objectClass != null)
+        {
+            if(resolveTopLevelClass)
+            {
+                cld = broker.getDescriptorRepository().getTopLevelDescriptor(objectClass);
+            }
+            else
+            {
+                cld = broker.getClassDescriptor(objectClass);
+            }
+            return cachingManager.getConnector(cld.getObjectCacheDescriptor());
+        }
+        return cachingManager.getConnector(null);
+    }
+
     // ************ PBStateListener methods **************
     /**
      * After committing the transaction push the object
@@ -421,6 +418,11 @@
         public void setLevel(int level)
         {
             this.level = level;
+        }
+
+        public String toString()
+        {
+            return ToStringBuilder.reflectionToString(this);
         }
     }
 }

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/cache/SessionEntry.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/cache/SessionEntry.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/cache/SessionEntry.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/cache/SessionEntry.java Fri Jan 12 10:19:39 2007
@@ -20,14 +20,14 @@
 /**
  * Wrapper object for cacheable persistent objects used by the {@link SessionCache}.
  *
- * @author <a href="mailto:[email protected]">Armin Waibel</a>
  * @version $Id$
  */
-public interface SessionEntry extends ObjectEntry
+public interface SessionEntry
 {
     public byte getType();
     public int getLevel();
     public Identity getIdentity();
     public void setType(byte type);
     public void setLevel(int level);
+    public Object getObject();
 }

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java Fri Jan 12 10:19:39 2007
@@ -21,7 +21,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.PBKey;
 import org.apache.ojb.broker.PBLifeCycleEvent;
 import org.apache.ojb.broker.PBListener;
@@ -210,6 +209,11 @@
         getBroker().delete(obj, ignoreReferences);
     }
 
+    public void delete(Object obj, Identity oid, ClassDescriptor cld, boolean ignoreReferences) throws PersistenceBrokerException
+    {
+        getBroker().delete(obj, oid, cld, ignoreReferences);
+    }
+
     public boolean isInTransaction() throws PersistenceBrokerException
     {
         return broker != null && getBroker().isInTransaction();
@@ -353,11 +357,6 @@
 		return getBroker().serviceBrokerHelper();
 	}
 
-	public ObjectCache serviceObjectCache()
-	{
-		return getBroker().serviceObjectCache();
-	}
-
     public IdentityFactory serviceIdentity()
     {
         return getBroker().serviceIdentity();
@@ -465,21 +464,21 @@
 		getBroker().deleteByQuery(query);
 	}
 
-    /**
-     * @see org.apache.ojb.broker.PersistenceBroker#deleteMtoNImplementor
-     */
-    public void deleteMtoNImplementor(MtoNImplementor m2nImpl) throws PersistenceBrokerException
-    {
-        getBroker().deleteMtoNImplementor(m2nImpl);
-    }
-
-    /**
-     * @see org.apache.ojb.broker.PersistenceBroker#addMtoNImplementor
-     */
-    public void addMtoNImplementor(MtoNImplementor m2nImpl) throws PersistenceBrokerException
-    {
-        getBroker().addMtoNImplementor(m2nImpl);
-    }
+//    /**
+//     * @see org.apache.ojb.broker.PersistenceBroker#deleteMtoNImplementor
+//     */
+//    public void deleteMtoNImplementor(MtoNImplementor m2nImpl) throws PersistenceBrokerException
+//    {
+//        getBroker().deleteMtoNImplementor(m2nImpl);
+//    }
+//
+//    /**
+//     * @see org.apache.ojb.broker.PersistenceBroker#addMtoNImplementor
+//     */
+//    public void addMtoNImplementor(MtoNImplementor m2nImpl) throws PersistenceBrokerException
+//    {
+//        getBroker().addMtoNImplementor(m2nImpl);
+//    }
     
     /*
      * (non-Javadoc)

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/core/IdentityFactoryImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/core/IdentityFactoryImpl.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/core/IdentityFactoryImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/core/IdentityFactoryImpl.java Fri Jan 12 10:19:39 2007
@@ -62,7 +62,8 @@
         doesn't improve performance.
         */
         //this.persistentIdentityMap = new ReferenceIdentityMap(ReferenceIdentityMap.WEAK, ReferenceIdentityMap.HARD, true);
-        this.transientSequenceManager = new SequenceManagerTransientImpl(broker);
+        this.transientSequenceManager = new SequenceManagerTransientImpl(
+                broker.serviceConnectionManager().getSupportedPlatform(), null);
         broker.addListener(this, true);
     }
 
@@ -94,11 +95,11 @@
             {
                 // now we are sure that the specified object is not a proxy
                 realClass = objOrProxy.getClass();
-                topLevelClass = broker.getTopLevelClass(realClass);
                 if(cld == null)
                 {
-                cld = broker.getClassDescriptor(realClass);
+                    cld = broker.getClassDescriptor(realClass);
                 }
+                topLevelClass = cld.getTopLevelClass();
                 BrokerHelper helper = broker.serviceBrokerHelper();
 
                 FieldDescriptor[] fields = cld.getPkFields();
@@ -116,7 +117,7 @@
                         result = (Identity) transientIdentityMap.get(objOrProxy);
                         if(result == null)
                         {
-                            pks[i] = transientSequenceManager.getUniqueValue(fld);
+                            pks[i] = transientSequenceManager.getUniqueValue(broker, fld);
                             result = new Identity(realClass, topLevelClass, pks, true);
                             transientIdentityMap.put(objOrProxy, result);
                         }
@@ -206,7 +207,9 @@
         return orderedValues;
     }
 
-    /** Find the index of the specified name in field name array. */
+    /**
+     * Find the index of the specified name in field name array.
+     */
     private int findIndexForName(String[] fieldNames, String searchName)
     {
         for(int i = 0; i < fieldNames.length; i++)

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/core/MtoNBroker.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/core/MtoNBroker.java?view=diff&rev=495677&r1=495676&r2=495677
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/core/MtoNBroker.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/core/MtoNBroker.java Fri Jan 12 10:19:39 2007
@@ -15,170 +15,121 @@
  * limitations under the License.
  */
 
+import java.sql.SQLException;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
-import java.sql.SQLException;
+import java.util.Collection;
+import java.util.HashSet;
 
-import org.apache.commons.lang.builder.EqualsBuilder;
 import org.apache.commons.lang.builder.HashCodeBuilder;
-import org.apache.commons.lang.builder.ToStringBuilder;
-import org.apache.commons.lang.ArrayUtils;
-import org.apache.ojb.broker.MtoNImplementor;
-import org.apache.ojb.broker.OJBRuntimeException;
 import org.apache.ojb.broker.PersistenceBrokerException;
 import org.apache.ojb.broker.PersistenceBrokerInternal;
 import org.apache.ojb.broker.PersistenceBrokerSQLException;
 import org.apache.ojb.broker.accesslayer.ResultSetAndStatement;
-import org.apache.ojb.broker.accesslayer.sql.SqlGenerator;
 import org.apache.ojb.broker.metadata.ClassDescriptor;
-import org.apache.ojb.broker.metadata.CollectionDescriptor;
-import org.apache.ojb.broker.metadata.DescriptorRepository;
 import org.apache.ojb.broker.metadata.FieldDescriptor;
-import org.apache.ojb.broker.metadata.JdbcType;
-import org.apache.ojb.broker.query.Query;
-import org.apache.ojb.broker.util.logging.Logger;
-import org.apache.ojb.broker.util.logging.LoggerFactory;
+import org.apache.ojb.broker.metadata.GenericObject;
+import org.apache.ojb.broker.metadata.IndirectionTableDescriptor;
 
 /**
  * Manage all stuff related to non-decomposed M:N association.
  *
- * @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>
- * @author <a href="mailto:[email protected]">Armin Waibel</a>
  * @version $Id$
  */
 public class MtoNBroker
 {
-    private Logger log = LoggerFactory.getLogger(MtoNBroker.class);
+    //private Logger log = LoggerFactory.getLogger(MtoNBroker.class);
 
-    private PersistenceBrokerInternal pb;
-    /**
-     * Used to store {@link GenericObject} while transaction running, used as
-     * workaround for m:n insert problem.
-     * TODO: find better solution for m:n handling
-     */
-    private List tempObjects = new ArrayList();
+    private final PersistenceBrokerInternal broker;
+    //private Collection inserted = new ArrayList();
+    private Collection inserted = new HashSet();
 
     public MtoNBroker(final PersistenceBrokerInternal broker)
     {
-        this.pb = broker;
+        this.broker = broker;
     }
 
     public void reset()
     {
-        tempObjects.clear();
+        inserted.clear();
+        //deleted.clear();
     }
 
     /**
      * Stores new values of a M:N association in a indirection table.
      *
-     * @param cod        The {@link org.apache.ojb.broker.metadata.CollectionDescriptor} for the m:n relation
-     * @param realObject The real object
-     * @param otherObj   The referenced object
-     * @param mnKeys     The all {@link org.apache.ojb.broker.core.MtoNBroker.Key} matching the real object
-     */
-    public void storeMtoNImplementor(CollectionDescriptor cod, Object realObject, Object otherObj, Collection mnKeys)
-    {
-        ClassDescriptor cld = pb.getDescriptorRepository().getDescriptorFor(realObject.getClass());
-        ValueContainer[] pkValues = pb.serviceBrokerHelper().getKeyValues(cld, realObject);
-        String[] pkColumns = cod.getFksToThisClass();
-
-        ClassDescriptor otherCld = pb.getDescriptorRepository().getDescriptorFor(pb.getProxyFactory().getRealClass(otherObj));
-        ValueContainer[] otherPkValues = pb.serviceBrokerHelper().getKeyValues(otherCld, otherObj);
-
-        String[] otherPkColumns = cod.getFksToItemClass();
-        String table = cod.getIndirectionTable();
-        MtoNBroker.Key key = new MtoNBroker.Key(otherPkValues);
-
-        if(mnKeys.contains(key))
+     * @param descriptor The {@link org.apache.ojb.broker.metadata.IndirectionTableDescriptor} for this object m:n relation
+     * @param thisObject The object associated with the specified descriptor.
+     * @param otherObj The referenced object.
+     * @param mnKeys The all {@link org.apache.ojb.broker.core.MtoNBroker.Key} already matching this object.
+     * This can be <em>null</em>.
+     */
+    public void storeIndirectionTableEntry(IndirectionTableDescriptor descriptor, Object thisObject, Object otherObj, List mnKeys)
+    {
+        ClassDescriptor otherCld = broker.getDescriptorRepository().getDescriptorFor(broker.getProxyFactory().getRealClass(otherObj));
+        ValueContainer[] otherPkValues = broker.serviceBrokerHelper().getKeyValues(otherCld, otherObj, true);
+        if(mnKeys != null && mnKeys.contains(new Key(otherPkValues)))
         {
             return;
         }
+        storeIndirectionTableEntry(descriptor, thisObject, otherObj);
+    }
 
-        /*
-        fix for OJB-76, composite M & N keys that have some fields common
-        find the "shared" indirection table columns, values and remove these from m- or n- side
-        */
-        for(int i = 0; i < otherPkColumns.length; i++)
-        {
-            int index = ArrayUtils.indexOf(pkColumns, otherPkColumns[i]);
-            if(index != -1)
-            {
-                // shared indirection table column found, remove this column from one side
-                pkColumns = (String[]) ArrayUtils.remove(pkColumns, index);
-                // remove duplicate value too
-                pkValues = (ValueContainer[]) ArrayUtils.remove(pkValues, index);
-            }
-        }
-
-        String[] cols = mergeColumns(pkColumns, otherPkColumns);
-        String insertStmt = pb.serviceSqlGenerator()
-                .getGenericPreparedStatement(SqlGenerator.TYPE_GENERIC_INSERT, table, cols, null).getStatement();
-        ValueContainer[] values = mergeContainer(pkValues, otherPkValues);
-        GenericObject gObj = new GenericObject(table, cols, values);
-        if(! tempObjects.contains(gObj))
+    /**
+     * Stores new values of a M:N association in a indirection table.
+     *
+     * @param descriptor The {@link IndirectionTableDescriptor} for this object m:n relation
+     * @param thisObject The object associated with the specified descriptor.
+     * @param otherObj The referenced object.
+     */
+    public void storeIndirectionTableEntry(IndirectionTableDescriptor descriptor, Object thisObject, Object otherObj)
+    {
+        GenericObject tableObject = descriptor.createObject(broker, thisObject, otherObj);
+        if(! inserted.contains(tableObject))
         {
-            pb.serviceJdbcAccess().executeUpdateSQL(insertStmt, values);
-            tempObjects.add(gObj);
+            broker.serviceJdbcAccess().executeInsert(descriptor, tableObject);
+            inserted.add(tableObject);
         }
     }
 
     /**
-     * get a Collection of Keys of already existing m:n rows
+     * Get a collection of {@link org.apache.ojb.broker.core.MtoNBroker.Key} instances of
+     * already existing m:n rows of the specified object.
      *
-     * @param cod
-     * @param obj
-     * @return Collection of Key
+     * @param descriptor The {@link org.apache.ojb.broker.metadata.IndirectionTableDescriptor}
+     * of the specified object.
+     * @param obj The object we search for indirection table entries.
+     * @return The {@link org.apache.ojb.broker.accesslayer.ResultSetAndStatement} of the query.
      */
-    public List getMtoNImplementor(CollectionDescriptor cod, Object obj)
+    public List getAllIndirectionTableEntries(IndirectionTableDescriptor descriptor, Object obj)
     {
         ResultSetAndStatement rs = null;
         ArrayList result = new ArrayList();
-        ClassDescriptor cld = pb.getDescriptorRepository().getDescriptorFor(obj.getClass());
-        ValueContainer[] pkValues = pb.serviceBrokerHelper().getKeyValues(cld, obj);
-        String[] pkColumns = cod.getFksToThisClass();
-        String[] fkColumns = cod.getFksToItemClass();
-        String table = cod.getIndirectionTable();
-
-        String selectStmt = pb.serviceSqlGenerator()
-                .getGenericPreparedStatement(SqlGenerator.TYPE_GENERIC_SELECT, table, fkColumns, pkColumns).getStatement();
-
-        ClassDescriptor itemCLD = cod.getItemClassDescriptor();
-        Collection extents = pb.getDescriptorRepository().getAllConcreteSubclassDescriptors(itemCLD);
-        if(extents.size() > 0)
-        {
-            itemCLD = (ClassDescriptor) extents.iterator().next();
-        }
-        FieldDescriptor[] itemClassPKFields = itemCLD.getPkFields();
-        if(itemClassPKFields.length != fkColumns.length)
+
+        ClassDescriptor otherCld = descriptor.getOtherFirstMappedDescriptor();
+        FieldDescriptor[] otherPKFields = otherCld.getPkFields();
+        if(otherPKFields.length != descriptor.getOtherColumns().length)
         {
             throw new PersistenceBrokerException("All pk fields of the element-class need to" +
                     " be declared in the indirection table. Element class is "
-                    + itemCLD.getClassNameOfObject() + " with " + itemClassPKFields.length + " pk-fields." +
+                    + otherCld.getClassNameOfObject() + " with " + otherPKFields.length + " pk-fields." +
                     " Declared 'fk-pointing-to-element-class' elements in collection-descriptor are"
-                    + fkColumns.length);
+                    + descriptor.getOtherColumns().length);
         }
         try
         {
-            rs = pb.serviceJdbcAccess().executeSQL(selectStmt, pkValues, Query.NOT_SCROLLABLE);
+            rs = descriptor.selectAllForeignKeyColumns(broker, obj);
             while(rs.m_rs.next())
             {
-                ValueContainer[] row = new ValueContainer[fkColumns.length];
+                ValueContainer[] row = new ValueContainer[descriptor.getOtherColumns().length];
                 for(int i = 0; i < row.length; i++)
                 {
-                    row[i] = new ValueContainer(rs.m_rs.getObject(i + 1), itemClassPKFields[i].getJdbcType());
+                    row[i] = new ValueContainer(rs.m_rs.getObject(i + 1), otherPKFields[i].getJdbcType());
                 }
-                result.add(new MtoNBroker.Key(row));
+                result.add(new Key(row));
             }
         }
-        catch(PersistenceBrokerException e)
-        {
-            throw e;
-        }
         catch(SQLException e)
         {
             throw new PersistenceBrokerSQLException(e);
@@ -191,201 +142,79 @@
     }
 
     /**
-     * delete all rows from m:n table belonging to obj
-     *
-     * @param cod
-     * @param obj
+     * Delete all rows in the m:n indirection table belonging to the specified object.
      */
-    public void deleteMtoNImplementor(CollectionDescriptor cod, Object obj)
+    public int deleteAllIndirectionTableEntries(IndirectionTableDescriptor descriptor, Object obj)
     {
-        ClassDescriptor cld = pb.getDescriptorRepository().getDescriptorFor(obj.getClass());
-        ValueContainer[] pkValues = pb.serviceBrokerHelper().getKeyValues(cld, obj);
-        String[] pkColumns = cod.getFksToThisClass();
-        String table = cod.getIndirectionTable();
-        String deleteStmt = pb.serviceSqlGenerator()
-                .getGenericPreparedStatement(SqlGenerator.TYPE_GENERIC_DELETE, table, null, pkColumns).getStatement();
-        pb.serviceJdbcAccess().executeUpdateSQL(deleteStmt, pkValues);
+        return descriptor.deleteAllIndirectionTableEntries(broker, obj);
     }
 
     /**
-     * deletes all rows from m:n table that are not used in relatedObjects
+     * Deletes all rows from m:n table that are not used in related objects.
      *
-     * @param cod
-     * @param obj
-     * @param collectionIterator
-     * @param mnKeys
+     * @param descriptor The indirection table descriptor.
+     * @param obj The source object.
+     * @param collectionIterator The iterator of all related objects of the source object.
+     * @param mnKeys All related indirection table entries of the source object found in database.
      */
-    public void deleteMtoNImplementor(CollectionDescriptor cod, Object obj, Iterator collectionIterator, Collection mnKeys)
+    public void deleteAllNotMatchedIndirectionTableEntries(IndirectionTableDescriptor descriptor,
+                                                           Object obj, Iterator collectionIterator, List mnKeys)
     {
         if(mnKeys.isEmpty() || collectionIterator == null)
         {
             return;
         }
         List workList = new ArrayList(mnKeys);
-        MtoNBroker.Key relatedObjKeys;
-        ClassDescriptor relatedCld = pb.getDescriptorRepository().getDescriptorFor(cod.getItemClass());
         Object relatedObj;
-
         // remove keys of relatedObject from the existing m:n rows in workList
         while(collectionIterator.hasNext())
         {
             relatedObj = collectionIterator.next();
-            relatedObjKeys = new MtoNBroker.Key(pb.serviceBrokerHelper().getKeyValues(relatedCld, relatedObj, true));
-            workList.remove(relatedObjKeys);
+            workList.remove(new Key(
+                    broker.serviceBrokerHelper().getKeyValues(
+                            descriptor.getOtherFirstMappedDescriptor(),
+                            relatedObj, true)));
         }
 
         // delete all remaining keys in workList
-        ClassDescriptor cld = pb.getDescriptorRepository().getDescriptorFor(obj.getClass());
-        ValueContainer[] pkValues = pb.serviceBrokerHelper().getKeyValues(cld, obj);
-
-        String[] pkColumns = cod.getFksToThisClass();
-        String[] fkColumns = cod.getFksToItemClass();
-        String table = cod.getIndirectionTable();
-        String deleteStmt;
-
-        String[] columns = mergeColumns(pkColumns, fkColumns);
+        ValueContainer[] pkValues = broker.serviceBrokerHelper().getKeyValues(
+                descriptor.getThisClassDescriptor(), obj, true);
         ValueContainer[] fkValues;
         Iterator iter = workList.iterator();
         while(iter.hasNext())
         {
-            fkValues = ((MtoNBroker.Key) iter.next()).m_containers;
-            deleteStmt = pb.serviceSqlGenerator()
-                    .getGenericPreparedStatement(SqlGenerator.TYPE_GENERIC_DELETE, table, null, columns).getStatement();
-            pb.serviceJdbcAccess().executeUpdateSQL(deleteStmt, mergeContainer(pkValues, fkValues));
+            fkValues = ((Key) iter.next()).values;
+            GenericObject genObj = descriptor.createObject(broker, pkValues, fkValues);
+            deleteIndirectionTableEntry(descriptor, genObj);
         }
     }
 
-    /**
-     * @param m2n
-     */
-    public void storeMtoNImplementor(MtoNImplementor m2n)
+    public void deleteIndirectionTableEntry(IndirectionTableDescriptor thisDescriptor, Object thisObject, Object otherObject)
     {
-        if(log.isDebugEnabled()) log.debug("Storing M2N implementor [" + m2n + "]");
-        insertOrDeleteMtoNImplementor(m2n, true);
+        GenericObject toDel = thisDescriptor.createObject(broker, thisObject, otherObject);
+        deleteIndirectionTableEntry(thisDescriptor, toDel);
     }
 
-    /**
-     * @param m2n
-     */
-    public void deleteMtoNImplementor(MtoNImplementor m2n)
-    {
-        if(log.isDebugEnabled()) log.debug("Deleting M2N implementor [" + m2n + "]");
-        insertOrDeleteMtoNImplementor(m2n, false);
-    }
-
-
-    /**
-     * @see org.apache.ojb.broker.PersistenceBroker#deleteMtoNImplementor
-     */
-    private void insertOrDeleteMtoNImplementor(MtoNImplementor m2nImpl, boolean insert)
-            throws PersistenceBrokerException
-    {
-        //look for a collection descriptor on left  such as left.element-class-ref='right'
-        DescriptorRepository dr = pb.getDescriptorRepository();
-
-        Object leftObject = m2nImpl.getLeftObject();
-        Class leftClass = m2nImpl.getLeftClass();
-        Object rightObject = m2nImpl.getRightObject();
-        Class rightClass = m2nImpl.getRightClass();
-
-        //are written per class, maybe referencing abstract classes or interfaces
-        //so let's look for collection descriptors on the left class and try to
-        // handle extents on teh right class
-        ClassDescriptor leftCld = dr.getDescriptorFor(leftClass);
-        ClassDescriptor rightCld = dr.getDescriptorFor(rightClass);
-        //Vector leftColds = leftCld.getCollectionDescriptors();
-        CollectionDescriptor wanted = m2nImpl.getLeftDescriptor();
-
-        if(leftObject == null || rightObject == null)
-        {
-            //TODO: to be implemented, must change MtoNImplementor
-            //deleteMtoNImplementor(wanted,leftObject) || deleteMtoNImplementor(wanted,rightObject)
-            log.error("Can't handle MtoNImplementor in correct way, found a 'null' object");
-        }
-        else
-        {
-            //delete only one row
-            ValueContainer[] leftPkValues = pb.serviceBrokerHelper().getKeyValues(leftCld, leftObject);
-            ValueContainer[] rightPkValues = pb.serviceBrokerHelper().getKeyValues(rightCld, rightObject);
-            String[] pkLeftColumns = wanted.getFksToThisClass();
-            String[] pkRightColumns = wanted.getFksToItemClass();
-            String table = wanted.getIndirectionTable();
-            if(table == null) throw new PersistenceBrokerException("Can't remove MtoN implementor without an indirection table");
-
-            String stmt;
-            String[] cols = mergeColumns(pkLeftColumns, pkRightColumns);
-            ValueContainer[] values = mergeContainer(leftPkValues, rightPkValues);
-            if(insert)
-            {
-                stmt = pb.serviceSqlGenerator()
-                        .getGenericPreparedStatement(SqlGenerator.TYPE_GENERIC_INSERT, table, cols, null).getStatement();
-                GenericObject gObj = new GenericObject(table, cols, values);
-                if(!tempObjects.contains(gObj))
-                {
-                    pb.serviceJdbcAccess().executeUpdateSQL(stmt, values);
-                    tempObjects.add(gObj);
-                }
-            }
-            else
-            {
-                stmt = pb.serviceSqlGenerator()
-                        .getGenericPreparedStatement(SqlGenerator.TYPE_GENERIC_DELETE, table, null, cols).getStatement();
-                pb.serviceJdbcAccess().executeUpdateSQL(stmt, values);
-            }
-        }
-    }
-
-    private String[] mergeColumns(String[] first, String[] second)
-    {
-        String[] cols = new String[first.length + second.length];
-        System.arraycopy(first, 0, cols, 0, first.length);
-        System.arraycopy(second, 0, cols, first.length, second.length);
-        return cols;
-    }
-
-    private ValueContainer[] mergeContainer(ValueContainer[] first, ValueContainer[] second)
+    public void deleteIndirectionTableEntry(IndirectionTableDescriptor thisDescriptor, GenericObject genObj)
     {
-        ValueContainer[] values = new ValueContainer[first.length + second.length];
-        System.arraycopy(first, 0, values, 0, first.length);
-        System.arraycopy(second, 0, values, first.length, second.length);
-        return values;
+        broker.serviceJdbcAccess().executeDelete(thisDescriptor, genObj);
+        inserted.remove(genObj);
     }
 
-
-
-// ************************************************************************
-// inner class
-// ************************************************************************
+    // ************************************************************************
+    // inner class
+    // ************************************************************************
 
     /**
      * This is a helper class to model a Key of an Object
      */
     private static final class Key
     {
-        final ValueContainer[] m_containers;
+        final ValueContainer[] values;
 
         Key(final ValueContainer[] containers)
         {
-            m_containers = new ValueContainer[containers.length];
-
-            for(int i = 0; i < containers.length; i++)
-            {
-                Object value = containers[i].getValue();
-                JdbcType type = containers[i].getJdbcType();
-
-                // BRJ:
-                // convert all Numbers to Long to simplify equals
-                // Long(100) is not equal to Integer(100)
-                //
-                // could lead to problems when Floats are used as key
-                // converting to String could be a better alternative
-                if(value instanceof Number)
-                {
-                    value = new Long(((Number) value).longValue());
-                }
-
-                m_containers[i] = new ValueContainer(value, type);
-            }
+            values = containers;
         }
 
         public boolean equals(Object other)
@@ -394,141 +223,30 @@
             {
                 return true;
             }
-            if(!(other instanceof Key))
-            {
-                return false;
-            }
-
-            Key otherKey = (Key) other;
-            EqualsBuilder eb = new EqualsBuilder();
-
-            eb.append(m_containers, otherKey.m_containers);
-            return eb.isEquals();
-        }
-
-        public int hashCode()
-        {
-            HashCodeBuilder hb = new HashCodeBuilder();
-            hb.append(m_containers);
-
-            return hb.toHashCode();
-        }
-    }
-
-
-
-    // ************************************************************************
-    // inner class
-    // ************************************************************************
-    private static final class GenericObject
-    {
-        private String tablename;
-        private String[] columnNames;
-        private ValueContainer[] values;
-
-        public GenericObject(String tablename, String[] columnNames, ValueContainer[] values)
-        {
-            this.tablename = tablename;
-            this.columnNames = columnNames;
-            this.values = values;
-            if(values != null && columnNames.length != values.length)
-            {
-                throw new OJBRuntimeException("Column name array and value array have NOT same length");
-            }
-        }
-
-        public boolean equals(Object obj)
-        {
-            if(this == obj)
-            {
-                return true;
-            }
-            boolean result = false;
-            if(obj instanceof GenericObject)
+            boolean result = true;
+            if(other instanceof Key)
             {
-                GenericObject other = (GenericObject) obj;
-                result = (tablename.equalsIgnoreCase(other.tablename)
-                        && (columnNames != null)
-                        && (other.columnNames != null)
-                        && (columnNames.length == other.columnNames.length));
-
-                if(result)
+                ValueContainer[] otherValues = ((Key) other).values;
+                for(int i = 0; i < otherValues.length; i++)
                 {
-                    for (int i = 0; i < columnNames.length; i++)
+                    ValueContainer otherValue = otherValues[i];
+                    if(!otherValue.equals(values[i]))
                     {
-                        int otherIndex = other.indexForColumn(columnNames[i]);
-                        if(otherIndex < 0)
-                        {
-                            result = false;
-                            break;
-                        }
-                        result = values[i].equals(other.values[otherIndex]);
-                        if(!result) break;
+                        result = false;
+                        break;
                     }
                 }
             }
-            return result;
-        }
-
-        int indexForColumn(String name)
-        {
-            int result = -1;
-            for (int i = 0; i < columnNames.length; i++)
+            else
             {
-                if(columnNames[i].equals(name))
-                {
-                    result = i;
-                    break;
-                }
+                result = false;
             }
             return result;
         }
 
         public int hashCode()
         {
-            return super.hashCode();
-        }
-
-        public ValueContainer getValueFor(String columnName)
-        {
-            try
-            {
-                return values[indexForColumn(columnName)];
-            }
-            catch(Exception e)
-            {
-                throw new OJBRuntimeException("Can't find value for column " + columnName
-                        + (indexForColumn(columnName) < 0 ? ". Column name was not found" : ""), e);
-            }
-        }
-
-        public String getTablename()
-        {
-            return tablename;
-        }
-
-        public String[] getColumnNames()
-        {
-            return columnNames;
-        }
-
-        public ValueContainer[] getValues()
-        {
-            return values;
-        }
-
-        public void setValues(ValueContainer[] values)
-        {
-            this.values = values;
-        }
-
-        public String toString()
-        {
-            return new ToStringBuilder(this)
-                    .append("tableName", tablename)
-                    .append("columnNames", columnNames)
-                    .append("values", values)
-                    .toString();
+            return new HashCodeBuilder().append(values).toHashCode();
         }
     }
 }
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.