View Javadoc
1   /*
2    * #%L
3    * Nuiton Utils
4    * %%
5    * Copyright (C) 2004 - 2010 CodeLutin
6    * %%
7    * This program is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU Lesser General Public License as 
9    * published by the Free Software Foundation, either version 3 of the 
10   * License, or (at your option) any later version.
11   * 
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Lesser Public License for more details.
16   * 
17   * You should have received a copy of the GNU General Lesser Public 
18   * License along with this program.  If not, see
19   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
20   * #L%
21   */
22  
23  /* *
24   * TransparenteWeakReference.java
25   *
26   * Created: 10 mai 2004
27   *
28   * @author Benjamin Poussin - poussin@codelutin.com
29   * Copyright Code Lutin
30   *
31   *
32   * Mise a jour: $Date$
33   * par : */
34  package org.nuiton.util;
35  
36  import java.lang.ref.Reference;
37  import java.lang.ref.ReferenceQueue;
38  import java.lang.ref.WeakReference;
39  
40  /**
41   * Cette classe etant WeakReference et surcharge les méthodes equals et
42   * hashCode pour que ces méthodes retournes les mêmes résultat que les objets
43   * contenu.
44   *
45   * @param <T> type of object
46   */
47  public class TransparenteWeakReference<T> extends WeakReference<T> {
48  
49      protected int hash;
50  
51      protected String toString;
52  
53      protected boolean objectToStringUsed = true;
54  
55      public TransparenteWeakReference(T o) {
56          this(o, true);
57      }
58  
59      public TransparenteWeakReference(T o, ReferenceQueue<? super T> queue) {
60          this(o, queue, true);
61      }
62  
63      /**
64       * @param o                  TODO ?
65       * @param objectToStringUsed if true, this ref used toString method of
66       *                           encapsulated object otherwize used default Object toString
67       */
68      public TransparenteWeakReference(T o, boolean objectToStringUsed) {
69          super(o);
70          init(o, objectToStringUsed);
71      }
72  
73      public TransparenteWeakReference(T o,
74                                       ReferenceQueue<? super T> queue,
75                                       boolean objectToStringUsed) {
76          super(o, queue);
77          init(o, objectToStringUsed);
78      }
79  
80      /**
81       * On conserve le hash pour que la Reference puisse encore se faire
82       * passer pour l'objet alors que celui-ci a disparu de la memoire
83       *
84       * @param o                  TODO ?
85       * @param objectToStringUsed TODO ?
86       */
87      protected void init(T o, boolean objectToStringUsed) {
88          if (o == null) {
89              hash = 0;
90          } else {
91              hash = o.hashCode();
92              if (objectToStringUsed) {
93                  toString = o.toString();
94              }
95              if (toString == null) {
96                  toString = o.getClass().getName() + '@' +
97                             Integer.toHexString(hash);
98              }
99              if (toString.length() > 100) {
100                 toString = toString.substring(0, 100) + "...";
101             }
102         }
103     }
104 
105     /**
106      * @param o l'objet a comparer
107      * @return {@code true} si meme reference memoire on les objets
108      *         references sont egaux
109      */
110     @Override
111     public boolean equals(Object o) {
112         if (o == this) {
113             return true;
114         }
115         // on travail avec un variable local pour ne pas etre obligé de
116         // synchroniser la méthode
117         Object local = get();
118         Object other = o;
119         if (o instanceof Reference<?>) {
120             other = ((Reference<?>) o).get();
121 
122             if (other == null) {
123                 // on fait l'egalite sur les hash car on a perdu les objets
124                 return o.hashCode() == hashCode();
125             }
126         }
127 
128         return other == null && local == null ||
129                other != null && other.equals(local);
130     }
131 
132     @Override
133     public int hashCode() {
134         return hash;
135     }
136 
137     @Override
138     public String toString() {
139         return toString;
140     }
141 }