[[dev@xxxxxxxxxxx]] [2] First release on a public SCM.

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


Revision: 2
Author:   galland
Date:     2008-09-12 17:59:03 +0200 (Fri, 12 Sep 2008)

Log Message:
-----------
First release on a public SCM.

Added Paths:
-----------
    trunk/pom.xml
    trunk/src/
    trunk/src/main/
    trunk/src/main/java/
    trunk/src/main/java/org/
    trunk/src/main/java/org/arakhne/
    trunk/src/main/java/org/arakhne/util/
    trunk/src/main/java/org/arakhne/util/ref/
    trunk/src/main/java/org/arakhne/util/ref/ComparableSoftReference.java
    trunk/src/main/java/org/arakhne/util/ref/ComparableWeakReference.java
    trunk/src/main/java/org/arakhne/util/ref/SoftValueMap.java
    trunk/src/main/java/org/arakhne/util/ref/WeakArrayList.java
    trunk/src/main/java/org/arakhne/util/ref/WeakValueMap.java
    trunk/src/main/resources/
    trunk/src/main/resources/AUTHORS
    trunk/src/main/resources/COPYING
    trunk/src/main/resources/Changelog
    trunk/src/main/resources/VERSION
    trunk/src/test/
    trunk/src/test/java/


Added: trunk/pom.xml
===================================================================
--- trunk/pom.xml	                        (rev 0)
+++ trunk/pom.xml	2008-09-12 15:59:03 UTC (rev 2)
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.arakhne</groupId>
+  <artifactId>arakhneRefs</artifactId>
+  <packaging>jar</packaging>
+  <version>3.0-SNAPSHOT</version>
+  <name>arakhneRefs</name>
+  <url>http://www.arakhne.org/arakhneRefs/</url>
+  <description>Java library that provides additional tools for managing weak and soft references</description>
+
+	<!-- ======================================= -->
+	<!-- ====       Project Information      === -->
+	<!-- ======================================= -->
+	
+	<licenses>
+		<license>
+			<name>GNU Lesser General Public License v2.0</name>
+			<url>http://www.gnu.org/licenses/lgpl.html</url>
+			<distribution>manual</distribution>
+		</license>
+	</licenses>
+
+	<mailingLists>
+		<mailingList>
+			<name>dev@xxxxxxxxxxx</name>
+			<subscribe>mailto:dev-request@xxxxxxxxxxx</subscribe>
+			<unsubscribe>mailto:dev-request@xxxxxxxxxxx</unsubscribe>
+			<post>mailto:dev@xxxxxxxxxxx</post>
+		</mailingList>
+	</mailingLists>
+
+	<!-- ======================================= -->
+	<!-- ====   Organization Information     === -->
+	<!-- ======================================= -->
+
+	<organization>
+		<name>Arakhn&ecirc;.org Project</name>
+		<url>http://www.arakhne.org</url>
+	</organization>
+
+	<developers>
+		<developer>
+			<id>sgalland</id>
+			<name>Stephane Galland</name>
+			<email>galland@xxxxxxxxxxx</email>
+			<url/>
+			<organization>
+				Arakhn&ecirc;.org
+			</organization>
+			<organizationUrl>http://www.arakhne.org</organizationUrl>
+			<roles>
+				<role>Architect</role>
+				<role>Developer</role>
+			</roles>
+			<timezone />
+			<properties />
+		</developer>
+	</developers>
+	
+	<!-- ======================================= -->
+	<!-- ====  Devel Configuration           === -->
+	<!-- ======================================= -->
+	
+	<scm>
+		<connection>scm:svn:svn+ssh://svn.tuxfamily.org/svnroot/arakhne/arakhneRefs</connection>
+		<developerConnection>scm:svn:svn+ssh://username@xxxxxxxxxxxxxxxxx/svnroot/arakhne/arakhneRefs</developerConnection>
+		<url>http://www.arakhne.org/websvn.php?project=arakhnerefs</url>
+	</scm>
+
+	<build>
+		<plugins> 
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>2.0.2</version>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-scm-plugin</artifactId>
+				<version>1.0</version>
+				<configuration>
+					<goals>install</goals>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+	<!-- ======================================= -->
+	<!-- ====  Dependencies		         === -->
+	<!-- ======================================= -->
+	
+	<dependencies>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>3.8.1</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+
+</project>

Added: trunk/src/main/java/org/arakhne/util/ref/ComparableSoftReference.java
===================================================================
--- trunk/src/main/java/org/arakhne/util/ref/ComparableSoftReference.java	                        (rev 0)
+++ trunk/src/main/java/org/arakhne/util/ref/ComparableSoftReference.java	2008-09-12 15:59:03 UTC (rev 2)
@@ -0,0 +1,172 @@
+/* 
+ * $Id: ComparableSoftReference.java,v 1.1 2007-02-20 08:52:37 sgalland Exp $
+ * 
+ * Copyright (C) 2005-2007 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.util.ref;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+
+/**
+ * This class is a WeakReference that allows to be
+ * compared on its pointed value.
+ * 
+ * @param <T> is the type of the referenced object. 
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
+ */
+public class ComparableSoftReference<T> extends SoftReference<T> implements Comparable<Object> {
+
+	/**
+	 * @param referent is the referenced object.
+	 */
+	public ComparableSoftReference(T referent) {
+		super(referent);
+	}
+	
+	/**
+	 * @param referent is the referenced object.
+	 * @param queue is the object that will be notified of the memory released for the referenced object.
+	 */
+	public ComparableSoftReference(T referent, ReferenceQueue<? super T> queue) {
+		super(referent,queue);
+	}
+
+	/** {@inheritDoc}
+	 * 
+	 * @param o {@inheritDoc}
+	 * @return {@inheritDoc}
+	 */
+	@SuppressWarnings("unchecked")
+	@Override
+	public boolean equals(Object o) {
+		if (super.equals(o)) return true;
+		
+		try {
+			if (o instanceof Reference)
+				return (compareToRef((Reference)o)==0);
+			
+			return compareToObject((T)o)==0;
+		}
+		catch(Exception _) {
+			return false;
+		}
+	}
+
+	/** Compare this reference to the specified object
+	 * based on the {@link Object#hashCode()} if the
+	 * references are not equals.
+	 * 
+	 * @param o {@inheritDoc}
+	 * @return {@inheritDoc}
+	 */
+	@SuppressWarnings("unchecked")
+	public int compareTo(Object o) {
+		try {
+			if (o instanceof Reference)
+				return compareToRef((Reference)o);
+			
+			return compareToObject((T)o);
+		}
+		catch(Exception _) {
+			int a = hashCode();
+			int b = o.hashCode();			
+			return a - b;
+		}
+	}
+
+	/** Compare this reference to the specified object
+	 * based on the {@link Object#hashCode()} if the
+	 * references are not equals.
+	 * 
+     * @param   o the object to be compared.
+     * @return  a negative integer, zero, or a positive integer as this object
+     *		is less than, equal to, or greater than the specified object.
+	 */
+	@SuppressWarnings("unchecked")
+	public int compareToRef(Reference<T> o) {
+		T obj = o.get();
+		T cur = get();
+		
+		if (((cur==null)&&(obj==null))||(cur==obj)) return 0;
+		if (cur==null) return -1;
+		if (obj==null) return 1;
+		
+		if (cur instanceof Comparable) {
+			Comparable cmp = (Comparable<?>)cur;
+			return cmp.compareTo(obj);
+		}
+
+		if ((cur==obj)||(cur.equals(obj))) return 0;
+		
+		int a = cur.hashCode();
+		int b = obj.hashCode();
+		
+		return a - b;
+	}
+	
+	/** Compare this reference to the specified object
+	 * based on the {@link Object#hashCode()} if the
+	 * references are not equals.
+	 * 
+     * @param   o the object to be compared.
+     * @return  a negative integer, zero, or a positive integer as this object
+     *		is less than, equal to, or greater than the specified object.
+	 */
+	@SuppressWarnings("unchecked")
+	public int compareToObject(T o) {
+		if (super.equals(o)) return 0;
+		
+		T cur = get();
+		
+		if ((cur==null)&&(o==null)) return 0;
+		if (cur==null) return -1;
+		if (o==null) return 1;
+		
+		if (cur instanceof Comparable) {
+			Comparable cmp = (Comparable)cur;
+			return cmp.compareTo(o);
+		}
+
+		if ((cur==o)||(cur.equals(o))) return 0;
+		
+		int a = cur.hashCode();
+		int b = o.hashCode();
+		
+		return a - b;
+	}
+
+	/** {@inheritDoc}
+	 * 
+	 * @return {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append('{');
+		T obj = get();
+		if (obj==null) buffer.append("#null#"); //$NON-NLS-1$
+		else buffer.append(obj.toString());
+		buffer.append('}');
+		return buffer.toString();
+	}
+
+}

Added: trunk/src/main/java/org/arakhne/util/ref/ComparableWeakReference.java
===================================================================
--- trunk/src/main/java/org/arakhne/util/ref/ComparableWeakReference.java	                        (rev 0)
+++ trunk/src/main/java/org/arakhne/util/ref/ComparableWeakReference.java	2008-09-12 15:59:03 UTC (rev 2)
@@ -0,0 +1,172 @@
+/* 
+ * $Id: ComparableWeakReference.java,v 1.1 2007-02-20 08:52:37 sgalland Exp $
+ * 
+ * Copyright (C) 2005-2007 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.util.ref;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+/**
+ * This class is a WeakReference that allows to be
+ * compared on its pointed value.
+ * 
+ * @param <T> is the type of the referenced object.
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
+ */
+public class ComparableWeakReference<T> extends WeakReference<T> implements Comparable<Object> {
+
+	/**
+	 * @param referent is the referenced object.
+	 */
+	public ComparableWeakReference(T referent) {
+		super(referent);
+	}
+	
+	/**
+	 * @param referent is the referenced object.
+	 * @param queue is the object that will be notified of the memory released for the referenced object.
+	 */
+	public ComparableWeakReference(T referent, ReferenceQueue<? super T> queue) {
+		super(referent,queue);
+	}
+
+	/** {@inheritDoc}
+	 * 
+	 * @param o {@inheritDoc}
+	 * @return {@inheritDoc}
+	 */
+	@SuppressWarnings("unchecked")
+	@Override
+	public boolean equals(Object o) {
+		if (super.equals(o)) return true;
+		
+		try {
+			if (o instanceof Reference)
+				return (compareToRef((Reference)o)==0);
+			
+			return compareToObject((T)o)==0;
+		}
+		catch(Exception _) {
+			return false;
+		}
+	}
+
+	/** Compare this reference to the specified object
+	 * based on the {@link Object#hashCode()} if the
+	 * references are not equals.
+	 * 
+	 * @param o {@inheritDoc}
+	 * @return {@inheritDoc}
+	 */
+	@SuppressWarnings("unchecked")
+	public int compareTo(Object o) {
+		try {
+			if (o instanceof Reference)
+				return compareToRef((Reference)o);
+			
+			return compareToObject((T)o);
+		}
+		catch(Exception _) {
+			int a = hashCode();
+			int b = o.hashCode();			
+			return a - b;
+		}
+	}
+
+	/** Compare this reference to the specified object
+	 * based on the {@link Object#hashCode()} if the
+	 * references are not equals.
+	 * 
+     * @param   o the object to be compared.
+     * @return  a negative integer, zero, or a positive integer as this object
+     *		is less than, equal to, or greater than the specified object.
+	 */
+	@SuppressWarnings("unchecked")
+	public int compareToObject(T o) {
+		if (super.equals(o)) return 0;
+		
+		T cur = get();
+		
+		if ((cur==null)&&(o==null)) return 0;
+		if (cur==null) return -1;
+		if (o==null) return 1;
+		
+		if (cur instanceof Comparable) {
+			Comparable cmp = (Comparable)cur;
+			return cmp.compareTo(o);
+		}
+
+		if ((cur==o)||(cur.equals(o))) return 0;
+		
+		int a = cur.hashCode();
+		int b = o.hashCode();
+		
+		return a - b;
+	}
+
+	/** Compare this reference to the specified object
+	 * based on the {@link Object#hashCode()} if the
+	 * references are not equals.
+	 * 
+     * @param   o the object to be compared.
+     * @return  a negative integer, zero, or a positive integer as this object
+     *		is less than, equal to, or greater than the specified object.
+	 */
+	@SuppressWarnings("unchecked")
+	public int compareToRef(Reference<T> o) {
+		Object obj = o.get();
+		Object cur = get();
+		
+		if (((cur==null)&&(obj==null))||(obj==cur)) return 0;
+		if (cur==null) return -1;
+		if (obj==null) return 1;
+		
+		if (cur instanceof Comparable) {
+			Comparable cmp = (Comparable)cur;
+			return cmp.compareTo(obj);
+		}
+		
+		if ((cur==obj)||(cur.equals(obj))) return 0;
+		
+		int a = cur.hashCode();
+		int b = obj.hashCode();
+		
+		return a - b;
+	}
+
+	/** {@inheritDoc}
+	 * 
+	 * @return {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append('{');
+		T obj = get();
+		if (obj==null) buffer.append("#null#"); //$NON-NLS-1$
+		else buffer.append(obj.toString());
+		buffer.append('}');
+		return buffer.toString();
+	}
+
+}

Added: trunk/src/main/java/org/arakhne/util/ref/SoftValueMap.java
===================================================================
--- trunk/src/main/java/org/arakhne/util/ref/SoftValueMap.java	                        (rev 0)
+++ trunk/src/main/java/org/arakhne/util/ref/SoftValueMap.java	2008-09-12 15:59:03 UTC (rev 2)
@@ -0,0 +1,448 @@
+/* 
+ * $Id: WeakValueMap.java,v 1.1 2007-02-20 08:52:37 sgalland Exp $
+ * 
+ * Copyright (C) 2005-2007 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.util.ref;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.ConcurrentModificationException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A <tt>Map</tt> implementation with <em>soft-referenced values</em>. An entry in a
+ * <tt>SoftValueMap</tt> will automatically be removed when its value is no
+ * longer in ordinary use or null.
+ * <p>
+ * This class was inspirated from {@link WeakValueMap}.
+ * <p>
+ * This class has a special flag which permits to control the
+ * way how the released references are expurged: {@link #isDeeplyExpurge()},
+ * {@link #setDeeplyExpurge(boolean)}. If this flag is <code>true</code>,
+ * all the released references will be immediately removed from the map even
+ * if they are not enqueued by the virtual machine (see {@link #expurge()}.
+ * If this flag is <code>false</code>,
+ * only the enqueued references will be removed from the map
+ * (see {@link #expurgeQueuedReferences()}.
+ * <p>
+ * If this map does not use a "deep expurge" of the released references,
+ * it could contains <code>null</code> values that corresponds to
+ * values that are released by the garbage collector. If a "deep expurge"
+ * is used, all the values released by the garbage collector will be
+ * removed from the map.
+ * <p>
+ * "Deep expurge" consumes much more time that "No deep expurge". This is the
+ * reason why this feature is not activated by default.
+ * <p>
+ * The "deep expurge" feature was added to fix the uncoherent behavior
+ * of the garbage collector which seems to not always enqueued the 
+ * released values (sometimes the queue is empty even if a value was released).
+ *
+ * @param <K> is the type of the keys.
+ * @param <V> is the type of the values.
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
+ */
+public class SoftValueMap<K,V> extends AbstractMap<K,V> implements Map<K,V> {
+
+	/** Constant that represent a NULL value inside a SoftValueMap.
+	 * @see #maskNull(Object)
+	 */
+	protected static final Object NULL_VALUE = new Object();
+
+	/** Mask the null values given by the used of this map.
+	 * <p>
+	 * This method replaces the <code>null</code> value by
+	 * the internal representation {@link #NULL_VALUE}.
+	 *
+	 * @param <V> is the type of the value
+	 * @param value is the value given by the user of this map.
+	 * @return the internal representation of the value.
+	 * @see #unmaskNull(Object)
+	 */
+	@SuppressWarnings("unchecked")
+	protected static <V> V maskNull(V value) {
+		return (value==null) ? (V)NULL_VALUE : value;
+	}
+
+	/** Unmask the null values given by the used of this map.
+	 * <p>
+	 * This method replaces the internal representation
+	 * {@link #NULL_VALUE} of null values by its user representation
+	 * <code>null</code>.
+	 * 
+	 * @param <V> is the type of the value
+	 * @param value is the value given by the user of this map.
+	 * @return the internal representation of the value.
+	 * @see #maskNull(Object)
+	 */
+	@SuppressWarnings("unchecked")
+	protected static <V> V unmaskNull(V value) {
+		return (value==NULL_VALUE) ? null : value;
+	}
+
+	private boolean autoExpurge = false;
+	private final HashMap<K,Value<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
+     * capacity and load factor.
+     *
+     * @param  initialCapacity the initial capacity
+     * @param  loadFactor      the load factor
+     * @throws IllegalArgumentException if the initial capacity is negative
+     *         or the load factor is nonpositive
+     */
+    public SoftValueMap(int initialCapacity, float loadFactor) {
+        this.map = new HashMap<K,Value<K,V>>(initialCapacity, loadFactor);
+        this.entrySet = new EntrySet();
+    }
+
+    /**
+     * Constructs an empty <tt>HashMap</tt> with the specified initial
+     * capacity and the default load factor (0.75).
+     *
+     * @param  initialCapacity the initial capacity.
+     * @throws IllegalArgumentException if the initial capacity is negative.
+     */
+    public SoftValueMap(int initialCapacity) {
+        this.map = new HashMap<K,Value<K,V>>(initialCapacity);
+        this.entrySet = new EntrySet();
+    }
+
+    /**
+     * Constructs an empty <tt>HashMap</tt> with the default initial capacity
+     * (16) and the default load factor (0.75).
+     */
+    public SoftValueMap() {
+        this.map = new HashMap<K,Value<K,V>>();
+        this.entrySet = new EntrySet();
+    }
+
+    /**
+     * Constructs a new <tt>HashMap</tt> with the same mappings as the
+     * specified <tt>Map</tt>.  The <tt>HashMap</tt> is created with
+     * default load factor (0.75) and an initial capacity sufficient to
+     * hold the mappings in the specified <tt>Map</tt>.
+     *
+     * @param   m the map whose mappings are to be placed in this map
+     * @throws  NullPointerException if the specified map is null
+     */
+    public SoftValueMap(Map<? extends K, ? extends V> m) {
+        this.map = new HashMap<K,Value<K,V>>();
+        this.entrySet = new EntrySet();
+        putAll(m);
+    }	
+
+    /** Clean the references that was marked as released inside
+     * the queue.
+     */
+	protected void expurgeNow() {
+		if (this.autoExpurge)
+			expurge();
+		else
+			expurgeQueuedReferences();
+	}
+	
+	/** Replies if this map expurge all the released references
+	 * even if they are not enqueued by the virtual machine
+	 * 
+	 * @return <code>true</code> if this map deeply expurge its content,
+	 * otherwise <code>false</code>
+	 */
+	public boolean isDeeplyExpurge() {
+		return this.autoExpurge;
+	}
+	
+	/** Set if this map expurge all the released references
+	 * even if they are not enqueued by the virtual machine
+	 * 
+	 * @param deeplyExpurge must be <code>true</code> to
+	 * expurge all the released values, otherwise <code>false</code>
+	 * to expurge only the enqueued values.
+	 * @return the old value of this flag
+	 */
+	public boolean setDeeplyExpurge(boolean deeplyExpurge) {
+		boolean old = this.autoExpurge;
+		this.autoExpurge = deeplyExpurge;
+		return old;
+	}
+	
+    /** Clean the references that was marked as released inside
+     * the queue.
+     */
+	public void expurgeQueuedReferences() {
+		Reference<? extends V> o;
+		while((o = this.queue.poll()) != null) {
+			if (o instanceof Entry) {
+				this.map.remove(((Entry<K,V>)o).getKey());
+			}
+			o.clear();
+		}
+	}
+
+	/** Clean the references that was released.
+     */
+	public void expurge() {
+		Reference<? extends V> o;
+		
+		Iterator<Entry<K,Value<K,V>>> iter = this.map.entrySet().iterator();
+		Entry<K,Value<K,V>> entry;
+		Value<K,V> value;
+		while (iter.hasNext()) {
+			entry = iter.next();
+			if (entry!=null) {
+				value = entry.getValue();
+				if ((value!=null)&&
+					((value.isEnqueued())||(value.get()==null))) {
+					value.enqueue();
+					value.clear();
+				}
+			}
+		}
+		entry = null;
+		value = null;
+
+		while((o = this.queue.poll()) != null) {
+			if (o instanceof Entry) {
+				this.map.remove(((Entry<K,V>)o).getKey());
+			}
+			o.clear();
+		}
+	}
+
+	/** 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
+	 * @param queue is the reference queue to use
+	 * @return the new storage object
+	 */
+	protected Value<K,V> makeValue(K k, V v, ReferenceQueue<V> queue) {
+		return new Value<K,V>(k, v, queue);
+	}
+
+	/**
+     * {@inheritDoc}
+     */
+	@Override
+	public V put(K key, V value) {
+		expurgeNow();
+		Value<K,V> ret = this.map.put(key, makeValue(key, value, this.queue));
+		if(ret == null) return null;
+		return ret.getValue();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Set<Entry<K,V>> entrySet() {
+		expurgeNow();
+		return this.entrySet;
+	}	
+		
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+	public boolean equals(Object o) {
+    	expurgeNow();
+    	return super.equals(o);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+	public int hashCode() {
+    	expurgeNow();
+    	return hashCode();
+    }
+
+    /**
+	 * @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 final Set<Entry<K,Value<K,V>>> baseSet;
+
+		/**
+		 * 
+		 */
+		@SuppressWarnings("synthetic-access")
+		public EntrySet() {
+			this.baseSet = SoftValueMap.this.map.entrySet();
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		@Override
+		public Iterator<Entry<K, V>> iterator() {
+			final Iterator<Entry<K,Value<K,V>>> iter = this.baseSet.iterator();
+			return new Iterator<Entry<K,V>>() {
+				public boolean hasNext() { 
+					expurgeNow();
+					return iter.hasNext();
+				}
+				public Entry<K,V> next() {
+					Entry<K, Value<K,V>> entry = iter.next();
+					if (entry==null) throw new ConcurrentModificationException();
+					Value<K,V> value = entry.getValue();
+					if (value==null) throw new ConcurrentModificationException();
+					return value;
+				}
+				public void remove() {
+					iter.remove();
+				}
+			};
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		@Override
+		public int size() {
+			expurgeNow();
+			return this.baseSet.size();
+		}
+		
+	}
+
+	/**
+	 * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+	 * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
+	 */
+	private static class Value<K,V> extends SoftReference<V> implements Entry<K,V> {
+		
+		private final K k;
+
+		/**
+		 * @param k is the key.
+		 * @param v is the value.
+		 * @param queue is the memory release listener.
+		 */
+		Value(K k, V v, ReferenceQueue<V> queue) {
+			super(maskNull(v), queue);
+			this.k = k;
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		@Override
+		public String toString() {
+			StringBuffer buffer = new StringBuffer();
+			buffer.append('{');
+			K key = getKey();
+			buffer.append(key==null ? null : key.toString());
+			buffer.append('=');
+			if (isEnqueued()) {
+				buffer.append("Q#"); //$NON-NLS-1$
+			}
+			else {
+				buffer.append("P#"); //$NON-NLS-1$
+			}
+			V v = getValue();
+			buffer.append((v==null ? null : v.toString()));
+			buffer.append('}');
+			return buffer.toString();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		public K getKey() {
+			return this.k;
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		public V getValue() {
+			return unmaskNull(get());
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @param o {@inheritDoc}
+		 * @return {@inheritDoc}
+		 */
+		public V setValue(V o) {
+			throw new UnsupportedOperationException();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		@Override
+		public int hashCode() { 
+			Object val = getValue();
+			return (getKey()==null   ? 0 : getKey().hashCode()) ^
+				   (val==null ? 0 : val.hashCode()); 
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @param o {@inheritDoc}
+		 * @return {@inheritDoc}
+		 */
+		@SuppressWarnings("unchecked")
+		@Override
+		public boolean equals(Object o) {
+			if (o instanceof Entry) {
+				Entry<K,V> e = (Entry<K,V>)o;
+				Object e1val = getValue();
+				Object e2val = e.getValue();
+				return  (getKey()==null ?
+						e.getKey()==null : getKey().equals(e.getKey()))  &&
+						(e1val==null ? e2val==null : e1val.equals(e2val));
+			}
+			return false;
+		}
+
+	}
+        
+}

Added: trunk/src/main/java/org/arakhne/util/ref/WeakArrayList.java
===================================================================
--- trunk/src/main/java/org/arakhne/util/ref/WeakArrayList.java	                        (rev 0)
+++ trunk/src/main/java/org/arakhne/util/ref/WeakArrayList.java	2008-09-12 15:59:03 UTC (rev 2)
@@ -0,0 +1,400 @@
+/* 
+ * $Id: WeakArrayList.java,v 1.1 2007-02-20 08:52:37 sgalland Exp $
+ * 
+ * Copyright (C) 2005-2007 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.util.ref;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.AbstractList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * A array-based <tt>List</tt> implementation with <em>weak keys</em>.
+ * An entry in a <tt>WeakArrayList</tt> will automatically be removed when
+ * it is no longer in ordinary use.
+ *
+ * <p> The behavior of the <tt>WeakArrayList</tt> class depends in part upon
+ * the actions of the garbage collector, so several familiar (though not
+ * required) <tt>List</tt> invariants do not hold for this class.  Because
+ * the garbage collector may discard values at any time, a
+ * <tt>WeakArrayList</tt> may behave as though an unknown thread is silently
+ * removing entries.  In particular, even if you synchronize on a
+ * <tt>WeakArrayList</tt> instance and invoke none of its mutator methods, it
+ * is possible for the <tt>size</tt> method to return smaller values over
+ * time, for the <tt>isEmpty</tt> method to return <tt>false</tt> and
+ * then <tt>true</tt>, for the <tt>contains</tt> method to return
+ * <tt>true</tt> and later <tt>false</tt> for a given value, for the
+ * <tt>get</tt> method to return a value for a given key but later return
+ * <tt>null</tt>, for the <tt>add</tt> method to return
+ * <tt>null</tt> and the <tt>remove</tt> method to return
+ * <tt>false</tt> for a value that previously appeared to be in the list.
+ * <p>
+ * This class has a special flag which permits to control the
+ * way how the released references are expurged: {@link #isDeeplyExpurge()},
+ * {@link #setDeeplyExpurge(boolean)}. If this flag is <code>true</code>,
+ * all the released references will be immediately removed from the map even
+ * if they are not enqueued by the virtual machine (see {@link #expurge()}.
+ * If this flag is <code>false</code>,
+ * only the enqueued references will be removed from the map
+ * (see {@link #expurgeQueuedReferences()}.
+ * <p>
+ * If this map does not use a "deep expurge" of the released references,
+ * it could contains <code>null</code> values that corresponds to
+ * values that are released by the garbage collector. If a "deep expurge"
+ * is used, all the values released by the garbage collector will be
+ * removed from the map.
+ * <p>
+ * "Deep expurge" consumes much more time that "No deep expurge". This is the
+ * reason why this feature is not activated by default.
+ * <p>
+ * The "deep expurge" feature was added to fix the uncoherent behavior
+ * of the garbage collector which seems to not always enqueued the 
+ * released values (sometimes the queue is empty even if a value was released).
+ *
+ * @param <T> is the type of the array's elements.
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $ 
+ */
+public class WeakArrayList<T> extends AbstractList<T> implements List<T> {
+
+	private static final long serialVersionUID = 2601162363164961860L;
+	
+	/** This value represents a null value given by the user.
+	 */
+	private static final Object NULL_VALUE = new Object();
+	
+	/** Replies the null value given by the user by the corresponding null object.
+	 */
+	@SuppressWarnings("unchecked")
+	private T maskNull(T value) {
+		return (value==null) ? (T)NULL_VALUE : value;
+	}
+
+	/** Replies the value given by the user.
+	 */
+	private T unmaskNull(T value) {
+		return (value==NULL_VALUE) ? null : value;
+	}
+
+	private final transient ReferenceQueue<T> queue = new ReferenceQueue<T>();
+	
+	private Object[] data;
+	
+	private int size;
+	
+	private boolean autoExpurge = false;
+	
+    /**
+     * Constructs an empty list with the specified initial capacity.
+     *
+     * @param   initialCapacity   the initial capacity of the list
+     * @exception IllegalArgumentException if the specified initial capacity
+     *            is negative
+     */
+    public WeakArrayList(int initialCapacity) {
+        if (initialCapacity < 0)
+            throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity); //$NON-NLS-1$
+        this.data = new Object[initialCapacity];
+        this.size = 0;
+    }
+
+    /**
+     * Constructs an empty list with an initial capacity of ten.
+     */
+    public WeakArrayList() {
+    	this(10);
+    }
+    
+    /**
+     * Constructs a list containing the elements of the specified
+     * collection, in the order they are returned by the collection's
+     * iterator.
+     *
+     * @param c the collection whose elements are to be placed into this list
+     * @throws NullPointerException if the specified collection is null
+     */
+    public WeakArrayList(Collection<? extends T> c) {
+    	this.data = new Object[c.size()];
+    	this.size = this.data.length;
+    	int i=0;
+    	for (T t : c) {
+			this.data[i] = createRef(t);
+			i++;
+		}
+    }
+    
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @return {@inheritDoc}
+	 */
+    @Override
+	@SuppressWarnings("unchecked")
+	public String toString() {
+    	StringBuffer buffer = new StringBuffer();
+    	Reference<T> ref;
+    	T obj;
+    	for(int i=0; i<this.size; i++) {
+    		ref = (Reference<T>)this.data[i];
+    		obj = ref.get();
+    		buffer.append('{');
+    		buffer.append(obj==null ? null : obj.toString());
+    		buffer.append('}');
+    	}
+    	return buffer.toString();
+    }
+	
+    /** Create and replies the reference for the specified object.
+     * 
+     * @param obj is the object on which a weak reference must be attached.
+     * @return the weak reference. 
+     */
+    private Reference<T> createRef(T obj) {
+    	return new WeakReference<T>(maskNull(obj), this.queue);
+    }
+    
+    /**
+     * Increases the capacity of this <tt>WeakArrayList</tt> instance, if
+     * necessary, to ensure that it can hold at least the number of elements
+     * specified by the minimum capacity argument.
+     *
+     * @param   minCapacity   the desired minimum capacity
+     */
+    public void ensureCapacity(int minCapacity) {
+		this.modCount++;
+		int oldCapacity = this.data.length;
+		if (minCapacity > oldCapacity) {
+			Object[] oldData = this.data;
+			int newCapacity = (oldCapacity * 3)/2 + 1;
+			if (newCapacity < minCapacity)
+				newCapacity = minCapacity;
+			// minCapacity is usually close to size, so this is a win:
+			this.data = Arrays.copyOf(oldData, newCapacity);
+		}
+    }
+
+    /**
+     * Trims the capacity of this <tt>WeakArrayList</tt> instance to be the
+     * list's current size.  An application can use this operation to minimize
+     * the storage of an <tt>WeakArrayList</tt> instance.
+     */
+    public void trimToSize() {
+    	this.modCount++;
+    	int oldCapacity = this.data.length;
+    	if (this.size < oldCapacity) {
+    		this.data = Arrays.copyOf(this.data, this.size);
+    	}
+    }
+    
+    /** Clean the references that was marked as released inside
+     * the queue.
+     * 
+     * @return the count of expurged elements.
+     */
+	protected int expurgeNow() {
+		if (this.autoExpurge)
+			return expurge();
+		return expurgeQueuedReferences();
+	}
+	
+	/** Replies if this map expurge all the released references
+	 * even if they are not enqueued by the virtual machine
+	 * 
+	 * @return <code>true</code> if this array list deeply expurge the
+	 * released elements, otherwise <code>false</code>
+	 */
+	public boolean isDeeplyExpurge() {
+		return this.autoExpurge;
+	}
+	
+	/** Set if this map expurge all the released references
+	 * even if they are not enqueued by the virtual machine
+	 * 
+	 * @param deeplyExpurge must be <code>true</code> to
+	 * expurge all the released values, otherwise <code>false</code>
+	 * to expurge only the enqueued values.
+	 * @return the old value of this flag
+	 */
+	public boolean setDeeplyExpurge(boolean deeplyExpurge) {
+		boolean old = this.autoExpurge;
+		this.autoExpurge = deeplyExpurge;
+		return old;
+	}
+
+    /** Clean the references that was marked as released inside
+     * the queue.
+     * 
+     * @return the size 
+     */
+	public int expurgeQueuedReferences() {
+		synchronized (this.queue) {
+			// Expurge the array only if a referenced
+			// object was marked as releasable
+			Reference<? extends T> ref = this.queue.poll();
+			if (ref!=null) {
+				return expurge();
+			}
+			return this.size;
+		}
+	}
+
+	/** Clean the references that was released.
+	 * 
+	 * @return the size
+     */
+	@SuppressWarnings("unchecked")
+	public int expurge() {
+		synchronized(this.queue) {
+			Reference<? extends T> ref = this.queue.poll();
+			while (ref!=null) {
+				ref.clear();
+				ref = this.queue.poll();
+			}
+				
+			// Clear the table
+			for(int i=this.size-1; i>=0; i--) {
+				ref = (Reference<T>)this.data[i];
+				assert(ref!=null);
+				if ((ref.isEnqueued())||(ref.get()==null)) {
+					ref.enqueue();
+					ref.clear();
+					System.arraycopy(
+							this.data, i+1,
+							this.data, i,
+							this.size - i - 1);
+					this.size --;
+				}
+			}
+				
+			ref = this.queue.poll();
+			while (ref!=null) {
+				ref.clear();
+				ref = this.queue.poll();
+			}
+			return this.size;
+		}
+    }
+    
+    /** Verify if the specified index is inside the array.
+     * 
+     * @param index is the index totest
+     * @param allowLast indicates if the last elements is assumed to be valid or not.
+     */
+    protected void assertRange(int index, boolean allowLast) {
+    	int size = expurgeNow();
+    	if (index<0)
+    		throw new IndexOutOfBoundsException("invalid negative value: "+Integer.toString(index)); //$NON-NLS-1$
+    	if ((allowLast)&&(index>size))
+    		throw new IndexOutOfBoundsException("index>"+size+": "+Integer.toString(index)); //$NON-NLS-1$ //$NON-NLS-2$
+    	if ((!allowLast)&&(index>=size))
+    		throw new IndexOutOfBoundsException("index>="+size+": "+Integer.toString(index)); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+	/** {@inheritDoc}
+	 */
+	@Override
+	public int size() {
+		synchronized(this.queue) {
+			return expurgeNow();
+		}
+	}
+
+	/** {@inheritDoc}
+	 */
+	@SuppressWarnings("unchecked")
+	@Override
+	public T get(int index) {
+		synchronized(this.queue) {
+			T value;
+			do {
+				assertRange(index,false);
+				value = ((Reference<T>)this.data[index]).get();
+			}
+			while (value==null);
+			return unmaskNull(value);
+		}
+	}
+
+    /**
+     * {@inheritDoc}
+     */
+    @SuppressWarnings("unchecked")
+	@Override
+	public T set(int index, T element) {
+		synchronized(this.queue) {
+			T oldValue;
+			Reference<T> ref;
+			do {
+				assertRange(index, false);
+				ref = (Reference<T>)this.data[index];
+				oldValue = ref.get();
+			}
+			while (oldValue==null);
+			ref.clear();
+			this.data[index] = createRef(element);
+			this.modCount++;
+			return unmaskNull(oldValue);
+		}
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+	public void add(int index, T element) {
+		synchronized(this.queue) {
+			assertRange(index,true);
+			ensureCapacity(this.size+1);
+			System.arraycopy(this.data, index, this.data, index+1, this.size-index);
+			this.data[index] = createRef(element);
+			this.size++;
+			this.modCount++;
+		}
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @SuppressWarnings("unchecked")
+	@Override
+	public T remove(int index) {
+		synchronized(this.queue) {
+			T oldValue;
+			Reference<T> ref;
+			do {
+				assertRange(index, false);
+				ref = (Reference<T>)this.data[index];
+				oldValue = ref.get();
+			}
+			while (oldValue==null);
+			ref.clear();
+			System.arraycopy(this.data, index+1, this.data, index, this.size-index-1);
+			this.data[this.size-1] = null;
+			this.size--;
+			this.modCount++;
+			return unmaskNull(oldValue);
+		}
+    }
+
+}

Added: trunk/src/main/java/org/arakhne/util/ref/WeakValueMap.java
===================================================================
--- trunk/src/main/java/org/arakhne/util/ref/WeakValueMap.java	                        (rev 0)
+++ trunk/src/main/java/org/arakhne/util/ref/WeakValueMap.java	2008-09-12 15:59:03 UTC (rev 2)
@@ -0,0 +1,450 @@
+/* 
+ * $Id: WeakValueMap.java,v 1.1 2007-02-20 08:52:37 sgalland Exp $
+ * 
+ * Copyright (C) 2005-2007 St&eacute;phane GALLAND
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.util.ref;
+
+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.ConcurrentModificationException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+/**
+ * A <tt>Map</tt> implementation with <em>weak values</em>. An entry in a
+ * <tt>WeakValueMap</tt> will automatically be removed when its value is no
+ * longer in ordinary use or null.
+ * <p>
+ * This class was inspirated from {@link WeakHashMap}
+ * <p>
+ * This class has a special flag which permits to control the
+ * way how the released references are expurged: {@link #isDeeplyExpurge()},
+ * {@link #setDeeplyExpurge(boolean)}. If this flag is <code>true</code>,
+ * all the released references will be immediately removed from the map even
+ * if they are not enqueued by the virtual machine (see {@link #expurge()}.
+ * If this flag is <code>false</code>,
+ * only the enqueued references will be removed from the map
+ * (see {@link #expurgeQueuedReferences()}.
+ * <p>
+ * If this map does not use a "deep expurge" of the released references,
+ * it could contains <code>null</code> values that corresponds to
+ * values that are released by the garbage collector. If a "deep expurge"
+ * is used, all the values released by the garbage collector will be
+ * removed from the map.
+ * <p>
+ * "Deep expurge" consumes much more time that "No deep expurge". This is the
+ * reason why this feature is not activated by default.
+ * <p>
+ * The "deep expurge" feature was added to fix the uncoherent behavior
+ * of the garbage collector which seems to not always enqueued the 
+ * released values (sometimes the queue is empty even if a value was released).
+ *
+ * @param <K> is the type of the keys.
+ * @param <V> is the type of the values.
+ * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
+ */
+public class WeakValueMap<K,V> extends AbstractMap<K,V> implements Map<K,V> {
+	
+	/** Defines the NULL object inside a WeakValueMap.
+	 * 
+	 * @see #maskNull(Object)
+	 */
+	protected static final Object NULL_VALUE = new Object();
+
+	/** Mask the null values given by the used of this map.
+	 * <p>
+	 * This method replaces the <code>null</code> value by
+	 * the internal representation {@link #NULL_VALUE}.
+	 *
+	 * @param <V> is the type of the value.
+	 * @param value is the value given by the user of this map.
+	 * @return the internal representation of the value.
+	 * @see #unmaskNull(Object)
+	 */
+	@SuppressWarnings("unchecked")
+	protected static <V> V maskNull(V value) {
+		return (value==null) ? (V)NULL_VALUE : value;
+	}
+
+	/** Unmask the null values given by the used of this map.
+	 * <p>
+	 * This method replaces the internal representation
+	 * {@link #NULL_VALUE} of null values by its user representation
+	 * <code>null</code>.
+	 * 
+	 * @param <V> is the type of the value.
+	 * @param value is the value given by the user of this map.
+	 * @return the internal representation of the value.
+	 * @see #maskNull(Object)
+	 */
+	@SuppressWarnings("unchecked")
+	protected static <V> V unmaskNull(V value) {
+		return (value==NULL_VALUE) ? null : value;
+	}
+
+	private boolean autoExpurge = false;
+	private final HashMap<K,Value<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
+     * capacity and load factor.
+     *
+     * @param  initialCapacity the initial capacity
+     * @param  loadFactor      the load factor
+     * @throws IllegalArgumentException if the initial capacity is negative
+     *         or the load factor is nonpositive
+     */
+    public WeakValueMap(int initialCapacity, float loadFactor) {
+        this.map = new HashMap<K,Value<K,V>>(initialCapacity, loadFactor);
+        this.entrySet = new EntrySet();
+    }
+
+    /**
+     * Constructs an empty <tt>HashMap</tt> with the specified initial
+     * capacity and the default load factor (0.75).
+     *
+     * @param  initialCapacity the initial capacity.
+     * @throws IllegalArgumentException if the initial capacity is negative.
+     */
+    public WeakValueMap(int initialCapacity) {
+        this.map = new HashMap<K,Value<K,V>>(initialCapacity);
+        this.entrySet = new EntrySet();
+    }
+
+    /**
+     * Constructs an empty <tt>HashMap</tt> with the default initial capacity
+     * (16) and the default load factor (0.75).
+     */
+    public WeakValueMap() {
+        this.map = new HashMap<K,Value<K,V>>();
+        this.entrySet = new EntrySet();
+    }
+
+    /**
+     * Constructs a new <tt>HashMap</tt> with the same mappings as the
+     * specified <tt>Map</tt>.  The <tt>HashMap</tt> is created with
+     * default load factor (0.75) and an initial capacity sufficient to
+     * hold the mappings in the specified <tt>Map</tt>.
+     *
+     * @param   m the map whose mappings are to be placed in this map
+     * @throws  NullPointerException if the specified map is null
+     */
+    public WeakValueMap(Map<? extends K, ? extends V> m) {
+        this.map = new HashMap<K,Value<K,V>>();
+        this.entrySet = new EntrySet();
+        putAll(m);
+    }	
+
+    /** Clean the references that was marked as released inside
+     * the queue.
+     */
+	protected void expurgeNow() {
+		if (this.autoExpurge)
+			expurge();
+		else
+			expurgeQueuedReferences();
+	}
+	
+	/** Replies if this map expurge all the released references
+	 * even if they are not enqueued by the virtual machine
+	 * 
+	 * @return <code>true</code> is the values are deeply expurged when they
+	 * are released from the moemory, otherwise <code>false</code>
+	 */
+	public boolean isDeeplyExpurge() {
+		return this.autoExpurge;
+	}
+	
+	/** Set if this map expurge all the released references
+	 * even if they are not enqueued by the virtual machine
+	 * 
+	 * @param deeplyExpurge must be <code>true</code> to
+	 * expurge all the released values, otherwise <code>false</code>
+	 * to expurge only the enqueued values.
+	 * @return the old value of this flag
+	 */
+	public boolean setDeeplyExpurge(boolean deeplyExpurge) {
+		boolean old = this.autoExpurge;
+		this.autoExpurge = deeplyExpurge;
+		return old;
+	}
+	
+    /** Clean the references that was marked as released inside
+     * the queue.
+     */
+	public void expurgeQueuedReferences() {
+		Reference<? extends V> o;
+		while((o = this.queue.poll()) != null) {
+			if (o instanceof Entry) {
+				this.map.remove(((Entry<K,V>)o).getKey());
+			}
+			o.clear();
+		}
+	}
+
+	/** Clean the references that was released.
+     */
+	public void expurge() {
+		Reference<? extends V> o;
+		
+		Iterator<Entry<K,Value<K,V>>> iter = this.map.entrySet().iterator();
+		Entry<K,Value<K,V>> entry;
+		Value<K,V> value;
+		while (iter.hasNext()) {
+			entry = iter.next();
+			if (entry!=null) {
+				value = entry.getValue();
+				if ((value!=null)&&
+					((value.isEnqueued())||(value.get()==null))) {
+					value.enqueue();
+					value.clear();
+				}
+			}
+		}
+		entry = null;
+		value = null;
+
+		while((o = this.queue.poll()) != null) {
+			if (o instanceof Entry) {
+				this.map.remove(((Entry<K,V>)o).getKey());
+			}
+			o.clear();
+		}
+	}
+
+	/** 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
+	 * @param queue is the reference queue to use
+	 * @return the new storage object
+	 */
+	protected Value<K,V> makeValue(K k, V v, ReferenceQueue<V> queue) {
+		return new Value<K,V>(k, v, queue);
+	}
+
+	/**
+     * {@inheritDoc}
+     */
+	@Override
+	public V put(K key, V value) {
+		expurgeNow();
+		Value<K,V> ret = this.map.put(key, makeValue(key, value, this.queue));
+		if(ret == null) return null;
+		return ret.getValue();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Set<Entry<K,V>> entrySet() {
+		expurgeNow();
+		return this.entrySet;
+	}	
+		
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+	public boolean equals(Object o) {
+    	expurgeNow();
+    	return super.equals(o);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+	public int hashCode() {
+    	expurgeNow();
+    	return hashCode();
+    }
+
+    /**
+	 * @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 final Set<Entry<K,Value<K,V>>> baseSet;
+
+		/**
+		 *
+		 */
+		@SuppressWarnings("synthetic-access")
+		public EntrySet() {
+			this.baseSet = WeakValueMap.this.map.entrySet();
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		@Override
+		public Iterator<Entry<K, V>> iterator() {
+			final Iterator<Entry<K,Value<K,V>>> iter = this.baseSet.iterator();
+			return new Iterator<Entry<K,V>>() {
+				public boolean hasNext() { 
+					expurgeNow();
+					return iter.hasNext();
+				}
+				public Entry<K,V> next() {
+					Entry<K, Value<K,V>> entry = iter.next();
+					if (entry==null) throw new ConcurrentModificationException();
+					Value<K,V> value = entry.getValue();
+					if (value==null) throw new ConcurrentModificationException();
+					return value;
+				}
+				public void remove() {
+					iter.remove();
+				}
+			};
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		@Override
+		public int size() {
+			expurgeNow();
+			return this.baseSet.size();
+		}
+		
+	}
+
+	/**
+	 * @author St&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+	 * @version $Name:  $ $Revision: 1.1 $ $Date: 2007-02-20 08:52:37 $
+	 */
+	private static class Value<K,V> extends WeakReference<V> implements Entry<K,V> {
+		
+		private final K k;
+
+		/**
+		 * @param k is the key.
+		 * @param v is the value.
+		 * @param queue is the memory-release listener.
+		 */
+		Value(K k, V v, ReferenceQueue<V> queue) {
+			super(maskNull(v), queue);
+			this.k = k;
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		@Override
+		public String toString() {
+			StringBuffer buffer = new StringBuffer();
+			buffer.append('{');
+			K key = getKey();
+			buffer.append(key==null ? null : key.toString());
+			buffer.append('=');
+			if (isEnqueued()) {
+				buffer.append("Q#"); //$NON-NLS-1$
+			}
+			else {
+				buffer.append("P#"); //$NON-NLS-1$
+			}
+			V v = getValue();
+			buffer.append((v==null ? null : v.toString()));
+			buffer.append('}');
+			return buffer.toString();
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		public K getKey() {
+			return this.k;
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		public V getValue() {
+			return unmaskNull(get());
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @param o {@inheritDoc}
+		 * @return {@inheritDoc}
+		 */
+		public V setValue(V o) {
+			throw new UnsupportedOperationException();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @return {@inheritDoc}
+		 */
+		@Override
+		public int hashCode() { 
+			Object val = getValue();
+			return (getKey()==null   ? 0 : getKey().hashCode()) ^
+				   (val==null ? 0 : val.hashCode()); 
+		}
+		
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @param o {@inheritDoc}
+		 * @return {@inheritDoc}
+		 */
+		@SuppressWarnings("unchecked")
+		@Override
+		public boolean equals(Object o) {
+			if (o instanceof Entry) {
+				Entry<K,V> e = (Entry<K,V>)o;
+				Object e1val = getValue();
+				Object e2val = e.getValue();
+				return  (getKey()==null ?
+						e.getKey()==null : getKey().equals(e.getKey()))  &&
+						(e1val==null ? e2val==null : e1val.equals(e2val));
+			}
+			return false;
+		}
+
+	}
+        
+}

Added: trunk/src/main/resources/AUTHORS
===================================================================
--- trunk/src/main/resources/AUTHORS	                        (rev 0)
+++ trunk/src/main/resources/AUTHORS	2008-09-12 15:59:03 UTC (rev 2)
@@ -0,0 +1 @@
+Stephane GALLAND <galland@xxxxxxxxxxx>

Added: trunk/src/main/resources/COPYING
===================================================================
--- trunk/src/main/resources/COPYING	                        (rev 0)
+++ trunk/src/main/resources/COPYING	2008-09-12 15:59:03 UTC (rev 2)
@@ -0,0 +1,165 @@
+		   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions. 
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version. 
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.

Added: trunk/src/main/resources/Changelog
===================================================================
--- trunk/src/main/resources/Changelog	                        (rev 0)
+++ trunk/src/main/resources/Changelog	2008-09-12 15:59:03 UTC (rev 2)
@@ -0,0 +1,17 @@
+arakhneRefs-3.0
+
+ * Add the class SoftValueMap
+
+ -- Stephane GALLAND <galland@xxxxxxxxxxx> Mon, 18 Feb 2008 20:04:24 +0100
+
+arakhneRefs-2.0
+
+ * Bug fixes inside the weak data structures
+
+ -- Stephane GALLAND <galland@xxxxxxxxxxx> Mon, 31 Dec 2007 12:24:59 +0100
+
+arakhneRefs-1.0
+
+ * First public release.
+
+ -- Stephane GALLAND <galland@xxxxxxxxxxx>

Added: trunk/src/main/resources/VERSION
===================================================================
--- trunk/src/main/resources/VERSION	                        (rev 0)
+++ trunk/src/main/resources/VERSION	2008-09-12 15:59:03 UTC (rev 2)
@@ -0,0 +1 @@
+arakhneRefs 3.0


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