[Arakhnę-Dev] [33] Reimplement AbstractWeakSoftValueMap to avoid exceptions.

[ Thread Index | Date Index | More arakhne.org/dev Archives ]


Revision: 33
Author:   galland
Date:     2009-02-03 13:37:00 +0100 (Tue, 03 Feb 2009)

Log Message:
-----------
Reimplement AbstractWeakSoftValueMap to avoid exceptions.

Modified Paths:
--------------
    trunk/arakhneRefs/src/main/java/org/arakhne/util/ref/AbstractWeakSoftValueMap.java
    trunk/arakhneRefs/src/main/resources/Changelog
    trunk/arakhneRefs/src/main/resources/VERSION
    trunk/arakhneRefs/src/test/java/org/arakhne/util/ref/WeakValueMapTest.java
    trunk/pom.xml


Modified: trunk/arakhneRefs/src/main/java/org/arakhne/util/ref/AbstractWeakSoftValueMap.java
===================================================================
--- trunk/arakhneRefs/src/main/java/org/arakhne/util/ref/AbstractWeakSoftValueMap.java	2009-02-03 09:58:11 UTC (rev 32)
+++ trunk/arakhneRefs/src/main/java/org/arakhne/util/ref/AbstractWeakSoftValueMap.java	2009-02-03 12:37:00 UTC (rev 33)
@@ -23,13 +23,11 @@
 
 import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
-import java.lang.ref.WeakReference;
 import java.util.AbstractMap;
-import java.util.AbstractSet;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
-import java.util.NoSuchElementException;
 import java.util.Set;
 
 /**
@@ -83,7 +81,6 @@
 	private boolean autoExpurge = false;
 	private final HashMap<K,WeakSoftValue<K,V>> map;
 	private final ReferenceQueue<V> queue = new ReferenceQueue<V>();
-	private final EntrySet entrySet;
 
     /**
      * Constructs an empty <tt>HashMap</tt> with the specified initial
@@ -96,7 +93,6 @@
      */
     public AbstractWeakSoftValueMap(int initialCapacity, float loadFactor) {
         this.map = new HashMap<K,WeakSoftValue<K,V>>(initialCapacity, loadFactor);
-        this.entrySet = new EntrySet();
     }
 
     /**
@@ -108,7 +104,6 @@
      */
     public AbstractWeakSoftValueMap(int initialCapacity) {
         this.map = new HashMap<K,WeakSoftValue<K,V>>(initialCapacity);
-        this.entrySet = new EntrySet();
     }
 
     /**
@@ -117,7 +112,6 @@
      */
     public AbstractWeakSoftValueMap() {
         this.map = new HashMap<K,WeakSoftValue<K,V>>();
-        this.entrySet = new EntrySet();
     }
 
     /**
@@ -131,7 +125,6 @@
      */
     public AbstractWeakSoftValueMap(Map<? extends K, ? extends V> m) {
         this.map = new HashMap<K,WeakSoftValue<K,V>>();
-        this.entrySet = new EntrySet();
         putAll(m);
     }	
 
@@ -222,6 +215,17 @@
 	 */
 	protected abstract WeakSoftValue<K,V> makeValue(K k, V v, ReferenceQueue<V> queue);
 
+	/** Create a storage object that permits to put the specified
+	 * elements inside this map.
+	 * 
+	 * @param k is the key associated to the value
+	 * @param v is the value
+	 * @return the new storage object
+	 */
+	protected final WeakSoftValue<K,V> makeValue(K k, V v) {
+		return makeValue(k, v, this.queue);
+	}
+
 	/**
      * {@inheritDoc}
      */
@@ -239,7 +243,7 @@
 	@Override
 	public final Set<Entry<K,V>> entrySet() {
 		expurgeNow();
-		return this.entrySet;
+		return new InnerEntrySet();
 	}	
 		
     /**
@@ -259,100 +263,233 @@
     	expurgeNow();
     	return hashCode();
     }
+        
+	/**
+	 * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+	 * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
+	 */
+	protected interface WeakSoftValue<K,V> extends Entry<K,V> {
+		
+		/**
+		 * @return if the value is enqueued into a reference queue.
+		 */
+		public boolean isEnqueued();
+		
+		/**
+		 * @return the weak/soft reference.
+		 */
+		public V get();
 
-    /**
+		/**
+		 * @return if the value was enqueued
+		 */
+		public boolean enqueue();
+
+		/**
+		 */
+		public void clear();
+
+	}
+
+	/**
 	 * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
 	 * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
 	 */
-	private class RealEntry implements Entry<K,V> {
+	@SuppressWarnings("synthetic-access")
+	private class InnerEntrySet implements Set<Entry<K,V>> {
 
-		private final WeakReference<WeakSoftValue<K,V>> realEntry;
-		private final K key;
-		private V value;
-		
-		public RealEntry(WeakSoftValue<K,V> rEntry, V rValue) {
-			this.value = rValue;
-			this.key = rEntry.getKey();
-			this.realEntry = new WeakReference<WeakSoftValue<K,V>>(rEntry);
+		public InnerEntrySet() {
+			//
 		}
-		
+
 		@Override
-		public K getKey() {
-			return this.key;
+		public final boolean add(java.util.Map.Entry<K, V> e) {
+			K key = e.getKey();
+			V value = e.getValue();
+			return AbstractWeakSoftValueMap.this.map.put(key,
+					makeValue(key, value)) == null;
 		}
 
 		@Override
-		public V getValue() {
-			return this.value;
+		public final boolean addAll(Collection<? extends java.util.Map.Entry<K, V>> c) {
+			boolean ok = true;
+			for(java.util.Map.Entry<K, V> entry : c) {
+				ok = add(entry) && ok;
+			}
+			return ok;
 		}
 
 		@Override
-		public V setValue(V value) {
-			V oldValue = this.value;
-			
-			this.value = value;
-			
-			WeakSoftValue<K,V> rEntry = this.realEntry.get();
-			
-			if (rEntry!=null) {
-				if (value==null) rEntry.clear();
-				else rEntry.setValue(value);
+		public final void clear() {
+			AbstractWeakSoftValueMap.this.map.clear();
+		}
+
+		@Override
+		public final boolean contains(Object o) {
+			if (o instanceof Entry) {
+				try {
+					expurgeNow();
+					return AbstractWeakSoftValueMap.this.map.containsKey(((Entry<?,?>)o).getKey());
+				}
+				catch(Throwable _) {
+					//
+				}
 			}
+			return false;
+		}
+
+		@Override
+		public final boolean containsAll(Collection<?> c) {
+			boolean ok;
+			expurgeNow();
+			for(Object o : c) {
+				ok = false;
+				if (o instanceof Entry) {
+					try {
+						ok = AbstractWeakSoftValueMap.this.map.containsKey(((Entry<?,?>)o).getKey());
+					}
+					catch(Throwable _) {
+						//
+					}
+				}
+				if (!ok) return false;
+			}
+			return true;
+		}
+
+		@Override
+		public final boolean isEmpty() {
+			expurgeNow();
+			return AbstractWeakSoftValueMap.this.map.isEmpty();
+		}
+
+		@Override
+		public final Iterator<java.util.Map.Entry<K, V>> iterator() {
+			return new InnerIterator();
+		}
+
+		@Override
+		public final boolean remove(Object o) {
+			if (o instanceof Entry) {
+				try {
+					return AbstractWeakSoftValueMap.this.map.remove(((Entry<?,?>)o).getKey())!=null;
+				}
+				catch(Throwable _) {
+					//
+				}
+			}
+			return false;
+		}
+
+		@Override
+		public final boolean removeAll(Collection<?> c) {
+			boolean ok = true;
+			for(Object o : c) {
+				ok = remove(o) && ok;
+			}
+			return ok;
+		}
+
+		@Override
+		public final boolean retainAll(Collection<?> c) {
+			expurgeNow();
+			Collection<K> keys = AbstractWeakSoftValueMap.this.map.keySet();
+			Iterator<K> iterator = keys.iterator();
+			K key;
+			boolean changed = false;
+			while (iterator.hasNext()) {
+				key = iterator.next();
+				if (!c.contains(key)) {
+					iterator.remove();
+					changed = true;
+				}
+			}
+			return changed;
+		}
+
+		@Override
+		public final int size() {
+			expurgeNow();
+			return AbstractWeakSoftValueMap.this.map.size();
+		}
+
+		@Override
+		public final Object[] toArray() {
+			expurgeNow();
+			Object[] tab = new Object[AbstractWeakSoftValueMap.this.map.size()];
+			return toArray(tab);
+		}
+
+		@SuppressWarnings("unchecked")
+		@Override
+		public final <T> T[] toArray(T[] a) {
+			Entry[] tab;
+			expurgeNow();
+			int count = AbstractWeakSoftValueMap.this.map.size();
+			if (a==null || a.length<count) {
+				tab = new Entry[count];
+			}
+			else {
+				tab = (Entry[])a;
+			}
+
+			Iterator<java.util.Map.Entry<K, V>> iterator = iterator();
+			int i = 0;
+			while (i<tab.length && iterator.hasNext()) {
+				tab[i] = iterator.next();
+			}
 			
-			return oldValue;
+			return (T[])tab;
 		}
 		
 	}
-
+	
 	/**
 	 * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
 	 * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
 	 */
-	private class EntrySetIterator implements Iterator<Entry<K,V>> {
+	private class InnerIterator implements Iterator<Entry<K,V>> {
+
+		private final Iterator<Entry<K,WeakSoftValue<K,V>>> originalIterator;
+		private Entry<K,V> next;
 		
-		private final Iterator<Entry<K,WeakSoftValue<K,V>>> iter;
-		private RealEntry lastReplied;
-		private RealEntry next;
-		
-		public EntrySetIterator(Iterator<Entry<K,WeakSoftValue<K,V>>> iter) {
-			this.iter = iter;
-			expurgeNow();
-			this.lastReplied = null;
+		@SuppressWarnings("synthetic-access")
+		public InnerIterator() {
+			this.originalIterator = AbstractWeakSoftValueMap.this.map.entrySet().iterator();
 			this.next = searchNext();
 		}
 		
-		private RealEntry searchNext() {
-			Entry<K,WeakSoftValue<K,V>> entry;
-			WeakSoftValue<K,V> val;
-			V value;
-			while (this.iter.hasNext()) {
-				entry = this.iter.next();
-				if (entry==null) throw new NoSuchElementException();
-				val = entry.getValue();
-				if (val==null) throw new NoSuchElementException();
-				value = val.getValue();
-				if (value!=null) {
-					return new RealEntry(val, value);
+		private Entry<K,V> searchNext() {
+			Entry<K,WeakSoftValue<K,V>> originalNext;
+			WeakSoftValue<K,V> wValue;
+			Entry<K,V> next = null;
+			while (next==null && this.originalIterator.hasNext()) {
+				originalNext = this.originalIterator.next();
+				if (originalNext!=null) {
+					wValue = originalNext.getValue();
+					if (wValue!=null) {
+						next = new InnerEntry(wValue.getValue(), originalNext);
+					}
 				}
 			}
-			return null;
+			return next;
 		}
 		
-		public boolean hasNext() { 
-			this.lastReplied = null;
-			return (this.next!=null); 
+		@Override
+		public boolean hasNext() {
+			return this.next!=null;
 		}
-		
-		public Entry<K,V> next() {
-			this.lastReplied = this.next;
-			if (this.lastReplied==null) throw new NoSuchElementException();
+
+		@Override
+		public java.util.Map.Entry<K, V> next() {
+			Entry<K,V> next = this.next;
 			this.next = searchNext();
-			return this.lastReplied;
+			return next;
 		}
-		
+
+		@Override
 		public void remove() {
-			if (this.lastReplied==null) throw new NoSuchElementException();
-			this.lastReplied.setValue(null);
+			this.originalIterator.remove();
 		}
 		
 	}
@@ -361,65 +498,32 @@
 	 * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
 	 * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
 	 */
-	private class EntrySet extends AbstractSet<Entry<K,V>> implements Set<Entry<K,V>> {
+	private class InnerEntry implements Entry<K,V> {
+
+		private final Entry<K,WeakSoftValue<K,V>> original;
+		private V value;
 		
-		/**
-		 *
-		 */
-		public EntrySet() {
-			//
+		public InnerEntry(V v, Entry<K,WeakSoftValue<K,V>> o) {
+			this.original = o;
+			this.value = v;
 		}
 		
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @return {@inheritDoc}
-		 */
-		@SuppressWarnings("synthetic-access")
 		@Override
-		public Iterator<Entry<K, V>> iterator() {
-			return new EntrySetIterator(AbstractWeakSoftValueMap.this.map.entrySet().iterator());
+		public K getKey() {
+			return this.original.getKey();
 		}
 
-		/**
-		 * {@inheritDoc}
-		 * 
-		 * @return {@inheritDoc}
-		 */
-		@SuppressWarnings("synthetic-access")
 		@Override
-		public int size() {
-			expurgeNow();
-			return AbstractWeakSoftValueMap.this.map.size();
+		public V getValue() {
+			return this.value;
 		}
-		
-	}
-        
-	/**
-	 * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
-	 * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
-	 */
-	protected interface WeakSoftValue<K,V> extends Entry<K,V> {
-		
-		/**
-		 * @return if the value is enqueued into a reference queue.
-		 */
-		public boolean isEnqueued();
-		
-		/**
-		 * @return the weak/soft reference.
-		 */
-		public V get();
 
-		/**
-		 * @return if the value was enqueued
-		 */
-		public boolean enqueue();
+		@Override
+		public V setValue(V value) {
+			this.value = value;
+			return this.original.getValue().setValue(value);
+		}
 
-		/**
-		 */
-		public void clear();
-
 	}
-
+	
 }

Modified: trunk/arakhneRefs/src/main/resources/Changelog
===================================================================
--- trunk/arakhneRefs/src/main/resources/Changelog	2009-02-03 09:58:11 UTC (rev 32)
+++ trunk/arakhneRefs/src/main/resources/Changelog	2009-02-03 12:37:00 UTC (rev 33)
@@ -1,3 +1,10 @@
+arakhneRefs-5.0
+
+  * Reimplement the AbstractWeakSoftValueMap to avoid execeptions.
+
+ -- Stephane GALLAND <galland@xxxxxxxxxxx> 2009-02-03
+
+
 arakhneRefs-4.1
 
   * Bug fix: avoid IllegalStateException from internal HashMap.

Modified: trunk/arakhneRefs/src/main/resources/VERSION
===================================================================
--- trunk/arakhneRefs/src/main/resources/VERSION	2009-02-03 09:58:11 UTC (rev 32)
+++ trunk/arakhneRefs/src/main/resources/VERSION	2009-02-03 12:37:00 UTC (rev 33)
@@ -1 +1 @@
-arakhneRefs 4.1
+arakhneRefs 5.0

Modified: trunk/arakhneRefs/src/test/java/org/arakhne/util/ref/WeakValueMapTest.java
===================================================================
--- trunk/arakhneRefs/src/test/java/org/arakhne/util/ref/WeakValueMapTest.java	2009-02-03 09:58:11 UTC (rev 32)
+++ trunk/arakhneRefs/src/test/java/org/arakhne/util/ref/WeakValueMapTest.java	2009-02-03 12:37:00 UTC (rev 33)
@@ -64,7 +64,62 @@
 		this.reference.clear();
 	}
 	
-	public void testWeakValueMapMap() {
+    public void testEntryIterator() {
+    	WeakValueMap<String,String> test = new WeakValueMap<String,String>(this.reference);
+        test.setDeeplyExpurge(true);
+	
+        // Test the content
+    	{
+        	assertDeepSimilars(this.reference, test);
+    		Entry<String,String> e;
+        	Iterator<Entry<String,String>> iter = test.entrySet().iterator();
+        	while (iter.hasNext()) {
+        		e = iter.next();
+        		assertTrue(this.reference.containsKey(e.getKey()));
+        		assertEquals(this.reference.get(e.getKey()),this.reference.get(e.getKey()));
+        	}
+    	}
+
+        // Remove elements
+    	Map<String,String> baseElements = new HashMap<String,String>(this.reference);
+        removeElementsFromReference();
+
+		// Collects the objects
+		collect();
+
+        // Test the content
+    	{
+    		assertNotDeepSimilars(this.reference, test);
+    		Entry<String,String> e;
+        	Iterator<Entry<String,String>> iter = test.entrySet().iterator();
+        	while (iter.hasNext()) {
+        		e = iter.next();
+        		assertTrue(baseElements.containsKey(e.getKey()));
+        		assertEquals(baseElements.get(e.getKey()),baseElements.get(e.getKey()));
+        	}
+    	}
+
+		// Clear the list of removed elements, which will cause collecting
+		baseElements.clear();
+		baseElements = null;
+
+		// Collects the objects
+		collect();
+
+        // Test the content
+    	{
+        	assertDeepSimilars(this.reference, test);
+    		Entry<String,String> e;
+        	Iterator<Entry<String,String>> iter = test.entrySet().iterator();
+        	while (iter.hasNext()) {
+        		e = iter.next();
+        		assertTrue(this.reference.containsKey(e.getKey()));
+        		assertEquals(this.reference.get(e.getKey()),this.reference.get(e.getKey()));
+        	}
+    	}
+    }
+
+    public void testWeakValueMapMap() {
         WeakValueMap<String,String> test = new WeakValueMap<String,String>(this.reference);
         assertDeepSimilars(this.reference, test);
     }
@@ -189,61 +244,6 @@
 		}
     }
 
-    public void testEntryIterator() {
-    	WeakValueMap<String,String> test = new WeakValueMap<String,String>(this.reference);
-        test.setDeeplyExpurge(true);
-	
-        // Test the content
-    	{
-        	assertDeepSimilars(this.reference, test);
-    		Entry<String,String> e;
-        	Iterator<Entry<String,String>> iter = test.entrySet().iterator();
-        	while (iter.hasNext()) {
-        		e = iter.next();
-        		assertTrue(this.reference.containsKey(e.getKey()));
-        		assertEquals(this.reference.get(e.getKey()),this.reference.get(e.getKey()));
-        	}
-    	}
-
-        // Remove elements
-    	Map<String,String> baseElements = new HashMap<String,String>(this.reference);
-        removeElementsFromReference();
-
-		// Collects the objects
-		collect();
-
-        // Test the content
-    	{
-    		assertNotDeepSimilars(this.reference, test);
-    		Entry<String,String> e;
-        	Iterator<Entry<String,String>> iter = test.entrySet().iterator();
-        	while (iter.hasNext()) {
-        		e = iter.next();
-        		assertTrue(baseElements.containsKey(e.getKey()));
-        		assertEquals(baseElements.get(e.getKey()),baseElements.get(e.getKey()));
-        	}
-    	}
-
-		// Clear the list of removed elements, which will cause collecting
-		baseElements.clear();
-		baseElements = null;
-
-		// Collects the objects
-		collect();
-
-        // Test the content
-    	{
-        	assertDeepSimilars(this.reference, test);
-    		Entry<String,String> e;
-        	Iterator<Entry<String,String>> iter = test.entrySet().iterator();
-        	while (iter.hasNext()) {
-        		e = iter.next();
-        		assertTrue(this.reference.containsKey(e.getKey()));
-        		assertEquals(this.reference.get(e.getKey()),this.reference.get(e.getKey()));
-        	}
-    	}
-    }
-
     public void testKeyIterator() {
     	WeakValueMap<String,String> test = new WeakValueMap<String,String>(this.reference);
         test.setDeeplyExpurge(true);

Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml	2009-02-03 09:58:11 UTC (rev 32)
+++ trunk/pom.xml	2009-02-03 12:37:00 UTC (rev 33)
@@ -18,7 +18,7 @@
 	<properties>
 		<version_myjdk>1.6</version_myjdk>
 		<version_arakhnelogger>1.1-SNAPSHOT</version_arakhnelogger>
-		<version_arakhnerefs>4.0-SNAPSHOT</version_arakhnerefs>
+		<version_arakhnerefs>5.0-SNAPSHOT</version_arakhnerefs>
 		<version_arakhnevmutils>2.1-SNAPSHOT</version_arakhnevmutils>
 	</properties>
 


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/