KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > collections > map > MultiKeyMap


1 /*
2  * Copyright 2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.collections.map;
17
18 import java.io.Serializable JavaDoc;
19 import java.util.Collection JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.Map JavaDoc;
22 import java.util.Set JavaDoc;
23
24 import org.apache.commons.collections.IterableMap;
25 import org.apache.commons.collections.MapIterator;
26 import org.apache.commons.collections.keyvalue.MultiKey;
27
28 /**
29  * A <code>Map</code> implementation that uses multiple keys to map the value.
30  * <p>
31  * This class is the most efficient way to uses multiple keys to map to a value.
32  * The best way to use this class is via the additional map-style methods.
33  * These provide <code>get</code>, <code>containsKey</code>, <code>put</code> and
34  * <code>remove</code> for individual keys which operate without extra object creation.
35  * <p>
36  * The additional methods are the main interface of this map.
37  * As such, you will not normally hold this map in a variable of type <code>Map</code>.
38  * <p>
39  * The normal map methods take in and return a {@link MultiKey}.
40  * If you try to use <code>put()</code> with any other object type a
41  * <code>ClassCastException</code> is thrown. If you try to use <code>null</code> as
42  * the key in <code>put()</code> a <code>NullPointerException</code> is thrown.
43  * <p>
44  * This map is implemented as a decorator of a <code>AbstractHashedMap</code> which
45  * enables extra behaviour to be added easily.
46  * <ul>
47  * <li><code>MultiKeyMap.decorate(new LinkedMap())</code> creates an ordered map.
48  * <li><code>MultiKeyMap.decorate(new LRUMap())</code> creates an least recently used map.
49  * <li><code>MultiKeyMap.decorate(new ReferenceMap())</code> creates a garbage collector sensitive map.
50  * </ul>
51  * Note that <code>IdentityMap</code> and <code>ReferenceIdentityMap</code> are unsuitable
52  * for use as the key comparison would work on the whole MultiKey, not the elements within.
53  * <p>
54  * As an example, consider a least recently used cache that uses a String airline code
55  * and a Locale to lookup the airline's name:
56  * <pre>
57  * private MultiKeyMap cache = MultiKeyMap.decorate(new LRUMap(50));
58  *
59  * public String getAirlineName(String code, String locale) {
60  * String name = (String) cache.get(code, locale);
61  * if (name == null) {
62  * name = getAirlineNameFromDB(code, locale);
63  * cache.put(code, locale, name);
64  * }
65  * return name;
66  * }
67  * </pre>
68  *
69  * @since Commons Collections 3.1
70  * @version $Revision: 1.3 $ $Date: 2004/06/07 21:00:58 $
71  *
72  * @author Stephen Colebourne
73  */

74 public class MultiKeyMap
75         implements IterableMap, Serializable JavaDoc {
76
77     /** Serialisation version */
78     private static final long serialVersionUID = -1788199231038721040L;
79
80     /** The decorated map */
81     protected final AbstractHashedMap map;
82
83     //-----------------------------------------------------------------------
84
/**
85      * Decorates the specified map to add the MultiKeyMap API and fast query.
86      * The map must not be null and must be empty.
87      *
88      * @param map the map to decorate, not null
89      * @throws IllegalArgumentException if the map is null or not empty
90      */

91     public static MultiKeyMap decorate(AbstractHashedMap map) {
92         if (map == null) {
93             throw new IllegalArgumentException JavaDoc("Map must not be null");
94         }
95         if (map.size() > 0) {
96             throw new IllegalArgumentException JavaDoc("Map must be empty");
97         }
98         return new MultiKeyMap(map);
99     }
100
101     //-----------------------------------------------------------------------
102
/**
103      * Constructs a new MultiKeyMap that decorates a <code>HashedMap</code>.
104      */

105     public MultiKeyMap() {
106         super();
107         map = new HashedMap();
108     }
109
110     /**
111      * Constructor that decorates the specified map and is called from
112      * {@link #decorate(AbstractHashedMap)}.
113      * The map must not be null and should be empty or only contain valid keys.
114      * This constructor performs no validation.
115      *
116      * @param map the map to decorate
117      */

118     protected MultiKeyMap(AbstractHashedMap map) {
119         super();
120         this.map = map;
121     }
122
123     //-----------------------------------------------------------------------
124
/**
125      * Gets the value mapped to the specified multi-key.
126      *
127      * @param key1 the first key
128      * @param key2 the second key
129      * @return the mapped value, null if no match
130      */

131     public Object JavaDoc get(Object JavaDoc key1, Object JavaDoc key2) {
132         int hashCode = hash(key1, key2);
133         AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)];
134         while (entry != null) {
135             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2)) {
136                 return entry.getValue();
137             }
138             entry = entry.next;
139         }
140         return null;
141     }
142
143     /**
144      * Checks whether the map contains the specified multi-key.
145      *
146      * @param key1 the first key
147      * @param key2 the second key
148      * @return true if the map contains the key
149      */

150     public boolean containsKey(Object JavaDoc key1, Object JavaDoc key2) {
151         int hashCode = hash(key1, key2);
152         AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)];
153         while (entry != null) {
154             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2)) {
155                 return true;
156             }
157             entry = entry.next;
158         }
159         return false;
160     }
161
162     /**
163      * Stores the value against the specified multi-key.
164      *
165      * @param key1 the first key
166      * @param key2 the second key
167      * @param value the value to store
168      * @return the value previously mapped to this combined key, null if none
169      */

170     public Object JavaDoc put(Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc value) {
171         int hashCode = hash(key1, key2);
172         int index = map.hashIndex(hashCode, map.data.length);
173         AbstractHashedMap.HashEntry entry = map.data[index];
174         while (entry != null) {
175             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2)) {
176                 Object JavaDoc oldValue = entry.getValue();
177                 map.updateEntry(entry, value);
178                 return oldValue;
179             }
180             entry = entry.next;
181         }
182         
183         map.addMapping(index, hashCode, new MultiKey(key1, key2), value);
184         return null;
185     }
186
187     /**
188      * Removes the specified multi-key from this map.
189      *
190      * @param key1 the first key
191      * @param key2 the second key
192      * @return the value mapped to the removed key, null if key not in map
193      */

194     public Object JavaDoc remove(Object JavaDoc key1, Object JavaDoc key2) {
195         int hashCode = hash(key1, key2);
196         int index = map.hashIndex(hashCode, map.data.length);
197         AbstractHashedMap.HashEntry entry = map.data[index];
198         AbstractHashedMap.HashEntry previous = null;
199         while (entry != null) {
200             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2)) {
201                 Object JavaDoc oldValue = entry.getValue();
202                 map.removeMapping(entry, index, previous);
203                 return oldValue;
204             }
205             previous = entry;
206             entry = entry.next;
207         }
208         return null;
209     }
210
211     /**
212      * Gets the hash code for the specified multi-key.
213      *
214      * @param key1 the first key
215      * @param key2 the second key
216      * @return the hash code
217      */

218     protected int hash(Object JavaDoc key1, Object JavaDoc key2) {
219         int h = 0;
220         if (key1 != null) {
221             h ^= key1.hashCode();
222         }
223         if (key2 != null) {
224             h ^= key2.hashCode();
225         }
226         h += ~(h << 9);
227         h ^= (h >>> 14);
228         h += (h << 4);
229         h ^= (h >>> 10);
230         return h;
231     }
232
233     /**
234      * Is the key equal to the combined key.
235      *
236      * @param entry the entry to compare to
237      * @param key1 the first key
238      * @param key2 the second key
239      * @return true if the key matches
240      */

241     protected boolean isEqualKey(AbstractHashedMap.HashEntry entry, Object JavaDoc key1, Object JavaDoc key2) {
242         MultiKey multi = (MultiKey) entry.getKey();
243         return
244             multi.size() == 2 &&
245             (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) &&
246             (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1)));
247     }
248
249     //-----------------------------------------------------------------------
250
/**
251      * Gets the value mapped to the specified multi-key.
252      *
253      * @param key1 the first key
254      * @param key2 the second key
255      * @param key3 the third key
256      * @return the mapped value, null if no match
257      */

258     public Object JavaDoc get(Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3) {
259         int hashCode = hash(key1, key2, key3);
260         AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)];
261         while (entry != null) {
262             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3)) {
263                 return entry.getValue();
264             }
265             entry = entry.next;
266         }
267         return null;
268     }
269
270     /**
271      * Checks whether the map contains the specified multi-key.
272      *
273      * @param key1 the first key
274      * @param key2 the second key
275      * @param key3 the third key
276      * @return true if the map contains the key
277      */

278     public boolean containsKey(Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3) {
279         int hashCode = hash(key1, key2, key3);
280         AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)];
281         while (entry != null) {
282             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3)) {
283                 return true;
284             }
285             entry = entry.next;
286         }
287         return false;
288     }
289
290     /**
291      * Stores the value against the specified multi-key.
292      *
293      * @param key1 the first key
294      * @param key2 the second key
295      * @param key3 the third key
296      * @param value the value to store
297      * @return the value previously mapped to this combined key, null if none
298      */

299     public Object JavaDoc put(Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3, Object JavaDoc value) {
300         int hashCode = hash(key1, key2, key3);
301         int index = map.hashIndex(hashCode, map.data.length);
302         AbstractHashedMap.HashEntry entry = map.data[index];
303         while (entry != null) {
304             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3)) {
305                 Object JavaDoc oldValue = entry.getValue();
306                 map.updateEntry(entry, value);
307                 return oldValue;
308             }
309             entry = entry.next;
310         }
311         
312         map.addMapping(index, hashCode, new MultiKey(key1, key2, key3), value);
313         return null;
314     }
315
316     /**
317      * Removes the specified multi-key from this map.
318      *
319      * @param key1 the first key
320      * @param key2 the second key
321      * @param key3 the third key
322      * @return the value mapped to the removed key, null if key not in map
323      */

324     public Object JavaDoc remove(Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3) {
325         int hashCode = hash(key1, key2, key3);
326         int index = map.hashIndex(hashCode, map.data.length);
327         AbstractHashedMap.HashEntry entry = map.data[index];
328         AbstractHashedMap.HashEntry previous = null;
329         while (entry != null) {
330             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3)) {
331                 Object JavaDoc oldValue = entry.getValue();
332                 map.removeMapping(entry, index, previous);
333                 return oldValue;
334             }
335             previous = entry;
336             entry = entry.next;
337         }
338         return null;
339     }
340
341     /**
342      * Gets the hash code for the specified multi-key.
343      *
344      * @param key1 the first key
345      * @param key2 the second key
346      * @param key3 the third key
347      * @return the hash code
348      */

349     protected int hash(Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3) {
350         int h = 0;
351         if (key1 != null) {
352             h ^= key1.hashCode();
353         }
354         if (key2 != null) {
355             h ^= key2.hashCode();
356         }
357         if (key3 != null) {
358             h ^= key3.hashCode();
359         }
360         h += ~(h << 9);
361         h ^= (h >>> 14);
362         h += (h << 4);
363         h ^= (h >>> 10);
364         return h;
365     }
366
367     /**
368      * Is the key equal to the combined key.
369      *
370      * @param entry the entry to compare to
371      * @param key1 the first key
372      * @param key2 the second key
373      * @param key3 the third key
374      * @return true if the key matches
375      */

376     protected boolean isEqualKey(AbstractHashedMap.HashEntry entry, Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3) {
377         MultiKey multi = (MultiKey) entry.getKey();
378         return
379             multi.size() == 3 &&
380             (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) &&
381             (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) &&
382             (key3 == null ? multi.getKey(2) == null : key3.equals(multi.getKey(2)));
383     }
384
385     //-----------------------------------------------------------------------
386
/**
387      * Gets the value mapped to the specified multi-key.
388      *
389      * @param key1 the first key
390      * @param key2 the second key
391      * @param key3 the third key
392      * @param key4 the fourth key
393      * @return the mapped value, null if no match
394      */

395     public Object JavaDoc get(Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3, Object JavaDoc key4) {
396         int hashCode = hash(key1, key2, key3, key4);
397         AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)];
398         while (entry != null) {
399             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4)) {
400                 return entry.getValue();
401             }
402             entry = entry.next;
403         }
404         return null;
405     }
406
407     /**
408      * Checks whether the map contains the specified multi-key.
409      *
410      * @param key1 the first key
411      * @param key2 the second key
412      * @param key3 the third key
413      * @param key4 the fourth key
414      * @return true if the map contains the key
415      */

416     public boolean containsKey(Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3, Object JavaDoc key4) {
417         int hashCode = hash(key1, key2, key3, key4);
418         AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)];
419         while (entry != null) {
420             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4)) {
421                 return true;
422             }
423             entry = entry.next;
424         }
425         return false;
426     }
427
428     /**
429      * Stores the value against the specified multi-key.
430      *
431      * @param key1 the first key
432      * @param key2 the second key
433      * @param key3 the third key
434      * @param key4 the fourth key
435      * @param value the value to store
436      * @return the value previously mapped to this combined key, null if none
437      */

438     public Object JavaDoc put(Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3, Object JavaDoc key4, Object JavaDoc value) {
439         int hashCode = hash(key1, key2, key3, key4);
440         int index = map.hashIndex(hashCode, map.data.length);
441         AbstractHashedMap.HashEntry entry = map.data[index];
442         while (entry != null) {
443             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4)) {
444                 Object JavaDoc oldValue = entry.getValue();
445                 map.updateEntry(entry, value);
446                 return oldValue;
447             }
448             entry = entry.next;
449         }
450         
451         map.addMapping(index, hashCode, new MultiKey(key1, key2, key3, key4), value);
452         return null;
453     }
454
455     /**
456      * Removes the specified multi-key from this map.
457      *
458      * @param key1 the first key
459      * @param key2 the second key
460      * @param key3 the third key
461      * @param key4 the fourth key
462      * @return the value mapped to the removed key, null if key not in map
463      */

464     public Object JavaDoc remove(Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3, Object JavaDoc key4) {
465         int hashCode = hash(key1, key2, key3, key4);
466         int index = map.hashIndex(hashCode, map.data.length);
467         AbstractHashedMap.HashEntry entry = map.data[index];
468         AbstractHashedMap.HashEntry previous = null;
469         while (entry != null) {
470             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4)) {
471                 Object JavaDoc oldValue = entry.getValue();
472                 map.removeMapping(entry, index, previous);
473                 return oldValue;
474             }
475             previous = entry;
476             entry = entry.next;
477         }
478         return null;
479     }
480
481     /**
482      * Gets the hash code for the specified multi-key.
483      *
484      * @param key1 the first key
485      * @param key2 the second key
486      * @param key3 the third key
487      * @param key4 the fourth key
488      * @return the hash code
489      */

490     protected int hash(Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3, Object JavaDoc key4) {
491         int h = 0;
492         if (key1 != null) {
493             h ^= key1.hashCode();
494         }
495         if (key2 != null) {
496             h ^= key2.hashCode();
497         }
498         if (key3 != null) {
499             h ^= key3.hashCode();
500         }
501         if (key4 != null) {
502             h ^= key4.hashCode();
503         }
504         h += ~(h << 9);
505         h ^= (h >>> 14);
506         h += (h << 4);
507         h ^= (h >>> 10);
508         return h;
509     }
510
511     /**
512      * Is the key equal to the combined key.
513      *
514      * @param entry the entry to compare to
515      * @param key1 the first key
516      * @param key2 the second key
517      * @param key3 the third key
518      * @param key4 the fourth key
519      * @return true if the key matches
520      */

521     protected boolean isEqualKey(AbstractHashedMap.HashEntry entry, Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3, Object JavaDoc key4) {
522         MultiKey multi = (MultiKey) entry.getKey();
523         return
524             multi.size() == 4 &&
525             (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) &&
526             (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) &&
527             (key3 == null ? multi.getKey(2) == null : key3.equals(multi.getKey(2))) &&
528             (key4 == null ? multi.getKey(3) == null : key4.equals(multi.getKey(3)));
529     }
530
531     //-----------------------------------------------------------------------
532
/**
533      * Gets the value mapped to the specified multi-key.
534      *
535      * @param key1 the first key
536      * @param key2 the second key
537      * @param key3 the third key
538      * @param key4 the fourth key
539      * @param key5 the fifth key
540      * @return the mapped value, null if no match
541      */

542     public Object JavaDoc get(Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3, Object JavaDoc key4, Object JavaDoc key5) {
543         int hashCode = hash(key1, key2, key3, key4, key5);
544         AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)];
545         while (entry != null) {
546             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4, key5)) {
547                 return entry.getValue();
548             }
549             entry = entry.next;
550         }
551         return null;
552     }
553
554     /**
555      * Checks whether the map contains the specified multi-key.
556      *
557      * @param key1 the first key
558      * @param key2 the second key
559      * @param key3 the third key
560      * @param key4 the fourth key
561      * @param key5 the fifth key
562      * @return true if the map contains the key
563      */

564     public boolean containsKey(Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3, Object JavaDoc key4, Object JavaDoc key5) {
565         int hashCode = hash(key1, key2, key3, key4, key5);
566         AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)];
567         while (entry != null) {
568             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4, key5)) {
569                 return true;
570             }
571             entry = entry.next;
572         }
573         return false;
574     }
575
576     /**
577      * Stores the value against the specified multi-key.
578      *
579      * @param key1 the first key
580      * @param key2 the second key
581      * @param key3 the third key
582      * @param key4 the fourth key
583      * @param key5 the fifth key
584      * @param value the value to store
585      * @return the value previously mapped to this combined key, null if none
586      */

587     public Object JavaDoc put(Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3, Object JavaDoc key4, Object JavaDoc key5, Object JavaDoc value) {
588         int hashCode = hash(key1, key2, key3, key4, key5);
589         int index = map.hashIndex(hashCode, map.data.length);
590         AbstractHashedMap.HashEntry entry = map.data[index];
591         while (entry != null) {
592             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4, key5)) {
593                 Object JavaDoc oldValue = entry.getValue();
594                 map.updateEntry(entry, value);
595                 return oldValue;
596             }
597             entry = entry.next;
598         }
599         
600         map.addMapping(index, hashCode, new MultiKey(key1, key2, key3, key4, key5), value);
601         return null;
602     }
603
604     /**
605      * Removes the specified multi-key from this map.
606      *
607      * @param key1 the first key
608      * @param key2 the second key
609      * @param key3 the third key
610      * @param key4 the fourth key
611      * @param key5 the fifth key
612      * @return the value mapped to the removed key, null if key not in map
613      */

614     public Object JavaDoc remove(Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3, Object JavaDoc key4, Object JavaDoc key5) {
615         int hashCode = hash(key1, key2, key3, key4, key5);
616         int index = map.hashIndex(hashCode, map.data.length);
617         AbstractHashedMap.HashEntry entry = map.data[index];
618         AbstractHashedMap.HashEntry previous = null;
619         while (entry != null) {
620             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4, key5)) {
621                 Object JavaDoc oldValue = entry.getValue();
622                 map.removeMapping(entry, index, previous);
623                 return oldValue;
624             }
625             previous = entry;
626             entry = entry.next;
627         }
628         return null;
629     }
630
631     /**
632      * Gets the hash code for the specified multi-key.
633      *
634      * @param key1 the first key
635      * @param key2 the second key
636      * @param key3 the third key
637      * @param key4 the fourth key
638      * @param key5 the fifth key
639      * @return the hash code
640      */

641     protected int hash(Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3, Object JavaDoc key4, Object JavaDoc key5) {
642         int h = 0;
643         if (key1 != null) {
644             h ^= key1.hashCode();
645         }
646         if (key2 != null) {
647             h ^= key2.hashCode();
648         }
649         if (key3 != null) {
650             h ^= key3.hashCode();
651         }
652         if (key4 != null) {
653             h ^= key4.hashCode();
654         }
655         if (key5 != null) {
656             h ^= key5.hashCode();
657         }
658         h += ~(h << 9);
659         h ^= (h >>> 14);
660         h += (h << 4);
661         h ^= (h >>> 10);
662         return h;
663     }
664
665     /**
666      * Is the key equal to the combined key.
667      *
668      * @param entry the entry to compare to
669      * @param key1 the first key
670      * @param key2 the second key
671      * @param key3 the third key
672      * @param key4 the fourth key
673      * @param key5 the fifth key
674      * @return true if the key matches
675      */

676     protected boolean isEqualKey(AbstractHashedMap.HashEntry entry, Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3, Object JavaDoc key4, Object JavaDoc key5) {
677         MultiKey multi = (MultiKey) entry.getKey();
678         return
679             multi.size() == 5 &&
680             (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) &&
681             (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) &&
682             (key3 == null ? multi.getKey(2) == null : key3.equals(multi.getKey(2))) &&
683             (key4 == null ? multi.getKey(3) == null : key4.equals(multi.getKey(3))) &&
684             (key5 == null ? multi.getKey(4) == null : key5.equals(multi.getKey(4)));
685     }
686
687     //-----------------------------------------------------------------------
688
/**
689      * Removes all mappings where the first key is that specified.
690      * <p>
691      * This method removes all the mappings where the <code>MultiKey</code>
692      * has one or more keys, and the first matches that specified.
693      *
694      * @param key1 the first key
695      * @return true if any elements were removed
696      */

697     public boolean removeAll(Object JavaDoc key1) {
698         boolean modified = false;
699         MapIterator it = mapIterator();
700         while (it.hasNext()) {
701             MultiKey multi = (MultiKey) it.next();
702             if (multi.size() >= 1 &&
703                 (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0)))) {
704                 it.remove();
705                 modified = true;
706             }
707         }
708         return modified;
709     }
710
711     /**
712      * Removes all mappings where the first two keys are those specified.
713      * <p>
714      * This method removes all the mappings where the <code>MultiKey</code>
715      * has two or more keys, and the first two match those specified.
716      *
717      * @param key1 the first key
718      * @param key2 the second key
719      * @return true if any elements were removed
720      */

721     public boolean removeAll(Object JavaDoc key1, Object JavaDoc key2) {
722         boolean modified = false;
723         MapIterator it = mapIterator();
724         while (it.hasNext()) {
725             MultiKey multi = (MultiKey) it.next();
726             if (multi.size() >= 2 &&
727                 (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) &&
728                 (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1)))) {
729                 it.remove();
730                 modified = true;
731             }
732         }
733         return modified;
734     }
735
736     /**
737      * Removes all mappings where the first three keys are those specified.
738      * <p>
739      * This method removes all the mappings where the <code>MultiKey</code>
740      * has three or more keys, and the first three match those specified.
741      *
742      * @param key1 the first key
743      * @param key2 the second key
744      * @param key3 the third key
745      * @return true if any elements were removed
746      */

747     public boolean removeAll(Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3) {
748         boolean modified = false;
749         MapIterator it = mapIterator();
750         while (it.hasNext()) {
751             MultiKey multi = (MultiKey) it.next();
752             if (multi.size() >= 3 &&
753                 (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) &&
754                 (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) &&
755                 (key3 == null ? multi.getKey(2) == null : key3.equals(multi.getKey(2)))) {
756                 it.remove();
757                 modified = true;
758             }
759         }
760         return modified;
761     }
762
763     /**
764      * Removes all mappings where the first four keys are those specified.
765      * <p>
766      * This method removes all the mappings where the <code>MultiKey</code>
767      * has four or more keys, and the first four match those specified.
768      *
769      * @param key1 the first key
770      * @param key2 the second key
771      * @param key3 the third key
772      * @param key4 the fourth key
773      * @return true if any elements were removed
774      */

775     public boolean removeAll(Object JavaDoc key1, Object JavaDoc key2, Object JavaDoc key3, Object JavaDoc key4) {
776         boolean modified = false;
777         MapIterator it = mapIterator();
778         while (it.hasNext()) {
779             MultiKey multi = (MultiKey) it.next();
780             if (multi.size() >= 4 &&
781                 (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) &&
782                 (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) &&
783                 (key3 == null ? multi.getKey(2) == null : key3.equals(multi.getKey(2))) &&
784                 (key4 == null ? multi.getKey(3) == null : key4.equals(multi.getKey(3)))) {
785                 it.remove();
786                 modified = true;
787             }
788         }
789         return modified;
790     }
791
792     //-----------------------------------------------------------------------
793
/**
794      * Check to ensure that input keys are valid MultiKey objects.
795      *
796      * @param key the key to check
797      */

798     protected void checkKey(Object JavaDoc key) {
799         if (key == null) {
800             throw new NullPointerException JavaDoc("Key must not be null");
801         }
802         if (key instanceof MultiKey == false) {
803             throw new ClassCastException JavaDoc("Key must be a MultiKey");
804         }
805     }
806
807     /**
808      * Clones the map without cloning the keys or values.
809      *
810      * @return a shallow clone
811      */

812     public Object JavaDoc clone() {
813         return new MultiKeyMap((AbstractHashedMap) map.clone());
814     }
815
816     /**
817      * Puts the key and value into the map, where the key must be a non-null
818      * MultiKey object.
819      *
820      * @param key the non-null MultiKey object
821      * @param value the value to store
822      * @return the previous value for the key
823      * @throws NullPointerException if the key is null
824      * @throws ClassCastException if the key is not a MultiKey
825      */

826     public Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
827         checkKey(key);
828         return map.put(key, value);
829     }
830
831     /**
832      * Puts all the keys and values into this map.
833      * Each key must be non-null and a MultiKey object.
834      *
835      * @param key the non-null MultiKey object
836      * @param value the value to store
837      * @return the previous value for the key
838      * @throws NullPointerException if the mapToCopy or any key within is null
839      * @throws ClassCastException if any key is not a MultiKey
840      */

841     public void putAll(Map JavaDoc mapToCopy) {
842         for (Iterator JavaDoc it = mapToCopy.keySet().iterator(); it.hasNext();) {
843             Object JavaDoc key = it.next();
844             checkKey(key);
845         }
846         map.putAll(mapToCopy);
847     }
848
849     //-----------------------------------------------------------------------
850
public MapIterator mapIterator() {
851         return map.mapIterator();
852     }
853
854     public int size() {
855         return map.size();
856     }
857
858     public boolean isEmpty() {
859         return map.isEmpty();
860     }
861
862     public boolean containsKey(Object JavaDoc key) {
863         return map.containsKey(key);
864     }
865
866     public boolean containsValue(Object JavaDoc value) {
867         return map.containsValue(value);
868     }
869
870     public Object JavaDoc get(Object JavaDoc key) {
871         return map.get(key);
872     }
873
874     public Object JavaDoc remove(Object JavaDoc key) {
875         return map.remove(key);
876     }
877
878     public void clear() {
879         map.clear();
880     }
881
882     public Set JavaDoc keySet() {
883         return map.keySet();
884     }
885
886     public Collection JavaDoc values() {
887         return map.values();
888     }
889
890     public Set JavaDoc entrySet() {
891         return map.entrySet();
892     }
893
894     public boolean equals(Object JavaDoc obj) {
895         if (obj == this) {
896             return true;
897         }
898         return map.equals(obj);
899     }
900
901     public int hashCode() {
902         return map.hashCode();
903     }
904
905     public String JavaDoc toString() {
906         return map.toString();
907     }
908
909 }
910
Popular Tags