Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/go/trove/util/NullKeyMap.java


1   /* ====================================================================
2    * Trove - Copyright (c) 1997-2000 Walt Disney Internet Group
3    * ====================================================================
4    * The Tea Software License, Version 1.1
5    *
6    * Copyright (c) 2000 Walt Disney Internet Group. All rights reserved.
7    *
8    * Redistribution and use in source and binary forms, with or without
9    * modification, are permitted provided that the following conditions
10   * are met:
11   *
12   * 1. Redistributions of source code must retain the above copyright
13   *    notice, this list of conditions and the following disclaimer.
14   *
15   * 2. Redistributions in binary form must reproduce the above copyright
16   *    notice, this list of conditions and the following disclaimer in
17   *    the documentation and/or other materials provided with the
18   *    distribution.
19   *
20   * 3. The end-user documentation included with the redistribution,
21   *    if any, must include the following acknowledgment:
22   *       "This product includes software developed by the
23   *        Walt Disney Internet Group (http://opensource.go.com/)."
24   *    Alternately, this acknowledgment may appear in the software itself,
25   *    if and wherever such third-party acknowledgments normally appear.
26   *
27   * 4. The names "Tea", "TeaServlet", "Kettle", "Trove" and "BeanDoc" must
28   *    not be used to endorse or promote products derived from this
29   *    software without prior written permission. For written
30   *    permission, please contact opensource@dig.com.
31   *
32   * 5. Products derived from this software may not be called "Tea",
33   *    "TeaServlet", "Kettle" or "Trove", nor may "Tea", "TeaServlet",
34   *    "Kettle", "Trove" or "BeanDoc" appear in their name, without prior
35   *    written permission of the Walt Disney Internet Group.
36   *
37   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40   * DISCLAIMED.  IN NO EVENT SHALL THE WALT DISNEY INTERNET GROUP OR ITS
41   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
42   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
43   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
44   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45   * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
46   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
47   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48   * ====================================================================
49   *
50   * For more information about Tea, please see http://opensource.go.com/.
51   */
52  
53  package com.go.trove.util;
54  
55  import java.util.*;
56  import java.io.Serializable;
57  
58  /******************************************************************************
59   * A Map supporting null keys that wraps a Map that doesn't support null keys.
60   * NullKeyMap substitutes null keys with a special placeholder object. This
61   * technique does not work when the wrapped Map is a TreeMap because it cannot
62   * be compared against other objects. In order for TreeMaps to support null
63   * keys, use any of the null ordering comparators found in the {@link Utils}
64   * class.
65   *
66   * @author Brian S O'Neill
67   * @version
68   * <!--$$Revision:--> 9 <!-- $-->, <!--$$JustDate:-->  9/07/00 <!-- $-->
69   */
70  public class NullKeyMap extends AbstractMap implements Serializable {
71      // Instead of using null as a key, use this placeholder.
72      private static final Object NULL = new Serializable() {};
73  
74      private Map mMap;
75  
76      private transient Set mKeySet;
77      private transient Set mEntrySet;
78  
79      /**
80       * @param map The map to wrap.
81       */
82      public NullKeyMap(Map map) {
83          mMap = map;
84      }
85      
86      public int size() {
87          return mMap.size();
88      }
89  
90      public boolean isEmpty() {
91          return mMap.isEmpty();
92      }
93  
94      public boolean containsKey(Object key) {
95          return (key == null) ? mMap.containsKey(NULL) : mMap.containsKey(key);
96      }
97  
98      public boolean containsValue(Object value) {
99          return mMap.containsValue(value);
100     }
101 
102     public Object get(Object key) {
103         return (key == null) ? mMap.get(NULL) : mMap.get(key);
104     }
105 
106     public Object put(Object key, Object value) {
107         return mMap.put((key == null) ? NULL : key, value);
108     }
109 
110     public Object remove(Object key) {
111         return (key == null) ? mMap.remove(NULL) : mMap.remove(key);
112     }
113 
114     public void putAll(Map map) {
115         Iterator it = map.entrySet().iterator();
116         while (it.hasNext()) {
117             Map.Entry entry = (Map.Entry)it.next();
118             put(entry.getKey(), entry.getValue());
119         }
120     }
121 
122     public void clear() {
123         mMap.clear();
124     }
125 
126     public Set keySet() {
127         if (mKeySet == null) {
128             mKeySet = new AbstractSet() {
129                 public Iterator iterator() {
130                     final Iterator it = mMap.keySet().iterator();
131 
132                     return new Iterator() {
133                         public boolean hasNext() {
134                             return it.hasNext();
135                         }
136 
137                         public Object next() {
138                             Object key = it.next();
139                             return (key == NULL) ? null : key;
140                         }
141 
142                         public void remove() {
143                             it.remove();
144                         }
145                     };
146                 }
147                 
148                 public boolean contains(Object key) {
149                     return containsKey((key == null) ? NULL : key);
150                 }
151 
152                 public boolean remove(Object key) {
153                     if (key == null) {
154                         key = NULL;
155                     }
156                     if (containsKey(key)) {
157                         NullKeyMap.this.remove(key);
158                         return true;
159                     }
160                     else {
161                         return false;
162                     }
163                 }
164 
165                 public int size() {
166                     return NullKeyMap.this.size();
167                 }
168                 
169                 public void clear() {
170                     NullKeyMap.this.clear();
171                 }
172             };
173         }
174 
175         return mKeySet;
176     }
177 
178     public Collection values() {
179         return mMap.values();
180     }
181 
182     public Set entrySet() {
183         if (mEntrySet == null) {
184             mEntrySet = new AbstractSet() {
185                 public Iterator iterator() {
186                     final Iterator it = mMap.entrySet().iterator();
187 
188                     return new Iterator() {
189                         public boolean hasNext() {
190                             return it.hasNext();
191                         }
192 
193                         public Object next() {
194                             final Map.Entry entry = (Map.Entry)it.next();
195                             if (entry.getKey() == NULL) {
196                                 return new AbstractMapEntry() {
197                                     public Object getKey() {
198                                         return null;
199                                     }
200 
201                                     public Object getValue() {
202                                         return entry.getValue();
203                                     }
204 
205                                     public Object setValue(Object value) {
206                                         return entry.setValue(value);
207                                     }
208                                 };
209                             }
210                             else {
211                                 return entry;
212                             }
213                         }
214 
215                         public void remove() {
216                             it.remove();
217                         }
218                     };
219                 }
220                 
221                 public boolean contains(Object obj) {
222                     if (!(obj instanceof Map.Entry)) {
223                         return false;
224                     }
225                     Map.Entry entry = (Map.Entry)obj;
226                     Object key = entry.getKey();
227                     Object value = entry.getValue();
228                     if (key == null) {
229                         key = NULL;
230                     }
231                     Object lookup = get(key);
232                     if (lookup == null) {
233                         return value == null;
234                     }
235                     else {
236                         return lookup.equals(value);
237                     }
238                 }
239 
240                 public boolean remove(Object obj) {
241                     if (!(obj instanceof Map.Entry)) {
242                         return false;
243                     }
244                     Map.Entry entry = ((Map.Entry)obj);
245                     Object key = entry.getKey();
246                     if (key == null) {
247                         key = NULL;
248                     }
249                     if (containsKey(key)) {
250                         NullKeyMap.this.remove(key);
251                         return true;
252                     }
253                     else {
254                         return false;
255                     }
256                 }
257 
258                 public int size() {
259                     return NullKeyMap.this.size();
260                 }
261                 
262                 public void clear() {
263                     NullKeyMap.this.clear();
264                 }
265             };
266         }
267 
268         return mEntrySet;
269     }
270 }