KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > collections > MapUtils


1 /*
2  * Copyright 2001-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;
17
18 import java.io.PrintStream JavaDoc;
19 import java.text.NumberFormat JavaDoc;
20 import java.text.ParseException JavaDoc;
21 import java.util.Collections JavaDoc;
22 import java.util.Enumeration JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.Map JavaDoc;
26 import java.util.Properties JavaDoc;
27 import java.util.ResourceBundle JavaDoc;
28 import java.util.SortedMap JavaDoc;
29 import java.util.TreeMap JavaDoc;
30
31 import org.apache.commons.collections.map.FixedSizeMap;
32 import org.apache.commons.collections.map.FixedSizeSortedMap;
33 import org.apache.commons.collections.map.LazyMap;
34 import org.apache.commons.collections.map.LazySortedMap;
35 import org.apache.commons.collections.map.ListOrderedMap;
36 import org.apache.commons.collections.map.PredicatedMap;
37 import org.apache.commons.collections.map.PredicatedSortedMap;
38 import org.apache.commons.collections.map.TransformedMap;
39 import org.apache.commons.collections.map.TransformedSortedMap;
40 import org.apache.commons.collections.map.TypedMap;
41 import org.apache.commons.collections.map.TypedSortedMap;
42 import org.apache.commons.collections.map.UnmodifiableMap;
43 import org.apache.commons.collections.map.UnmodifiableSortedMap;
44
45 /**
46  * Provides utility methods and decorators for
47  * {@link Map} and {@link SortedMap} instances.
48  * <p>
49  * It contains various type safe methods
50  * as well as other useful features like deep copying.
51  * <p>
52  * It also provides the following decorators:
53  *
54  * <ul>
55  * <li>{@link #fixedSizeMap(Map)}
56  * <li>{@link #fixedSizeSortedMap(SortedMap)}
57  * <li>{@link #lazyMap(Map,Factory)}
58  * <li>{@link #lazyMap(Map,Transformer)}
59  * <li>{@link #lazySortedMap(SortedMap,Factory)}
60  * <li>{@link #lazySortedMap(SortedMap,Transformer)}
61  * <li>{@link #predicatedMap(Map,Predicate,Predicate)}
62  * <li>{@link #predicatedSortedMap(SortedMap,Predicate,Predicate)}
63  * <li>{@link #transformedMap(Map, Transformer, Transformer)}
64  * <li>{@link #transformedSortedMap(SortedMap, Transformer, Transformer)}
65  * <li>{@link #typedMap(Map, Class, Class)}
66  * <li>{@link #typedSortedMap(SortedMap, Class, Class)}
67  * </ul>
68  *
69  * @since Commons Collections 1.0
70  * @version $Revision: 1.46 $ $Date: 2004/04/21 20:34:11 $
71  *
72  * @author <a HREF="mailto:jstrachan@apache.org">James Strachan</a>
73  * @author <a HREF="mailto:nissim@nksystems.com">Nissim Karpenstein</a>
74  * @author <a HREF="mailto:knielsen@apache.org">Kasper Nielsen</a>
75  * @author Paul Jack
76  * @author Stephen Colebourne
77  * @author Matthew Hawthorne
78  * @author Arun Mammen Thomas
79  * @author Janek Bogucki
80  * @author Max Rydahl Andersen
81  * @author <a HREF="mailto:equinus100@hotmail.com">Ashwin S</a>
82  */

83 public class MapUtils {
84     
85     /**
86      * An empty unmodifiable map.
87      * This was not provided in JDK1.2.
88      */

89     public static final Map JavaDoc EMPTY_MAP = UnmodifiableMap.decorate(new HashMap JavaDoc(1));
90     /**
91      * An empty unmodifiable sorted map.
92      * This is not provided in the JDK.
93      */

94     public static final SortedMap JavaDoc EMPTY_SORTED_MAP = UnmodifiableSortedMap.decorate(new TreeMap JavaDoc());
95     /**
96      * String used to indent the verbose and debug Map prints.
97      */

98     private static final String JavaDoc INDENT_STRING = " ";
99
100     /**
101      * <code>MapUtils</code> should not normally be instantiated.
102      */

103     public MapUtils() {
104     }
105     
106     // Type safe getters
107
//-------------------------------------------------------------------------
108
/**
109      * Gets from a Map in a null-safe manner.
110      *
111      * @param map the map to use
112      * @param key the key to look up
113      * @return the value in the Map, <code>null</code> if null map input
114      */

115     public static Object JavaDoc getObject(final Map JavaDoc map, final Object JavaDoc key) {
116         if (map != null) {
117             return map.get(key);
118         }
119         return null;
120     }
121
122     /**
123      * Gets a String from a Map in a null-safe manner.
124      * <p>
125      * The String is obtained via <code>toString</code>.
126      *
127      * @param map the map to use
128      * @param key the key to look up
129      * @return the value in the Map as a String, <code>null</code> if null map input
130      */

131     public static String JavaDoc getString(final Map JavaDoc map, final Object JavaDoc key) {
132         if (map != null) {
133             Object JavaDoc answer = map.get(key);
134             if (answer != null) {
135                 return answer.toString();
136             }
137         }
138         return null;
139     }
140
141     /**
142      * Gets a Boolean from a Map in a null-safe manner.
143      * <p>
144      * If the value is a <code>Boolean</code> it is returned directly.
145      * If the value is a <code>String</code> and it equals 'true' ignoring case
146      * then <code>true</code> is returned, otherwise <code>false</code>.
147      * If the value is a <code>Number</code> an integer zero value returns
148      * <code>false</code> and non-zero returns <code>true</code>.
149      * Otherwise, <code>null</code> is returned.
150      *
151      * @param map the map to use
152      * @param key the key to look up
153      * @return the value in the Map as a Boolean, <code>null</code> if null map input
154      */

155     public static Boolean JavaDoc getBoolean(final Map JavaDoc map, final Object JavaDoc key) {
156         if (map != null) {
157             Object JavaDoc answer = map.get(key);
158             if (answer != null) {
159                 if (answer instanceof Boolean JavaDoc) {
160                     return (Boolean JavaDoc) answer;
161                     
162                 } else if (answer instanceof String JavaDoc) {
163                     return new Boolean JavaDoc((String JavaDoc) answer);
164                     
165                 } else if (answer instanceof Number JavaDoc) {
166                     Number JavaDoc n = (Number JavaDoc) answer;
167                     return (n.intValue() != 0) ? Boolean.TRUE : Boolean.FALSE;
168                 }
169             }
170         }
171         return null;
172     }
173
174     /**
175      * Gets a Number from a Map in a null-safe manner.
176      * <p>
177      * If the value is a <code>Number</code> it is returned directly.
178      * If the value is a <code>String</code> it is converted using
179      * {@link NumberFormat#parse(String)} on the system default formatter
180      * returning <code>null</code> if the conversion fails.
181      * Otherwise, <code>null</code> is returned.
182      *
183      * @param map the map to use
184      * @param key the key to look up
185      * @return the value in the Map as a Number, <code>null</code> if null map input
186      */

187     public static Number JavaDoc getNumber(final Map JavaDoc map, final Object JavaDoc key) {
188         if (map != null) {
189             Object JavaDoc answer = map.get(key);
190             if (answer != null) {
191                 if (answer instanceof Number JavaDoc) {
192                     return (Number JavaDoc) answer;
193                     
194                 } else if (answer instanceof String JavaDoc) {
195                     try {
196                         String JavaDoc text = (String JavaDoc) answer;
197                         return NumberFormat.getInstance().parse(text);
198                         
199                     } catch (ParseException JavaDoc e) {
200                         logInfo(e);
201                     }
202                 }
203             }
204         }
205         return null;
206     }
207
208     /**
209      * Gets a Byte from a Map in a null-safe manner.
210      * <p>
211      * The Byte is obtained from the results of {@link #getNumber(Map,Object)}.
212      *
213      * @param map the map to use
214      * @param key the key to look up
215      * @return the value in the Map as a Byte, <code>null</code> if null map input
216      */

217     public static Byte JavaDoc getByte(final Map JavaDoc map, final Object JavaDoc key) {
218         Number JavaDoc answer = getNumber(map, key);
219         if (answer == null) {
220             return null;
221         } else if (answer instanceof Byte JavaDoc) {
222             return (Byte JavaDoc) answer;
223         }
224         return new Byte JavaDoc(answer.byteValue());
225     }
226
227     /**
228      * Gets a Short from a Map in a null-safe manner.
229      * <p>
230      * The Short is obtained from the results of {@link #getNumber(Map,Object)}.
231      *
232      * @param map the map to use
233      * @param key the key to look up
234      * @return the value in the Map as a Short, <code>null</code> if null map input
235      */

236     public static Short JavaDoc getShort(final Map JavaDoc map, final Object JavaDoc key) {
237         Number JavaDoc answer = getNumber(map, key);
238         if (answer == null) {
239             return null;
240         } else if (answer instanceof Short JavaDoc) {
241             return (Short JavaDoc) answer;
242         }
243         return new Short JavaDoc(answer.shortValue());
244     }
245
246     /**
247      * Gets a Integer from a Map in a null-safe manner.
248      * <p>
249      * The Integer is obtained from the results of {@link #getNumber(Map,Object)}.
250      *
251      * @param map the map to use
252      * @param key the key to look up
253      * @return the value in the Map as a Integer, <code>null</code> if null map input
254      */

255     public static Integer JavaDoc getInteger(final Map JavaDoc map, final Object JavaDoc key) {
256         Number JavaDoc answer = getNumber(map, key);
257         if (answer == null) {
258             return null;
259         } else if (answer instanceof Integer JavaDoc) {
260             return (Integer JavaDoc) answer;
261         }
262         return new Integer JavaDoc(answer.intValue());
263     }
264
265     /**
266      * Gets a Long from a Map in a null-safe manner.
267      * <p>
268      * The Long is obtained from the results of {@link #getNumber(Map,Object)}.
269      *
270      * @param map the map to use
271      * @param key the key to look up
272      * @return the value in the Map as a Long, <code>null</code> if null map input
273      */

274     public static Long JavaDoc getLong(final Map JavaDoc map, final Object JavaDoc key) {
275         Number JavaDoc answer = getNumber(map, key);
276         if (answer == null) {
277             return null;
278         } else if (answer instanceof Long JavaDoc) {
279             return (Long JavaDoc) answer;
280         }
281         return new Long JavaDoc(answer.longValue());
282     }
283
284     /**
285      * Gets a Float from a Map in a null-safe manner.
286      * <p>
287      * The Float is obtained from the results of {@link #getNumber(Map,Object)}.
288      *
289      * @param map the map to use
290      * @param key the key to look up
291      * @return the value in the Map as a Float, <code>null</code> if null map input
292      */

293     public static Float JavaDoc getFloat(final Map JavaDoc map, final Object JavaDoc key) {
294         Number JavaDoc answer = getNumber(map, key);
295         if (answer == null) {
296             return null;
297         } else if (answer instanceof Float JavaDoc) {
298             return (Float JavaDoc) answer;
299         }
300         return new Float JavaDoc(answer.floatValue());
301     }
302
303     /**
304      * Gets a Double from a Map in a null-safe manner.
305      * <p>
306      * The Double is obtained from the results of {@link #getNumber(Map,Object)}.
307      *
308      * @param map the map to use
309      * @param key the key to look up
310      * @return the value in the Map as a Double, <code>null</code> if null map input
311      */

312     public static Double JavaDoc getDouble(final Map JavaDoc map, final Object JavaDoc key) {
313         Number JavaDoc answer = getNumber(map, key);
314         if (answer == null) {
315             return null;
316         } else if (answer instanceof Double JavaDoc) {
317             return (Double JavaDoc) answer;
318         }
319         return new Double JavaDoc(answer.doubleValue());
320     }
321
322     /**
323      * Gets a Map from a Map in a null-safe manner.
324      * <p>
325      * If the value returned from the specified map is not a Map then
326      * <code>null</code> is returned.
327      *
328      * @param map the map to use
329      * @param key the key to look up
330      * @return the value in the Map as a Map, <code>null</code> if null map input
331      */

332     public static Map JavaDoc getMap(final Map JavaDoc map, final Object JavaDoc key) {
333         if (map != null) {
334             Object JavaDoc answer = map.get(key);
335             if (answer != null && answer instanceof Map JavaDoc) {
336                 return (Map JavaDoc) answer;
337             }
338         }
339         return null;
340     }
341
342     // Type safe getters with default values
343
//-------------------------------------------------------------------------
344
/**
345      * Looks up the given key in the given map, converting null into the
346      * given default value.
347      *
348      * @param map the map whose value to look up
349      * @param key the key of the value to look up in that map
350      * @param defaultValue what to return if the value is null
351      * @return the value in the map, or defaultValue if the original value
352      * is null or the map is null
353      */

354     public static Object JavaDoc getObject( Map JavaDoc map, Object JavaDoc key, Object JavaDoc defaultValue ) {
355         if ( map != null ) {
356             Object JavaDoc answer = map.get( key );
357             if ( answer != null ) {
358                 return answer;
359             }
360         }
361         return defaultValue;
362     }
363
364     /**
365      * Looks up the given key in the given map, converting the result into
366      * a string, using the default value if the the conversion fails.
367      *
368      * @param map the map whose value to look up
369      * @param key the key of the value to look up in that map
370      * @param defaultValue what to return if the value is null or if the
371      * conversion fails
372      * @return the value in the map as a string, or defaultValue if the
373      * original value is null, the map is null or the string conversion
374      * fails
375      */

376     public static String JavaDoc getString( Map JavaDoc map, Object JavaDoc key, String JavaDoc defaultValue ) {
377         String JavaDoc answer = getString( map, key );
378         if ( answer == null ) {
379             answer = defaultValue;
380         }
381         return answer;
382     }
383
384     /**
385      * Looks up the given key in the given map, converting the result into
386      * a boolean, using the default value if the the conversion fails.
387      *
388      * @param map the map whose value to look up
389      * @param key the key of the value to look up in that map
390      * @param defaultValue what to return if the value is null or if the
391      * conversion fails
392      * @return the value in the map as a boolean, or defaultValue if the
393      * original value is null, the map is null or the boolean conversion
394      * fails
395      */

396     public static Boolean JavaDoc getBoolean( Map JavaDoc map, Object JavaDoc key, Boolean JavaDoc defaultValue ) {
397         Boolean JavaDoc answer = getBoolean( map, key );
398         if ( answer == null ) {
399             answer = defaultValue;
400         }
401         return answer;
402     }
403
404     /**
405      * Looks up the given key in the given map, converting the result into
406      * a number, using the default value if the the conversion fails.
407      *
408      * @param map the map whose value to look up
409      * @param key the key of the value to look up in that map
410      * @param defaultValue what to return if the value is null or if the
411      * conversion fails
412      * @return the value in the map as a number, or defaultValue if the
413      * original value is null, the map is null or the number conversion
414      * fails
415      */

416     public static Number JavaDoc getNumber( Map JavaDoc map, Object JavaDoc key, Number JavaDoc defaultValue ) {
417         Number JavaDoc answer = getNumber( map, key );
418         if ( answer == null ) {
419             answer = defaultValue;
420         }
421         return answer;
422     }
423
424     /**
425      * Looks up the given key in the given map, converting the result into
426      * a byte, using the default value if the the conversion fails.
427      *
428      * @param map the map whose value to look up
429      * @param key the key of the value to look up in that map
430      * @param defaultValue what to return if the value is null or if the
431      * conversion fails
432      * @return the value in the map as a number, or defaultValue if the
433      * original value is null, the map is null or the number conversion
434      * fails
435      */

436     public static Byte JavaDoc getByte( Map JavaDoc map, Object JavaDoc key, Byte JavaDoc defaultValue ) {
437         Byte JavaDoc answer = getByte( map, key );
438         if ( answer == null ) {
439             answer = defaultValue;
440         }
441         return answer;
442     }
443
444     /**
445      * Looks up the given key in the given map, converting the result into
446      * a short, using the default value if the the conversion fails.
447      *
448      * @param map the map whose value to look up
449      * @param key the key of the value to look up in that map
450      * @param defaultValue what to return if the value is null or if the
451      * conversion fails
452      * @return the value in the map as a number, or defaultValue if the
453      * original value is null, the map is null or the number conversion
454      * fails
455      */

456     public static Short JavaDoc getShort( Map JavaDoc map, Object JavaDoc key, Short JavaDoc defaultValue ) {
457         Short JavaDoc answer = getShort( map, key );
458         if ( answer == null ) {
459             answer = defaultValue;
460         }
461         return answer;
462     }
463
464     /**
465      * Looks up the given key in the given map, converting the result into
466      * an integer, using the default value if the the conversion fails.
467      *
468      * @param map the map whose value to look up
469      * @param key the key of the value to look up in that map
470      * @param defaultValue what to return if the value is null or if the
471      * conversion fails
472      * @return the value in the map as a number, or defaultValue if the
473      * original value is null, the map is null or the number conversion
474      * fails
475      */

476     public static Integer JavaDoc getInteger( Map JavaDoc map, Object JavaDoc key, Integer JavaDoc defaultValue ) {
477         Integer JavaDoc answer = getInteger( map, key );
478         if ( answer == null ) {
479             answer = defaultValue;
480         }
481         return answer;
482     }
483
484     /**
485      * Looks up the given key in the given map, converting the result into
486      * a long, using the default value if the the conversion fails.
487      *
488      * @param map the map whose value to look up
489      * @param key the key of the value to look up in that map
490      * @param defaultValue what to return if the value is null or if the
491      * conversion fails
492      * @return the value in the map as a number, or defaultValue if the
493      * original value is null, the map is null or the number conversion
494      * fails
495      */

496     public static Long JavaDoc getLong( Map JavaDoc map, Object JavaDoc key, Long JavaDoc defaultValue ) {
497         Long JavaDoc answer = getLong( map, key );
498         if ( answer == null ) {
499             answer = defaultValue;
500         }
501         return answer;
502     }
503
504     /**
505      * Looks up the given key in the given map, converting the result into
506      * a float, using the default value if the the conversion fails.
507      *
508      * @param map the map whose value to look up
509      * @param key the key of the value to look up in that map
510      * @param defaultValue what to return if the value is null or if the
511      * conversion fails
512      * @return the value in the map as a number, or defaultValue if the
513      * original value is null, the map is null or the number conversion
514      * fails
515      */

516     public static Float JavaDoc getFloat( Map JavaDoc map, Object JavaDoc key, Float JavaDoc defaultValue ) {
517         Float JavaDoc answer = getFloat( map, key );
518         if ( answer == null ) {
519             answer = defaultValue;
520         }
521         return answer;
522     }
523
524     /**
525      * Looks up the given key in the given map, converting the result into
526      * a double, using the default value if the the conversion fails.
527      *
528      * @param map the map whose value to look up
529      * @param key the key of the value to look up in that map
530      * @param defaultValue what to return if the value is null or if the
531      * conversion fails
532      * @return the value in the map as a number, or defaultValue if the
533      * original value is null, the map is null or the number conversion
534      * fails
535      */

536     public static Double JavaDoc getDouble( Map JavaDoc map, Object JavaDoc key, Double JavaDoc defaultValue ) {
537         Double JavaDoc answer = getDouble( map, key );
538         if ( answer == null ) {
539             answer = defaultValue;
540         }
541         return answer;
542     }
543
544     /**
545      * Looks up the given key in the given map, converting the result into
546      * a map, using the default value if the the conversion fails.
547      *
548      * @param map the map whose value to look up
549      * @param key the key of the value to look up in that map
550      * @param defaultValue what to return if the value is null or if the
551      * conversion fails
552      * @return the value in the map as a number, or defaultValue if the
553      * original value is null, the map is null or the map conversion
554      * fails
555      */

556     public static Map JavaDoc getMap( Map JavaDoc map, Object JavaDoc key, Map JavaDoc defaultValue ) {
557         Map JavaDoc answer = getMap( map, key );
558         if ( answer == null ) {
559             answer = defaultValue;
560         }
561         return answer;
562     }
563     
564
565     // Type safe primitive getters
566
//-------------------------------------------------------------------------
567
/**
568      * Gets a boolean from a Map in a null-safe manner.
569      * <p>
570      * If the value is a <code>Boolean</code> its value is returned.
571      * If the value is a <code>String</code> and it equals 'true' ignoring case
572      * then <code>true</code> is returned, otherwise <code>false</code>.
573      * If the value is a <code>Number</code> an integer zero value returns
574      * <code>false</code> and non-zero returns <code>true</code>.
575      * Otherwise, <code>false</code> is returned.
576      *
577      * @param map the map to use
578      * @param key the key to look up
579      * @return the value in the Map as a Boolean, <code>false</code> if null map input
580      */

581     public static boolean getBooleanValue(final Map JavaDoc map, final Object JavaDoc key) {
582         Boolean JavaDoc booleanObject = getBoolean(map, key);
583         if (booleanObject == null) {
584             return false;
585         }
586         return booleanObject.booleanValue();
587     }
588
589     /**
590      * Gets a byte from a Map in a null-safe manner.
591      * <p>
592      * The byte is obtained from the results of {@link #getNumber(Map,Object)}.
593      *
594      * @param map the map to use
595      * @param key the key to look up
596      * @return the value in the Map as a byte, <code>0</code> if null map input
597      */

598     public static byte getByteValue(final Map JavaDoc map, final Object JavaDoc key) {
599         Byte JavaDoc byteObject = getByte(map, key);
600         if (byteObject == null) {
601             return 0;
602         }
603         return byteObject.byteValue();
604     }
605
606     /**
607      * Gets a short from a Map in a null-safe manner.
608      * <p>
609      * The short is obtained from the results of {@link #getNumber(Map,Object)}.
610      *
611      * @param map the map to use
612      * @param key the key to look up
613      * @return the value in the Map as a short, <code>0</code> if null map input
614      */

615     public static short getShortValue(final Map JavaDoc map, final Object JavaDoc key) {
616         Short JavaDoc shortObject = getShort(map, key);
617         if (shortObject == null) {
618             return 0;
619         }
620         return shortObject.shortValue();
621     }
622
623     /**
624      * Gets an int from a Map in a null-safe manner.
625      * <p>
626      * The int is obtained from the results of {@link #getNumber(Map,Object)}.
627      *
628      * @param map the map to use
629      * @param key the key to look up
630      * @return the value in the Map as an int, <code>0</code> if null map input
631      */

632     public static int getIntValue(final Map JavaDoc map, final Object JavaDoc key) {
633         Integer JavaDoc integerObject = getInteger(map, key);
634         if (integerObject == null) {
635             return 0;
636         }
637         return integerObject.intValue();
638     }
639
640     /**
641      * Gets a long from a Map in a null-safe manner.
642      * <p>
643      * The long is obtained from the results of {@link #getNumber(Map,Object)}.
644      *
645      * @param map the map to use
646      * @param key the key to look up
647      * @return the value in the Map as a long, <code>0L</code> if null map input
648      */

649     public static long getLongValue(final Map JavaDoc map, final Object JavaDoc key) {
650         Long JavaDoc longObject = getLong(map, key);
651         if (longObject == null) {
652             return 0L;
653         }
654         return longObject.longValue();
655     }
656
657     /**
658      * Gets a float from a Map in a null-safe manner.
659      * <p>
660      * The float is obtained from the results of {@link #getNumber(Map,Object)}.
661      *
662      * @param map the map to use
663      * @param key the key to look up
664      * @return the value in the Map as a float, <code>0.0F</code> if null map input
665      */

666     public static float getFloatValue(final Map JavaDoc map, final Object JavaDoc key) {
667         Float JavaDoc floatObject = getFloat(map, key);
668         if (floatObject == null) {
669             return 0f;
670         }
671         return floatObject.floatValue();
672     }
673
674     /**
675      * Gets a double from a Map in a null-safe manner.
676      * <p>
677      * The double is obtained from the results of {@link #getNumber(Map,Object)}.
678      *
679      * @param map the map to use
680      * @param key the key to look up
681      * @return the value in the Map as a double, <code>0.0</code> if null map input
682      */

683     public static double getDoubleValue(final Map JavaDoc map, final Object JavaDoc key) {
684         Double JavaDoc doubleObject = getDouble(map, key);
685         if (doubleObject == null) {
686             return 0d;
687         }
688         return doubleObject.doubleValue();
689     }
690
691     // Type safe primitive getters with default values
692
//-------------------------------------------------------------------------
693
/**
694      * Gets a boolean from a Map in a null-safe manner,
695      * using the default value if the the conversion fails.
696      * <p>
697      * If the value is a <code>Boolean</code> its value is returned.
698      * If the value is a <code>String</code> and it equals 'true' ignoring case
699      * then <code>true</code> is returned, otherwise <code>false</code>.
700      * If the value is a <code>Number</code> an integer zero value returns
701      * <code>false</code> and non-zero returns <code>true</code>.
702      * Otherwise, <code>defaultValue</code> is returned.
703      *
704      * @param map the map to use
705      * @param key the key to look up
706      * @param defaultValue return if the value is null or if the
707      * conversion fails
708      * @return the value in the Map as a Boolean, <code>defaultValue</code> if null map input
709      */

710     public static boolean getBooleanValue(final Map JavaDoc map, final Object JavaDoc key, boolean defaultValue) {
711         Boolean JavaDoc booleanObject = getBoolean(map, key);
712         if (booleanObject == null) {
713             return defaultValue;
714         }
715         return booleanObject.booleanValue();
716     }
717
718     /**
719      * Gets a byte from a Map in a null-safe manner,
720      * using the default value if the the conversion fails.
721      * <p>
722      * The byte is obtained from the results of {@link #getNumber(Map,Object)}.
723      *
724      * @param map the map to use
725      * @param key the key to look up
726      * @param defaultValue return if the value is null or if the
727      * conversion fails
728      * @return the value in the Map as a byte, <code>defaultValue</code> if null map input
729      */

730     public static byte getByteValue(final Map JavaDoc map, final Object JavaDoc key, byte defaultValue) {
731         Byte JavaDoc byteObject = getByte(map, key);
732         if (byteObject == null) {
733             return defaultValue;
734         }
735         return byteObject.byteValue();
736     }
737
738     /**
739      * Gets a short from a Map in a null-safe manner,
740      * using the default value if the the conversion fails.
741      * <p>
742      * The short is obtained from the results of {@link #getNumber(Map,Object)}.
743      *
744      * @param map the map to use
745      * @param key the key to look up
746      * @param defaultValue return if the value is null or if the
747      * conversion fails
748      * @return the value in the Map as a short, <code>defaultValue</code> if null map input
749      */

750     public static short getShortValue(final Map JavaDoc map, final Object JavaDoc key, short defaultValue) {
751         Short JavaDoc shortObject = getShort(map, key);
752         if (shortObject == null) {
753             return defaultValue;
754         }
755         return shortObject.shortValue();
756     }
757
758     /**
759      * Gets an int from a Map in a null-safe manner,
760      * using the default value if the the conversion fails.
761      * <p>
762      * The int is obtained from the results of {@link #getNumber(Map,Object)}.
763      *
764      * @param map the map to use
765      * @param key the key to look up
766      * @param defaultValue return if the value is null or if the
767      * conversion fails
768      * @return the value in the Map as an int, <code>defaultValue</code> if null map input
769      */

770     public static int getIntValue(final Map JavaDoc map, final Object JavaDoc key, int defaultValue) {
771         Integer JavaDoc integerObject = getInteger(map, key);
772         if (integerObject == null) {
773             return defaultValue;
774         }
775         return integerObject.intValue();
776     }
777
778     /**
779      * Gets a long from a Map in a null-safe manner,
780      * using the default value if the the conversion fails.
781      * <p>
782      * The long is obtained from the results of {@link #getNumber(Map,Object)}.
783      *
784      * @param map the map to use
785      * @param key the key to look up
786      * @param defaultValue return if the value is null or if the
787      * conversion fails
788      * @return the value in the Map as a long, <code>defaultValue</code> if null map input
789      */

790     public static long getLongValue(final Map JavaDoc map, final Object JavaDoc key, long defaultValue) {
791         Long JavaDoc longObject = getLong(map, key);
792         if (longObject == null) {
793             return defaultValue;
794         }
795         return longObject.longValue();
796     }
797
798     /**
799      * Gets a float from a Map in a null-safe manner,
800      * using the default value if the the conversion fails.
801      * <p>
802      * The float is obtained from the results of {@link #getNumber(Map,Object)}.
803      *
804      * @param map the map to use
805      * @param key the key to look up
806      * @param defaultValue return if the value is null or if the
807      * conversion fails
808      * @return the value in the Map as a float, <code>defaultValue</code> if null map input
809      */

810     public static float getFloatValue(final Map JavaDoc map, final Object JavaDoc key, float defaultValue) {
811         Float JavaDoc floatObject = getFloat(map, key);
812         if (floatObject == null) {
813             return defaultValue;
814         }
815         return floatObject.floatValue();
816     }
817
818     /**
819      * Gets a double from a Map in a null-safe manner,
820      * using the default value if the the conversion fails.
821      * <p>
822      * The double is obtained from the results of {@link #getNumber(Map,Object)}.
823      *
824      * @param map the map to use
825      * @param key the key to look up
826      * @param defaultValue return if the value is null or if the
827      * conversion fails
828      * @return the value in the Map as a double, <code>defaultValue</code> if null map input
829      */

830     public static double getDoubleValue(final Map JavaDoc map, final Object JavaDoc key, double defaultValue) {
831         Double JavaDoc doubleObject = getDouble(map, key);
832         if (doubleObject == null) {
833             return defaultValue;
834         }
835         return doubleObject.doubleValue();
836     }
837
838     // Conversion methods
839
//-------------------------------------------------------------------------
840
/**
841      * Gets a new Properties object initialised with the values from a Map.
842      * A null input will return an empty properties object.
843      *
844      * @param map the map to convert to a Properties object, may not be null
845      * @return the properties object
846      */

847     public static Properties JavaDoc toProperties(final Map JavaDoc map) {
848         Properties JavaDoc answer = new Properties JavaDoc();
849         if (map != null) {
850             for (Iterator JavaDoc iter = map.entrySet().iterator(); iter.hasNext();) {
851                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) iter.next();
852                 Object JavaDoc key = entry.getKey();
853                 Object JavaDoc value = entry.getValue();
854                 answer.put(key, value);
855             }
856         }
857         return answer;
858     }
859
860     /**
861      * Creates a new HashMap using data copied from a ResourceBundle.
862      *
863      * @param resourceBundle the resource bundle to convert, may not be null
864      * @return the hashmap containing the data
865      * @throws NullPointerException if the bundle is null
866      */

867     public static Map JavaDoc toMap(final ResourceBundle JavaDoc resourceBundle) {
868         Enumeration JavaDoc enumeration = resourceBundle.getKeys();
869         Map JavaDoc map = new HashMap JavaDoc();
870
871         while (enumeration.hasMoreElements()) {
872             String JavaDoc key = (String JavaDoc) enumeration.nextElement();
873             Object JavaDoc value = resourceBundle.getObject(key);
874             map.put(key, value);
875         }
876         
877         return map;
878     }
879  
880     // Printing methods
881
//-------------------------------------------------------------------------
882
/**
883      * Prints the given map with nice line breaks.
884      * <p>
885      * This method prints a nicely formatted String describing the Map.
886      * Each map entry will be printed with key and value.
887      * When the value is a Map, recursive behaviour occurs.
888      * <p>
889      * This method is NOT thread-safe in any special way. You must manually
890      * synchronize on either this class or the stream as required.
891      *
892      * @param out the stream to print to, must not be null
893      * @param label The label to be used, may be <code>null</code>.
894      * If <code>null</code>, the label is not output.
895      * It typically represents the name of the property in a bean or similar.
896      * @param map The map to print, may be <code>null</code>.
897      * If <code>null</code>, the text 'null' is output.
898      * @throws NullPointerException if the stream is <code>null</code>
899      */

900     public static void verbosePrint(
901         final PrintStream JavaDoc out,
902         final Object JavaDoc label,
903         final Map JavaDoc map) {
904
905         verbosePrintInternal(out, label, map, new ArrayStack(), false);
906     }
907
908     /**
909      * Prints the given map with nice line breaks.
910      * <p>
911      * This method prints a nicely formatted String describing the Map.
912      * Each map entry will be printed with key, value and value classname.
913      * When the value is a Map, recursive behaviour occurs.
914      * <p>
915      * This method is NOT thread-safe in any special way. You must manually
916      * synchronize on either this class or the stream as required.
917      *
918      * @param out the stream to print to, must not be null
919      * @param label The label to be used, may be <code>null</code>.
920      * If <code>null</code>, the label is not output.
921      * It typically represents the name of the property in a bean or similar.
922      * @param map The map to print, may be <code>null</code>.
923      * If <code>null</code>, the text 'null' is output.
924      * @throws NullPointerException if the stream is <code>null</code>
925      */

926     public static void debugPrint(
927         final PrintStream JavaDoc out,
928         final Object JavaDoc label,
929         final Map JavaDoc map) {
930
931         verbosePrintInternal(out, label, map, new ArrayStack(), true);
932     }
933
934     // Implementation methods
935
//-------------------------------------------------------------------------
936
/**
937      * Logs the given exception to <code>System.out</code>.
938      * <p>
939      * This method exists as Jakarta Collections does not depend on logging.
940      *
941      * @param ex the exception to log
942      */

943     protected static void logInfo(final Exception JavaDoc ex) {
944         System.out.println("INFO: Exception: " + ex);
945     }
946
947     /**
948      * Implementation providing functionality for {@link #debugPrint} and for
949      * {@link #verbosePrint}. This prints the given map with nice line breaks.
950      * If the debug flag is true, it additionally prints the type of the object
951      * value. If the contents of a map include the map itself, then the text
952      * <em>(this Map)</em> is printed out. If the contents include a
953      * parent container of the map, the the text <em>(ancestor[i] Map)</em> is
954      * printed, where i actually indicates the number of levels which must be
955      * traversed in the sequential list of ancestors (e.g. father, grandfather,
956      * great-grandfather, etc).
957      *
958      * @param out the stream to print to
959      * @param label the label to be used, may be <code>null</code>.
960      * If <code>null</code>, the label is not output.
961      * It typically represents the name of the property in a bean or similar.
962      * @param map the map to print, may be <code>null</code>.
963      * If <code>null</code>, the text 'null' is output
964      * @param lineage a stack consisting of any maps in which the previous
965      * argument is contained. This is checked to avoid infinite recursion when
966      * printing the output
967      * @param debug flag indicating whether type names should be output.
968      * @throws NullPointerException if the stream is <code>null</code>
969      */

970     private static void verbosePrintInternal(
971         final PrintStream JavaDoc out,
972         final Object JavaDoc label,
973         final Map JavaDoc map,
974         final ArrayStack lineage,
975         final boolean debug) {
976         
977         printIndent(out, lineage.size());
978
979         if (map == null) {
980             if (label != null) {
981                 out.print(label);
982                 out.print(" = ");
983             }
984             out.println("null");
985             return;
986         }
987         if (label != null) {
988             out.print(label);
989             out.println(" = ");
990         }
991
992         printIndent(out, lineage.size());
993         out.println("{");
994
995         lineage.push(map);
996
997         for (Iterator JavaDoc it = map.entrySet().iterator(); it.hasNext();) {
998             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
999             Object JavaDoc childKey = entry.getKey();
1000            Object JavaDoc childValue = entry.getValue();
1001            if (childValue instanceof Map JavaDoc && !lineage.contains(childValue)) {
1002                verbosePrintInternal(
1003                    out,
1004                    (childKey == null ? "null" : childKey),
1005                    (Map JavaDoc) childValue,
1006                    lineage,
1007                    debug);
1008            } else {
1009                printIndent(out, lineage.size());
1010                out.print(childKey);
1011                out.print(" = ");
1012                
1013                final int lineageIndex = lineage.indexOf(childValue);
1014                if (lineageIndex == -1) {
1015                    out.print(childValue);
1016                } else if (lineage.size() - 1 == lineageIndex) {
1017                    out.print("(this Map)");
1018                } else {
1019                    out.print(
1020                        "(ancestor["
1021                            + (lineage.size() - 1 - lineageIndex - 1)
1022                            + "] Map)");
1023                }
1024                
1025                if (debug && childValue != null) {
1026                    out.print(' ');
1027                    out.println(childValue.getClass().getName());
1028                } else {
1029                    out.println();
1030                }
1031            }
1032        }
1033        
1034        lineage.pop();
1035
1036        printIndent(out, lineage.size());
1037        out.println(debug ? "} " + map.getClass().getName() : "}");
1038    }
1039
1040    /**
1041     * Writes indentation to the given stream.
1042     *
1043     * @param out the stream to indent
1044     */

1045    private static void printIndent(final PrintStream JavaDoc out, final int indent) {
1046        for (int i = 0; i < indent; i++) {
1047            out.print(INDENT_STRING);
1048        }
1049    }
1050    
1051    // Misc
1052
//-----------------------------------------------------------------------
1053
/**
1054     * Inverts the supplied map returning a new HashMap such that the keys of
1055     * the input are swapped with the values.
1056     * <p>
1057     * This operation assumes that the inverse mapping is well defined.
1058     * If the input map had multiple entries with the same value mapped to
1059     * different keys, the returned map will map one of those keys to the
1060     * value, but the exact key which will be mapped is undefined.
1061     *
1062     * @see DoubleOrderedMap
1063     * @param map the map to invert, may not be null
1064     * @return a new HashMap containing the inverted data
1065     * @throws NullPointerException if the map is null
1066     */

1067    public static Map JavaDoc invertMap(Map JavaDoc map) {
1068        Map JavaDoc out = new HashMap JavaDoc(map.size());
1069        for (Iterator JavaDoc it = map.entrySet().iterator(); it.hasNext();) {
1070            Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
1071            out.put(entry.getValue(), entry.getKey());
1072        }
1073        return out;
1074    }
1075     
1076    /**
1077     * Nice method for adding data to a map in such a way
1078     * as to not get NPE's. The point being that if the
1079     * value is null, map.put() will throw an exception.
1080     * That blows in the case of this class cause you may want to
1081     * essentially treat put("Not Null", null ) == put("Not Null", "")
1082     * We will still throw a NPE if the key is null cause that should
1083     * never happen.
1084     *
1085     * @param map the map to add to, may not be null
1086     * @param key the key
1087     * @param value the value
1088     * @throws NullPointerException if the map is null
1089     */

1090    public static void safeAddToMap(Map JavaDoc map, Object JavaDoc key, Object JavaDoc value) throws NullPointerException JavaDoc {
1091        if (value == null) {
1092            map.put ( key, "" );
1093        } else {
1094           map.put ( key, value );
1095        }
1096    }
1097
1098    // Map decorators
1099
//-----------------------------------------------------------------------
1100
/**
1101     * Returns a synchronized map backed by the given map.
1102     * <p>
1103     * You must manually synchronize on the returned buffer's iterator to
1104     * avoid non-deterministic behavior:
1105     *
1106     * <pre>
1107     * Map m = MapUtils.synchronizedMap(myMap);
1108     * Set s = m.keySet(); // outside synchronized block
1109     * synchronized (m) { // synchronized on MAP!
1110     * Iterator i = s.iterator();
1111     * while (i.hasNext()) {
1112     * process (i.next());
1113     * }
1114     * }
1115     * </pre>
1116     *
1117     * This method uses the implementation in {@link java.util.Collections Collections}.
1118     *
1119     * @param map the map to synchronize, must not be null
1120     * @return a synchronized map backed by the given map
1121     * @throws IllegalArgumentException if the map is null
1122     */

1123    public static Map JavaDoc synchronizedMap(Map JavaDoc map) {
1124        return Collections.synchronizedMap(map);
1125    }
1126
1127    /**
1128     * Returns an unmodifiable map backed by the given map.
1129     * <p>
1130     * This method uses the implementation in the decorators subpackage.
1131     *
1132     * @param map the map to make unmodifiable, must not be null
1133     * @return an unmodifiable map backed by the given map
1134     * @throws IllegalArgumentException if the map is null
1135     */

1136    public static Map JavaDoc unmodifiableMap(Map JavaDoc map) {
1137        return UnmodifiableMap.decorate(map);
1138    }
1139
1140    /**
1141     * Returns a predicated (validating) map backed by the given map.
1142     * <p>
1143     * Only objects that pass the tests in the given predicates can be added to the map.
1144     * Trying to add an invalid object results in an IllegalArgumentException.
1145     * Keys must pass the key predicate, values must pass the value predicate.
1146     * It is important not to use the original map after invoking this method,
1147     * as it is a backdoor for adding invalid objects.
1148     *
1149     * @param map the map to predicate, must not be null
1150     * @param keyPred the predicate for keys, null means no check
1151     * @param valuePred the predicate for values, null means no check
1152     * @return a predicated map backed by the given map
1153     * @throws IllegalArgumentException if the Map is null
1154     */

1155    public static Map JavaDoc predicatedMap(Map JavaDoc map, Predicate keyPred, Predicate valuePred) {
1156        return PredicatedMap.decorate(map, keyPred, valuePred);
1157    }
1158
1159    /**
1160     * Returns a typed map backed by the given map.
1161     * <p>
1162     * Only keys and values of the specified types can be added to the map.
1163     *
1164     * @param map the map to limit to a specific type, must not be null
1165     * @param keyType the type of keys which may be added to the map, must not be null
1166     * @param valueType the type of values which may be added to the map, must not be null
1167     * @return a typed map backed by the specified map
1168     * @throws IllegalArgumentException if the Map or Class is null
1169     */

1170    public static Map JavaDoc typedMap(Map JavaDoc map, Class JavaDoc keyType, Class JavaDoc valueType) {
1171        return TypedMap.decorate(map, keyType, valueType);
1172    }
1173    
1174    /**
1175     * Returns a transformed map backed by the given map.
1176     * <p>
1177     * Each object is passed through the transformers as it is added to the
1178     * Map. It is important not to use the original map after invoking this
1179     * method, as it is a backdoor for adding untransformed objects.
1180     *
1181     * @param map the map to transform, must not be null
1182     * @param keyTransformer the transformer for the map keys, null means no transformation
1183     * @param valueTransformer the transformer for the map values, null means no transformation
1184     * @return a transformed map backed by the given map
1185     * @throws IllegalArgumentException if the Map is null
1186     */

1187    public static Map JavaDoc transformedMap(Map JavaDoc map, Transformer keyTransformer, Transformer valueTransformer) {
1188        return TransformedMap.decorate(map, keyTransformer, valueTransformer);
1189    }
1190    
1191    /**
1192     * Returns a fixed-sized map backed by the given map.
1193     * Elements may not be added or removed from the returned map, but
1194     * existing elements can be changed (for instance, via the
1195     * {@link Map#put(Object,Object)} method).
1196     *
1197     * @param map the map whose size to fix, must not be null
1198     * @return a fixed-size map backed by that map
1199     * @throws IllegalArgumentException if the Map is null
1200     */

1201    public static Map JavaDoc fixedSizeMap(Map JavaDoc map) {
1202        return FixedSizeMap.decorate(map);
1203    }
1204
1205    /**
1206     * Returns a "lazy" map whose values will be created on demand.
1207     * <p>
1208     * When the key passed to the returned map's {@link Map#get(Object)}
1209     * method is not present in the map, then the factory will be used
1210     * to create a new object and that object will become the value
1211     * associated with that key.
1212     * <p>
1213     * For instance:
1214     * <pre>
1215     * Factory factory = new Factory() {
1216     * public Object create() {
1217     * return new Date();
1218     * }
1219     * }
1220     * Map lazyMap = MapUtils.lazyMap(new HashMap(), factory);
1221     * Object obj = lazyMap.get("test");
1222     * </pre>
1223     *
1224     * After the above code is executed, <code>obj</code> will contain
1225     * a new <code>Date</code> instance. Furthermore, that <code>Date</code>
1226     * instance is the value for the <code>"test"</code> key in the map.
1227     *
1228     * @param map the map to make lazy, must not be null
1229     * @param factory the factory for creating new objects, must not be null
1230     * @return a lazy map backed by the given map
1231     * @throws IllegalArgumentException if the Map or Factory is null
1232     */

1233    public static Map JavaDoc lazyMap(Map JavaDoc map, Factory factory) {
1234        return LazyMap.decorate(map, factory);
1235    }
1236
1237    /**
1238     * Returns a "lazy" map whose values will be created on demand.
1239     * <p>
1240     * When the key passed to the returned map's {@link Map#get(Object)}
1241     * method is not present in the map, then the factory will be used
1242     * to create a new object and that object will become the value
1243     * associated with that key. The factory is a {@link Transformer}
1244     * that will be passed the key which it must transform into the value.
1245     * <p>
1246     * For instance:
1247     * <pre>
1248     * Transformer factory = new Transformer() {
1249     * public Object transform(Object mapKey) {
1250     * return new File(mapKey);
1251     * }
1252     * }
1253     * Map lazyMap = MapUtils.lazyMap(new HashMap(), factory);
1254     * Object obj = lazyMap.get("C:/dev");
1255     * </pre>
1256     *
1257     * After the above code is executed, <code>obj</code> will contain
1258     * a new <code>File</code> instance for the C drive dev directory.
1259     * Furthermore, that <code>File</code> instance is the value for the
1260     * <code>"C:/dev"</code> key in the map.
1261     * <p>
1262     * If a lazy map is wrapped by a synchronized map, the result is a simple
1263     * synchronized cache. When an object is not is the cache, the cache itself
1264     * calls back to the factory Transformer to populate itself, all within the
1265     * same synchronized block.
1266     *
1267     * @param map the map to make lazy, must not be null
1268     * @param transformerFactory the factory for creating new objects, must not be null
1269     * @return a lazy map backed by the given map
1270     * @throws IllegalArgumentException if the Map or Transformer is null
1271     */

1272    public static Map JavaDoc lazyMap(Map JavaDoc map, Transformer transformerFactory) {
1273        return LazyMap.decorate(map, transformerFactory);
1274    }
1275
1276    /**
1277     * Returns a map that maintains the order of keys that are added
1278     * backed by the given map.
1279     * <p>
1280     * If a key is added twice, the order is determined by the first add.
1281     * The order is observed through the keySet, values and entrySet.
1282     *
1283     * @param map the map to order, must not be null
1284     * @return an ordered map backed by the given map
1285     * @throws IllegalArgumentException if the Map is null
1286     */

1287    public static Map JavaDoc orderedMap(Map JavaDoc map) {
1288        return ListOrderedMap.decorate(map);
1289    }
1290    
1291    // SortedMap decorators
1292
//-----------------------------------------------------------------------
1293
/**
1294     * Returns a synchronized sorted map backed by the given sorted map.
1295     * <p>
1296     * You must manually synchronize on the returned buffer's iterator to
1297     * avoid non-deterministic behavior:
1298     *
1299     * <pre>
1300     * Map m = MapUtils.synchronizedSortedMap(myMap);
1301     * Set s = m.keySet(); // outside synchronized block
1302     * synchronized (m) { // synchronized on MAP!
1303     * Iterator i = s.iterator();
1304     * while (i.hasNext()) {
1305     * process (i.next());
1306     * }
1307     * }
1308     * </pre>
1309     *
1310     * This method uses the implementation in {@link java.util.Collections Collections}.
1311     *
1312     * @param map the map to synchronize, must not be null
1313     * @return a synchronized map backed by the given map
1314     * @throws IllegalArgumentException if the map is null
1315     */

1316    public static Map JavaDoc synchronizedSortedMap(SortedMap JavaDoc map) {
1317        return Collections.synchronizedSortedMap(map);
1318    }
1319
1320    /**
1321     * Returns an unmodifiable sorted map backed by the given sorted map.
1322     * <p>
1323     * This method uses the implementation in the decorators subpackage.
1324     *
1325     * @param map the sorted map to make unmodifiable, must not be null
1326     * @return an unmodifiable map backed by the given map
1327     * @throws IllegalArgumentException if the map is null
1328     */

1329    public static Map JavaDoc unmodifiableSortedMap(SortedMap JavaDoc map) {
1330        return UnmodifiableSortedMap.decorate(map);
1331    }
1332
1333    /**
1334     * Returns a predicated (validating) sorted map backed by the given map.
1335     * <p>
1336     * Only objects that pass the tests in the given predicates can be added to the map.
1337     * Trying to add an invalid object results in an IllegalArgumentException.
1338     * Keys must pass the key predicate, values must pass the value predicate.
1339     * It is important not to use the original map after invoking this method,
1340     * as it is a backdoor for adding invalid objects.
1341     *
1342     * @param map the map to predicate, must not be null
1343     * @param keyPred the predicate for keys, null means no check
1344     * @param valuePred the predicate for values, null means no check
1345     * @return a predicated map backed by the given map
1346     * @throws IllegalArgumentException if the SortedMap is null
1347     */

1348    public static SortedMap JavaDoc predicatedSortedMap(SortedMap JavaDoc map, Predicate keyPred, Predicate valuePred) {
1349        return PredicatedSortedMap.decorate(map, keyPred, valuePred);
1350    }
1351
1352    /**
1353     * Returns a typed sorted map backed by the given map.
1354     * <p>
1355     * Only keys and values of the specified types can be added to the map.
1356     *
1357     * @param map the map to limit to a specific type, must not be null
1358     * @param keyType the type of keys which may be added to the map, must not be null
1359     * @param valueType the type of values which may be added to the map, must not be null
1360     * @return a typed map backed by the specified map
1361     */

1362    public static SortedMap JavaDoc typedSortedMap(SortedMap JavaDoc map, Class JavaDoc keyType, Class JavaDoc valueType) {
1363        return TypedSortedMap.decorate(map, keyType, valueType);
1364    }
1365    
1366    /**
1367     * Returns a transformed sorted map backed by the given map.
1368     * <p>
1369     * Each object is passed through the transformers as it is added to the
1370     * Map. It is important not to use the original map after invoking this
1371     * method, as it is a backdoor for adding untransformed objects.
1372     *
1373     * @param map the map to transform, must not be null
1374     * @param keyTransformer the transformer for the map keys, null means no transformation
1375     * @param valueTransformer the transformer for the map values, null means no transformation
1376     * @return a transformed map backed by the given map
1377     * @throws IllegalArgumentException if the SortedMap is null
1378     */

1379    public static SortedMap JavaDoc transformedSortedMap(SortedMap JavaDoc map, Transformer keyTransformer, Transformer valueTransformer) {
1380        return TransformedSortedMap.decorate(map, keyTransformer, valueTransformer);
1381    }
1382    
1383    /**
1384     * Returns a fixed-sized sorted map backed by the given sorted map.
1385     * Elements may not be added or removed from the returned map, but
1386     * existing elements can be changed (for instance, via the
1387     * {@link Map#put(Object,Object)} method).
1388     *
1389     * @param map the map whose size to fix, must not be null
1390     * @return a fixed-size map backed by that map
1391     * @throws IllegalArgumentException if the SortedMap is null
1392     */

1393    public static SortedMap JavaDoc fixedSizeSortedMap(SortedMap JavaDoc map) {
1394        return FixedSizeSortedMap.decorate(map);
1395    }
1396
1397    /**
1398     * Returns a "lazy" sorted map whose values will be created on demand.
1399     * <p>
1400     * When the key passed to the returned map's {@link Map#get(Object)}
1401     * method is not present in the map, then the factory will be used
1402     * to create a new object and that object will become the value
1403     * associated with that key.
1404     * <p>
1405     * For instance:
1406     *
1407     * <pre>
1408     * Factory factory = new Factory() {
1409     * public Object create() {
1410     * return new Date();
1411     * }
1412     * }
1413     * SortedMap lazy = MapUtils.lazySortedMap(new TreeMap(), factory);
1414     * Object obj = lazy.get("test");
1415     * </pre>
1416     *
1417     * After the above code is executed, <code>obj</code> will contain
1418     * a new <code>Date</code> instance. Furthermore, that <code>Date</code>
1419     * instance is the value for the <code>"test"</code> key.
1420     *
1421     * @param map the map to make lazy, must not be null
1422     * @param factory the factory for creating new objects, must not be null
1423     * @return a lazy map backed by the given map
1424     * @throws IllegalArgumentException if the SortedMap or Factory is null
1425     */

1426    public static SortedMap JavaDoc lazySortedMap(SortedMap JavaDoc map, Factory factory) {
1427        return LazySortedMap.decorate(map, factory);
1428    }
1429    
1430    /**
1431     * Returns a "lazy" sorted map whose values will be created on demand.
1432     * <p>
1433     * When the key passed to the returned map's {@link Map#get(Object)}
1434     * method is not present in the map, then the factory will be used
1435     * to create a new object and that object will become the value
1436     * associated with that key. The factory is a {@link Transformer}
1437     * that will be passed the key which it must transform into the value.
1438     * <p>
1439     * For instance:
1440     * <pre>
1441     * Transformer factory = new Transformer() {
1442     * public Object transform(Object mapKey) {
1443     * return new File(mapKey);
1444     * }
1445     * }
1446     * SortedMap lazy = MapUtils.lazySortedMap(new TreeMap(), factory);
1447     * Object obj = lazy.get("C:/dev");
1448     * </pre>
1449     *
1450     * After the above code is executed, <code>obj</code> will contain
1451     * a new <code>File</code> instance for the C drive dev directory.
1452     * Furthermore, that <code>File</code> instance is the value for the
1453     * <code>"C:/dev"</code> key in the map.
1454     * <p>
1455     * If a lazy map is wrapped by a synchronized map, the result is a simple
1456     * synchronized cache. When an object is not is the cache, the cache itself
1457     * calls back to the factory Transformer to populate itself, all within the
1458     * same synchronized block.
1459     *
1460     * @param map the map to make lazy, must not be null
1461     * @param transformerFactory the factory for creating new objects, must not be null
1462     * @return a lazy map backed by the given map
1463     * @throws IllegalArgumentException if the Map or Transformer is null
1464     */

1465    public static SortedMap JavaDoc lazySortedMap(SortedMap JavaDoc map, Transformer transformerFactory) {
1466        return LazySortedMap.decorate(map, transformerFactory);
1467    }
1468
1469}
1470
Popular Tags