Index: lutinutil/src/java/org/codelutin/util/HashMapMultiKey.java diff -u lutinutil/src/java/org/codelutin/util/HashMapMultiKey.java:1.3 lutinutil/src/java/org/codelutin/util/HashMapMultiKey.java:1.4 --- lutinutil/src/java/org/codelutin/util/HashMapMultiKey.java:1.3 Thu Jul 28 20:03:03 2005 +++ lutinutil/src/java/org/codelutin/util/HashMapMultiKey.java Wed Oct 5 20:23:46 2005 @@ -23,30 +23,141 @@ * Created: 2 nov. 2004 * * @author Benjamin Poussin - * @version $Revision: 1.3 $ + * @version $Revision: 1.4 $ * - * Mise a jour: $Date: 2005/07/28 20:03:03 $ + * Mise a jour: $Date: 2005/10/05 20:23:46 $ * par : $Author: bpoussin $ */ package org.codelutin.util; import java.io.Serializable; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; -import java.util.LinkedList; +import java.util.Set; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; /** * Permet de stocker un element suivant un ensemble de cle. + * @TODO pour l'instant on ne gere pas les references sur les clef + * FIXME pas le temps d'implanter toutes les methodes pour un support + * complet des References. iterator(), entrySet(), ... peuvent ne pas + * fonctionner comme il faut, c-a-d qu'il retourne les references et non + * les objets. Mais les methodes simples fonctionnent: put, remove, get, ... */ public class HashMapMultiKey extends HashMap { // HashMapMultiKey + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(HashMapMultiKey.class); + + public static final Object HARD = null; + public static final Object SOFT = new Object(); + public static final Object WEAK = new Object(); + /** key: un objet, value une list de key pour la vrai hashmap */ protected HashMap keys = new HashMap(); + /** key: la valeur, valeur: la cle. Permet de supprimer rapidement une + * key lorsque la valeur disparait */ + protected HashMap valueToKey = new HashMap(); + protected ReferenceQueue refQueueValue = new ReferenceQueue(); - public HashMapMultiKey() { + protected Object keyType = null; + protected Object valueType = null; + + /** + * Si value est une reference et qu'il disparait alors la cle disparait + * Si key est une reference et qu'une de ses composantes disparait alors + * la cle et la valeur disparaissent. + * @param keyType le type de cle SOFT ou WEAK ou null + * @param valueType le type de valeur SOFT ou WEAK ou null + */ + public HashMapMultiKey(Object keyType, Object valueType) { super(); + this.keyType = keyType; + this.valueType = valueType; + } + + public HashMapMultiKey() { + this(null, null); + } + + /** + * Look in the queue if reference is available and remove reference in + * all map + */ + protected void cleanQueue(){ + Reference o = null; + while(null != (o = refQueueValue.poll())) { + if(log.isTraceEnabled()){ log.trace("clean the refQueueValue : " + o.hashCode());} + // suppression dans la table des values et recuperation de la cle + // associé + Object key = valueToKey.remove(o); + if( key != null) { + // suppression dans la table a partir de la cle recuperé + super.remove(key); + // suppression dans l'association des objets de la cle + for(Iterator i=((Key)key).iterator(); i.hasNext();){ + Set list = (Set)keys.get(i.next()); + if (list != null) { + list.remove(key); + } + } + } + } + + // TODO la meme chose ici pour la queue des cles + } + + /** + * Encapsule dans un objet Reference si besoin l'objet o + */ + protected Object refValue(Object o) { + Object result = o; + if (valueType == SOFT) { + result = new TransparenteSoftReference(o, refQueueValue); + } else if (valueType == WEAK) { + result = new TransparenteWeakReference(o, refQueueValue); + } + return result; + } + + protected Object derefValue(Object o) { + Object result = o; + if (valueType == SOFT && o != null) { + result = ((TransparenteSoftReference)o).get(); + } else if (valueType == WEAK && o != null) { + result = ((TransparenteWeakReference)o).get(); + } + return result; + } + + + /** + * Encapsule dans un objet Reference si besoin l'objet o + */ + protected Object refKey(Object o){ + Object result = o; + if (keyType == SOFT) { + result = new TransparenteSoftReference(o); + } else if (keyType == WEAK) { + result = new TransparenteWeakReference(o); + } + return result; + } + + protected Object derefKey(Object o) { + Object result = o; + if (keyType == SOFT && o != null) { + result = ((TransparenteSoftReference)o).get(); + } else if (keyType == WEAK && o != null) { + result = ((TransparenteWeakReference)o).get(); + } + return result; } /** @@ -56,10 +167,11 @@ * @return la liste des cles. Si aucune cle ne contient l'element e, * alors la liste retourné est vide */ - public LinkedList getKeys(Object e){ - LinkedList list = (LinkedList)keys.get(e); + public Set getKeys(Object e){ + cleanQueue(); + Set list = (Set)keys.get(e); if( list == null){ - list = new LinkedList(); + list = new HashSet(); keys.put(e, list); } return list; @@ -76,22 +188,37 @@ * une collection d'objet. */ public Object put(Object key, Object value){ + // a chaque fois que l'on ajoute, on nettoie un peu avant + cleanQueue(); if(key instanceof Key){ // ajout dans la hash des cles Key keyObject = (Key)key; for(int i=0; i * Copyright Code Lutin -* @version $Revision: 1.1 $ +* @version $Revision: 1.2 $ * -* Mise a jour: $Date: 2005/06/10 12:43:54 $ +* Mise a jour: $Date: 2005/10/05 20:23:46 $ * par : $Author: bpoussin $ */ package org.codelutin.util; import java.beans.Statement; import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; - import java.util.HashSet; import java.util.Iterator; @@ -41,6 +41,9 @@ * contenu. */ public class TransparenteSoftReference extends SoftReference { + + protected int hash = 0; + /** *DOCUMENTME Constructor for the TransparenteSoftReference object * @@ -48,38 +51,49 @@ */ public TransparenteSoftReference(Object o) { super(o); + init(o); } - /** - * DOCUMENTME Method - * - * @param o DOCUMENTME Description of the Parameter - * @return DOCUMENTME Description of the Return Value - */ - public boolean equals(Object o) { - // on travail avec un variable local pour ne pas etre obligé de - // synchroniser la méthode - Object local = get(); - if (o instanceof Reference) { - o = ((Reference)o).get(); - } - - return (o == null && local == null) - || (o != null && o.equals(local)); + public TransparenteSoftReference(Object o, ReferenceQueue queue) { + super(o, queue); + init(o); } /** - * DOCUMENTME Method - * - * @return DOCUMENTME Description of the Return Value + * On conserve le hash pour que la Reference puisse encore se faire + * passer pour l'objet alors que celui-ci a disparu de la memoire */ - public int hashCode() { - // on travail avec une variable local pour ne pas etre obligé de - // synchroniser la méthode - Object local = get(); - if (local == null) { - return 0; - } - return local.hashCode(); + protected void init(Object o){ + hash = o.hashCode(); } + + /** + * DOCUMENTME Method + * + * @param o DOCUMENTME Description of the Parameter + * @return DOCUMENTME Description of the Return Value + */ + public boolean equals(Object o) { + if (o == this) { + return true; + } + // on travail avec un variable local pour ne pas etre obligé de + // synchroniser la méthode + Object local = get(); + if (o instanceof Reference) { + o = ((Reference)o).get(); + } + + return (o == null && local == null) + || (o != null && o.equals(local)); + } + + /** + * DOCUMENTME Method + * + * @return DOCUMENTME Description of the Return Value + */ + public int hashCode() { + return hash; + } } Index: lutinutil/src/java/org/codelutin/util/TransparenteWeakReference.java diff -u lutinutil/src/java/org/codelutin/util/TransparenteWeakReference.java:1.1 lutinutil/src/java/org/codelutin/util/TransparenteWeakReference.java:1.2 --- lutinutil/src/java/org/codelutin/util/TransparenteWeakReference.java:1.1 Fri Jun 10 12:43:54 2005 +++ lutinutil/src/java/org/codelutin/util/TransparenteWeakReference.java Wed Oct 5 20:23:46 2005 @@ -22,16 +22,16 @@ * * @author Benjamin Poussin * Copyright Code Lutin -* @version $Revision: 1.1 $ +* @version $Revision: 1.2 $ * -* Mise a jour: $Date: 2005/06/10 12:43:54 $ +* Mise a jour: $Date: 2005/10/05 20:23:46 $ * par : $Author: bpoussin $ */ package org.codelutin.util; import java.beans.Statement; import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; - import java.util.HashSet; import java.util.Iterator; @@ -41,6 +41,9 @@ * contenu. */ public class TransparenteWeakReference extends WeakReference { + + protected int hash = 0; + /** *DOCUMENTME Constructor for the TransparenteWeakReference object * @@ -48,15 +51,29 @@ */ public TransparenteWeakReference(Object o) { super(o); + init(o); + } + + public TransparenteWeakReference(Object o, ReferenceQueue queue) { + super(o, queue); + init(o); } /** - * DOCUMENTME Method - * - * @param o DOCUMENTME Description of the Parameter - * @return DOCUMENTME Description of the Return Value + * On conserve le hash pour que la Reference puisse encore se faire + * passer pour l'objet alors que celui-ci a disparu de la memoire + */ + protected void init(Object o){ + hash = o.hashCode(); + } + + /** + * Equals si meme reference memoire on les objets references sont egauxs */ public boolean equals(Object o) { + if (o == this) { + return true; + } // on travail avec un variable local pour ne pas etre obligé de // synchroniser la méthode Object local = get(); @@ -74,12 +91,6 @@ * @return DOCUMENTME Description of the Return Value */ public int hashCode() { - // on travail avec une variable local pour ne pas etre obligé de - // synchroniser la méthode - Object local = get(); - if (local == null) { - return 0; - } - return local.hashCode(); + return hash; } }