Author: tv
Date: Tue Feb  2 15:27:42 2016
New Revision: 1728149

URL: http://svn.apache.org/viewvc?rev=1728149&view=rev
Log:
Simplify managers

Modified:
    
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/AbstractBaseManager.java
    
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/CacheListener.java
    
db/torque/torque4/trunk/torque-runtime/src/test/java/org/apache/torque/manager/AbstractBaseManagerTest.java

Modified: 
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/AbstractBaseManager.java
URL: 
http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/AbstractBaseManager.java?rev=1728149&r1=1728148&r2=1728149&view=diff
==============================================================================
--- 
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/AbstractBaseManager.java
 (original)
+++ 
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/AbstractBaseManager.java
 Tue Feb  2 15:27:42 2016
@@ -22,15 +22,16 @@ package org.apache.torque.manager;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.Serializable;
-import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CopyOnWriteArraySet;
 
-import org.apache.commons.collections.FastArrayList;
 import org.apache.commons.jcs.JCS;
 import org.apache.commons.jcs.access.CacheAccess;
 import org.apache.commons.jcs.access.GroupCacheAccess;
@@ -82,11 +83,11 @@ public abstract class AbstractBaseManage
     private boolean isNew = true;
 
     /** The fields which are valid fields of interest for a listener. */
-    protected Map<Column, ?> validFields;
+    private CopyOnWriteArraySet<Column> validFields = new 
CopyOnWriteArraySet<Column>();
 
     /** The listeners for this manager. */
-    protected Map<Column, FastArrayList> listenersMap
-        = new HashMap<Column, FastArrayList>();
+    protected ConcurrentMap<Column, CopyOnWriteArrayList<CacheListener<?>>> 
listenersMap =
+        new ConcurrentHashMap<Column, 
CopyOnWriteArrayList<CacheListener<?>>>();
 
     /**
      * Get the Class instance
@@ -109,6 +110,16 @@ public abstract class AbstractBaseManage
     }
 
     /**
+     * Add variable number of  fields to the list potentially monitored by a 
listener
+     *
+     * @param columns array of columns
+     */
+    protected void addValidField(Column ...columns)
+    {
+        this.validFields.addAll(Arrays.asList(columns));
+    }
+
+    /**
      * Get a fresh instance of an om
      *
      * @return an instance of the om class
@@ -259,7 +270,7 @@ public abstract class AbstractBaseManage
     }
 
     /**
-     * Disposes of the cache. This triggers a shutdown of the connected cache
+     * Disposes of the manager. This triggers a shutdown of the connected cache
      * instances. This method should only be used during shutdown of Torque. 
The
      * manager instance will not cache anymore after this call.
      */
@@ -276,6 +287,9 @@ public abstract class AbstractBaseManage
             groupCache.dispose();
             groupCache = null;
         }
+
+        validFields.clear();
+        listenersMap.clear();
     }
 
     /**
@@ -357,12 +371,12 @@ public abstract class AbstractBaseManage
     /**
      * Gets a list of om's based on id's.
      *
-     * @param ids a <code>ObjectKey[]</code> value
-     * @return a <code>List</code> value
+     * @param ids a number of object ids
+     * @return a <code>List</code> of objects
      * @throws TorqueException Any exceptions caught during processing will be
      *         rethrown wrapped into a TorqueException.
      */
-    protected List<T> getOMs(final ObjectKey[] ids)
+    protected List<T> getOMs(final ObjectKey ...ids)
         throws TorqueException
     {
         return getOMs(Arrays.asList(ids));
@@ -508,6 +522,8 @@ public abstract class AbstractBaseManage
     }
 
     /**
+     * Get the object usable for result caching
+     *
      * @return The cache instance.
      */
     public synchronized MethodResultCache getMethodResultCache()
@@ -530,110 +546,63 @@ public abstract class AbstractBaseManage
     }
 
     /**
+     * Add a new listener
      *
      * @param listener A new listener for cache events.
      */
-    public void addCacheListenerImpl(
-            final CacheListener<? extends Persistent> listener)
+    public void addCacheListenerImpl(final CacheListener<?> listener)
     {
-        List<Column> keys = listener.getInterestedFields();
-        for (Column key : keys)
+        for (Column key : listener.getInterestedFields())
         {
             // Peer.column names are the fields
-            if (validFields != null && validFields.containsKey(key))
+            if (validFields.contains(key))
             {
-                FastArrayList listeners = listenersMap.get(key);
+                CopyOnWriteArrayList<CacheListener<?>> newList = new 
CopyOnWriteArrayList<CacheListener<?>>();
+                CopyOnWriteArrayList<CacheListener<?>> listeners = 
listenersMap.putIfAbsent(key, newList);
+
                 if (listeners == null)
                 {
-                    listeners = createSubsetList(key);
+                    listeners = newList;
                 }
 
-                boolean isListenerNew = true;
-                Iterator<?> j = listeners.iterator();
-                while (j.hasNext())
-                {
-                    Object listener2 =
-                        ((WeakReference<?>) j.next()).get();
-//                    if (listener2 == null)
-//                    {
-//                        // do a little cleanup while checking for dupes
-//                        // not thread-safe, not likely to be many nulls
-//                        // but should revisit
-//                        //j.remove();
-//                    }
-//                    else
-                    if (listener2 == listener)
-                    {
-                        isListenerNew = false;
-                        break;
-                    }
-                }
-                if (isListenerNew)
-                {
-                    listeners.add(new WeakReference<CacheListener<? extends 
Persistent>>(listener));
-                }
+                listeners.addIfAbsent(listener);
             }
         }
     }
 
     /**
+     * Notify all listeners in the list that an object has changed
      *
-     * @param key
-     * @return A subset of the list identified by <code>key</code>.
-     */
-    private synchronized FastArrayList createSubsetList(final Column key)
-    {
-        FastArrayList list = null;
-        if (listenersMap.containsKey(key))
-        {
-            list = listenersMap.get(key);
-        }
-        else
-        {
-            list = new FastArrayList();
-            list.setFast(true);
-            listenersMap.put(key, list);
-        }
-        return list;
-    }
-
-    /**
-     *
-     * @param listeners
-     * @param oldOm
-     * @param om
+     * @param listeners the list of listeners
+     * @param oldOm the previous object, null if the object has been added
+     * @param om the new object, null if the object has been removed
      */
     protected <TT extends Persistent> void notifyListeners(
-            final List<WeakReference<CacheListener<TT>>> listeners,
+            final List<CacheListener<?>> listeners,
             final TT oldOm,
             final TT om)
     {
         if (listeners != null)
         {
-            synchronized (listeners)
+            for (CacheListener<?> cl : listeners)
             {
-                Iterator<WeakReference<CacheListener<TT>>> i = 
listeners.iterator();
-                while (i.hasNext())
+                @SuppressWarnings("unchecked")
+                CacheListener<TT> listener = (CacheListener<TT>) cl;
+
+                if (oldOm == null)
                 {
-                    CacheListener<TT> listener = i.next().get();
-                    if (listener == null)
-                    {
-                        // remove reference as its object was cleared
-                        i.remove();
-                    }
-                    else
-                    {
-                        if (oldOm == null)
-                        {
-                            // object was added
-                            listener.addedObject(om);
-                        }
-                        else
-                        {
-                            // object was refreshed
-                            listener.refreshedObject(om);
-                        }
-                    }
+                    // object was added
+                    listener.addedObject(om);
+                }
+                else if (om == null)
+                {
+                    // object was removed
+                    listener.removedObject(om);
+                }
+                else
+                {
+                    // object was refreshed
+                    listener.refreshedObject(om);
                 }
             }
         }

Modified: 
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/CacheListener.java
URL: 
http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/CacheListener.java?rev=1728149&r1=1728148&r2=1728149&view=diff
==============================================================================
--- 
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/CacheListener.java
 (original)
+++ 
db/torque/torque4/trunk/torque-runtime/src/main/java/org/apache/torque/manager/CacheListener.java
 Tue Feb  2 15:27:42 2016
@@ -34,21 +34,30 @@ import org.apache.torque.om.Persistent;
 public interface CacheListener<T extends Persistent>
 {
     /**
+     * Notify listener that an object has been added to the database
      *
-     * @param om
+     * @param om the object
      */
     void addedObject(T om);
 
     /**
+     * Notify listener that an object has been modified
      *
-     * @param om
+     * @param om the object
      */
     void refreshedObject(T om);
 
-    //public void removedObject(T om);
+    /**
+     * Notify listener that an object has been removed from the database
+     *
+     * @param om the object
+     */
+    void removedObject(T om);
 
     /**
+     * Get the list of fields we are listening for
      *
+     * @return a list of fields, not null
      */
     List<Column> getInterestedFields();
 }

Modified: 
db/torque/torque4/trunk/torque-runtime/src/test/java/org/apache/torque/manager/AbstractBaseManagerTest.java
URL: 
http://svn.apache.org/viewvc/db/torque/torque4/trunk/torque-runtime/src/test/java/org/apache/torque/manager/AbstractBaseManagerTest.java?rev=1728149&r1=1728148&r2=1728149&view=diff
==============================================================================
--- 
db/torque/torque4/trunk/torque-runtime/src/test/java/org/apache/torque/manager/AbstractBaseManagerTest.java
 (original)
+++ 
db/torque/torque4/trunk/torque-runtime/src/test/java/org/apache/torque/manager/AbstractBaseManagerTest.java
 Tue Feb  2 15:27:42 2016
@@ -20,7 +20,6 @@ package org.apache.torque.manager;
  */
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 
 import junit.framework.TestCase;
@@ -42,6 +41,7 @@ public class AbstractBaseManagerTest ext
 
        private boolean addedObjectCalled;
        private boolean refreshedObjectCalled;
+    private boolean removedObjectCalled;
 
        static
        {
@@ -69,7 +69,13 @@ public class AbstractBaseManagerTest ext
                this.refreshedObjectCalled = true;
        }
 
-       @Override
+    @Override
+    public void removedObject(TestPersistent om)
+    {
+        this.removedObjectCalled = true;
+    }
+
+    @Override
     public List<Column> getInterestedFields()
        {
            List<Column> columnList = new ArrayList<Column>(2);
@@ -172,24 +178,34 @@ public class AbstractBaseManagerTest ext
                assertNotNull("Should have MethodResultCache", mrc);
        }
 
-       @SuppressWarnings("unchecked")
        public void testListeners()
        {
-               manager.validFields = new HashMap<Column, Object>();
-               manager.validFields.put(new ColumnImpl("test1"), null);
-               manager.validFields.put(new ColumnImpl("test2"), null);
+               manager.addValidField(new ColumnImpl("test1"), new 
ColumnImpl("test2"));
                manager.addCacheListenerImpl(this);
                this.addedObjectCalled = false;
                this.refreshedObjectCalled = false;
+        this.removedObjectCalled = false;
                TestPersistent test1 = new TestPersistent();
                TestPersistent test2 = new TestPersistent();
                manager.notifyListeners(manager.listenersMap.get(new 
ColumnImpl("test1")), (TestPersistent)null, test1);
                assertTrue("Should call addedObject", addedObjectCalled);
                assertFalse("Should not call refreshedObject", 
refreshedObjectCalled);
+        assertFalse("Should not call removedObject", removedObjectCalled);
+
                this.addedObjectCalled = false;
                this.refreshedObjectCalled = false;
+        this.removedObjectCalled = false;
                manager.notifyListeners(manager.listenersMap.get(new 
ColumnImpl("test2")), test2, test1);
                assertFalse("Should not call addedObject", addedObjectCalled);
                assertTrue("Should call refreshedObject", 
refreshedObjectCalled);
+        assertFalse("Should not call removedObject", removedObjectCalled);
+
+        this.addedObjectCalled = false;
+        this.refreshedObjectCalled = false;
+        this.removedObjectCalled = false;
+        manager.notifyListeners(manager.listenersMap.get(new 
ColumnImpl("test2")), test2, null);
+        assertFalse("Should not call addedObject", addedObjectCalled);
+        assertFalse("Should not call refreshedObject", refreshedObjectCalled);
+        assertTrue("Should call removedObject", removedObjectCalled);
        }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: torque-dev-unsubscr...@db.apache.org
For additional commands, e-mail: torque-dev-h...@db.apache.org

Reply via email to