001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.configuration;
019
020 import java.awt.Color;
021 import java.io.Serializable;
022 import java.lang.reflect.Array;
023 import java.math.BigDecimal;
024 import java.math.BigInteger;
025 import java.net.URL;
026 import java.util.ArrayList;
027 import java.util.Calendar;
028 import java.util.Collection;
029 import java.util.Date;
030 import java.util.Iterator;
031 import java.util.List;
032 import java.util.Locale;
033 import java.util.NoSuchElementException;
034
035 import org.apache.commons.lang.ClassUtils;
036 import org.apache.commons.lang.StringUtils;
037
038 /**
039 * Decorator providing additional getters for any Configuration. This extended
040 * Configuration supports more types:
041 * <ul>
042 * <li>{@link java.net.URL}</li>
043 * <li>{@link java.util.Locale}</li>
044 * <li>{@link java.util.Date}</li>
045 * <li>{@link java.util.Calendar}</li>
046 * <li>{@link java.awt.Color}</li>
047 * <li>{@link java.net.InetAddress}</li>
048 * <li>{@link javax.mail.internet.InternetAddress} (requires Javamail in the classpath)</li>
049 * <li>{@link java.lang.Enum} (Java 5 enumeration types)</li>
050 * </ul>
051 *
052 * Lists and arrays are available for all types.
053 *
054 * <h4>Example</h4>
055 *
056 * Configuration file <tt>config.properties</tt>:
057 * <pre>
058 * title.color = #0000FF
059 * remote.host = 192.168.0.53
060 * default.locales = fr,en,de
061 * email.contact = ebourg@apache.org, oheger@apache.org
062 * </pre>
063 *
064 * Usage:
065 *
066 * <pre>
067 * DataConfiguration config = new DataConfiguration(new PropertiesConfiguration("config.properties"));
068 *
069 * // retrieve a property using a specialized getter
070 * Color color = config.getColor("title.color");
071 *
072 * // retrieve a property using a generic getter
073 * InetAddress host = (InetAddress) config.get(InetAddress.class, "remote.host");
074 * Locale[] locales = (Locale[]) config.getArray(Locale.class, "default.locales");
075 * List contacts = config.getList(InternetAddress.class, "email.contact");
076 * </pre>
077 *
078 * <h4>Dates</h4>
079 *
080 * Date objects are expected to be formatted with the pattern <tt>yyyy-MM-dd HH:mm:ss</tt>.
081 * This default format can be changed by specifying another format in the
082 * getters, or by putting a date format in the configuration under the key
083 * <tt>org.apache.commons.configuration.format.date</tt>.
084 *
085 * @author <a href="ebourg@apache.org">Emmanuel Bourg</a>
086 * @version $Id: DataConfiguration.java 1234985 2012-01-23 21:09:09Z oheger $
087 * @since 1.1
088 */
089 public class DataConfiguration extends AbstractConfiguration implements Serializable
090 {
091 /** The key of the property storing the user defined date format. */
092 public static final String DATE_FORMAT_KEY = "org.apache.commons.configuration.format.date";
093
094 /** The default format for dates. */
095 public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
096
097 /**
098 * The serial version UID.
099 */
100 private static final long serialVersionUID = -69011336405718640L;
101
102 /** Stores the wrapped configuration.*/
103 protected Configuration configuration;
104
105 /**
106 * Creates a new instance of {@code DataConfiguration} and sets the
107 * wrapped configuration.
108 *
109 * @param configuration the wrapped configuration
110 */
111 public DataConfiguration(Configuration configuration)
112 {
113 this.configuration = configuration;
114 }
115
116 /**
117 * Return the configuration decorated by this DataConfiguration.
118 *
119 * @return the wrapped configuration
120 */
121 public Configuration getConfiguration()
122 {
123 return configuration;
124 }
125
126 public Object getProperty(String key)
127 {
128 return configuration.getProperty(key);
129 }
130
131 @Override
132 protected void addPropertyDirect(String key, Object obj)
133 {
134 if (configuration instanceof AbstractConfiguration)
135 {
136 ((AbstractConfiguration) configuration).addPropertyDirect(key, obj);
137 }
138 else
139 {
140 configuration.addProperty(key, obj);
141 }
142 }
143
144 @Override
145 public void addProperty(String key, Object value)
146 {
147 getConfiguration().addProperty(key, value);
148 }
149
150 public boolean isEmpty()
151 {
152 return configuration.isEmpty();
153 }
154
155 public boolean containsKey(String key)
156 {
157 return configuration.containsKey(key);
158 }
159
160 @Override
161 public void clearProperty(String key)
162 {
163 configuration.clearProperty(key);
164 }
165
166 @Override
167 public void setProperty(String key, Object value)
168 {
169 configuration.setProperty(key, value);
170 }
171
172 public Iterator<String> getKeys()
173 {
174 return configuration.getKeys();
175 }
176
177 /**
178 * Get an object of the specified type associated with the given
179 * configuration key. If the key doesn't map to an existing object, the
180 * method returns null unless {@link #isThrowExceptionOnMissing()} is set
181 * to <tt>true</tt>.
182 *
183 * @param <T> the target type of the value
184 * @param cls the target class of the value
185 * @param key the key of the value
186 *
187 * @return the value of the requested type for the key
188 *
189 * @throws NoSuchElementException if the key doesn't map to an existing
190 * object and <tt>throwExceptionOnMissing=true</tt>
191 * @throws ConversionException if the value is not compatible with the requested type
192 *
193 * @since 1.5
194 */
195 public <T> T get(Class<T> cls, String key)
196 {
197 T value = get(cls, key, null);
198 if (value != null)
199 {
200 return value;
201 }
202 else if (isThrowExceptionOnMissing())
203 {
204 throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
205 }
206 else
207 {
208 return null;
209 }
210 }
211
212 /**
213 * Get an object of the specified type associated with the given
214 * configuration key. If the key doesn't map to an existing object, the
215 * default value is returned.
216 *
217 * @param <T> the target type of the value
218 * @param cls the target class of the value
219 * @param key the key of the value
220 * @param defaultValue the default value
221 *
222 * @return the value of the requested type for the key
223 *
224 * @throws ConversionException if the value is not compatible with the requested type
225 *
226 * @since 1.5
227 */
228 public <T> T get(Class<T> cls, String key, T defaultValue)
229 {
230 Object value = resolveContainerStore(key);
231
232 if (value == null)
233 {
234 return defaultValue;
235 }
236
237 if (Date.class.equals(cls) || Calendar.class.equals(cls))
238 {
239 return convert(cls, key, interpolate(value), new String[] {getDefaultDateFormat()});
240 }
241 else
242 {
243 return convert(cls, key, interpolate(value), null);
244 }
245 }
246
247 /**
248 * Get a list of typed objects associated with the given configuration key.
249 * If the key doesn't map to an existing object, an empty list is returned.
250 *
251 * @param <T> the type expected for the elements of the list
252 * @param cls the class expected for the elements of the list
253 * @param key The configuration key.
254 * @return The associated list if the key is found.
255 *
256 * @throws ConversionException is thrown if the key maps to an object that
257 * is not compatible with a list of the specified class.
258 *
259 * @since 1.5
260 */
261 public <T> List<T> getList(Class<T> cls, String key)
262 {
263 return getList(cls, key, new ArrayList<T>());
264 }
265
266 /**
267 * Get a list of typed objects associated with the given configuration key.
268 * If the key doesn't map to an existing object, the default value is
269 * returned.
270 *
271 * @param <T> the type expected for the elements of the list
272 * @param cls the class expected for the elements of the list
273 * @param key the configuration key.
274 * @param defaultValue the default value.
275 * @return The associated List.
276 *
277 * @throws ConversionException is thrown if the key maps to an object that
278 * is not compatible with a list of the specified class.
279 *
280 * @since 1.5
281 */
282 public <T> List<T> getList(Class<T> cls, String key, List<T> defaultValue)
283 {
284 Object value = getProperty(key);
285 Class<?> valueClass = value != null ? value.getClass() : null;
286
287 List<T> list;
288
289 if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
290 {
291 // the value is null or is an empty string
292 list = defaultValue;
293 }
294 else
295 {
296 list = new ArrayList<T>();
297
298 Object[] params = null;
299 if (cls.equals(Date.class) || cls.equals(Calendar.class))
300 {
301 params = new Object[] {getDefaultDateFormat()};
302 }
303
304 if (valueClass.isArray())
305 {
306 // get the class of the objects contained in the array
307 Class<?> arrayType = valueClass.getComponentType();
308 int length = Array.getLength(value);
309
310 if (arrayType.equals(cls)
311 || (arrayType.isPrimitive() && cls.equals(ClassUtils.primitiveToWrapper(arrayType))))
312 {
313 // the value is an array of the specified type, or an array
314 // of the primitive type derived from the specified type
315 for (int i = 0; i < length; i++)
316 {
317 list.add(cls.cast(Array.get(value, i)));
318 }
319 }
320 else
321 {
322 // attempt to convert the elements of the array
323 for (int i = 0; i < length; i++)
324 {
325 list.add(convert(cls, key, interpolate(Array.get(value, i)), params));
326 }
327 }
328 }
329 else if (value instanceof Collection)
330 {
331 Collection<?> values = (Collection<?>) value;
332
333 for (Object o : values)
334 {
335 list.add(convert(cls, key, interpolate(o), params));
336 }
337 }
338 else
339 {
340 // attempt to convert a single value
341 list.add(convert(cls, key, interpolate(value), params));
342 }
343 }
344
345 return list;
346 }
347
348 /**
349 * Get an array of typed objects associated with the given configuration key.
350 * If the key doesn't map to an existing object, an empty list is returned.
351 *
352 * @param cls the type expected for the elements of the array
353 * @param key The configuration key.
354 * @return The associated array if the key is found, and the value compatible with the type specified.
355 *
356 * @throws ConversionException is thrown if the key maps to an object that
357 * is not compatible with a list of the specified class.
358 *
359 * @since 1.5
360 */
361 public Object getArray(Class<?> cls, String key)
362 {
363 return getArray(cls, key, Array.newInstance(cls, 0));
364 }
365
366 /**
367 * Get an array of typed objects associated with the given configuration key.
368 * If the key doesn't map to an existing object, the default value is returned.
369 *
370 * @param cls the type expected for the elements of the array
371 * @param key the configuration key.
372 * @param defaultValue the default value
373 * @return The associated array if the key is found, and the value compatible with the type specified.
374 *
375 * @throws ConversionException is thrown if the key maps to an object that
376 * is not compatible with an array of the specified class.
377 * @throws IllegalArgumentException if the default value is not an array of the specified type
378 *
379 * @since 1.5
380 */
381 public Object getArray(Class<?> cls, String key, Object defaultValue)
382 {
383 // check the type of the default value
384 if (defaultValue != null
385 && (!defaultValue.getClass().isArray() || !cls
386 .isAssignableFrom(defaultValue.getClass()
387 .getComponentType())))
388 {
389 throw new IllegalArgumentException(
390 "The type of the default value (" + defaultValue.getClass()
391 + ")" + " is not an array of the specified class ("
392 + cls + ")");
393 }
394
395 if (cls.isPrimitive())
396 {
397 return getPrimitiveArray(cls, key, defaultValue);
398 }
399
400 List<?> list = getList(cls, key);
401 if (list.isEmpty())
402 {
403 return defaultValue;
404 }
405 else
406 {
407 return list.toArray((Object[]) Array.newInstance(cls, list.size()));
408 }
409 }
410
411 /**
412 * Get an array of primitive values associated with the given configuration key.
413 * If the key doesn't map to an existing object, the default value is returned.
414 *
415 * @param cls the primitive type expected for the elements of the array
416 * @param key the configuration key.
417 * @param defaultValue the default value
418 * @return The associated array if the key is found, and the value compatible with the type specified.
419 *
420 * @throws ConversionException is thrown if the key maps to an object that
421 * is not compatible with an array of the specified class.
422 *
423 * @since 1.5
424 */
425 private Object getPrimitiveArray(Class<?> cls, String key, Object defaultValue)
426 {
427 Object value = getProperty(key);
428 Class<?> valueClass = value != null ? value.getClass() : null;
429
430 Object array;
431
432 if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
433 {
434 // the value is null or is an empty string
435 array = defaultValue;
436 }
437 else
438 {
439 if (valueClass.isArray())
440 {
441 // get the class of the objects contained in the array
442 Class<?> arrayType = valueClass.getComponentType();
443 int length = Array.getLength(value);
444
445 if (arrayType.equals(cls))
446 {
447 // the value is an array of the same primitive type
448 array = value;
449 }
450 else if (arrayType.equals(ClassUtils.primitiveToWrapper(cls)))
451 {
452 // the value is an array of the wrapper type derived from the specified primitive type
453 array = Array.newInstance(cls, length);
454
455 for (int i = 0; i < length; i++)
456 {
457 Array.set(array, i, Array.get(value, i));
458 }
459 }
460 else
461 {
462 throw new ConversionException('\'' + key + "' (" + arrayType + ")"
463 + " doesn't map to a compatible array of " + cls);
464 }
465 }
466 else if (value instanceof Collection)
467 {
468 Collection<?> values = (Collection<?>) value;
469
470 array = Array.newInstance(cls, values.size());
471
472 int i = 0;
473 for (Object o : values)
474 {
475 // This is safe because PropertyConverter can handle
476 // conversion to wrapper classes correctly.
477 @SuppressWarnings("unchecked")
478 Object convertedValue = convert(ClassUtils.primitiveToWrapper(cls), key, interpolate(o), null);
479 Array.set(array, i++, convertedValue);
480 }
481 }
482 else
483 {
484 // attempt to convert a single value
485 // This is safe because PropertyConverter can handle
486 // conversion to wrapper classes correctly.
487 @SuppressWarnings("unchecked")
488 Object convertedValue = convert(ClassUtils.primitiveToWrapper(cls), key, interpolate(value), null);
489
490 // create an array of one element
491 array = Array.newInstance(cls, 1);
492 Array.set(array, 0, convertedValue);
493 }
494 }
495
496 return array;
497 }
498
499 /**
500 * Get a list of Boolean objects associated with the given
501 * configuration key. If the key doesn't map to an existing object
502 * an empty list is returned.
503 *
504 * @param key The configuration key.
505 * @return The associated Boolean list if the key is found.
506 *
507 * @throws ConversionException is thrown if the key maps to an
508 * object that is not a list of booleans.
509 */
510 public List<Boolean> getBooleanList(String key)
511 {
512 return getBooleanList(key, new ArrayList<Boolean>());
513 }
514
515 /**
516 * Get a list of Boolean objects associated with the given
517 * configuration key. If the key doesn't map to an existing object,
518 * the default value is returned.
519 *
520 * @param key The configuration key.
521 * @param defaultValue The default value.
522 * @return The associated List of Booleans.
523 *
524 * @throws ConversionException is thrown if the key maps to an
525 * object that is not a list of booleans.
526 */
527 public List<Boolean> getBooleanList(String key, List<Boolean> defaultValue)
528 {
529 return getList(Boolean.class, key, defaultValue);
530 }
531
532 /**
533 * Get an array of boolean primitives associated with the given
534 * configuration key. If the key doesn't map to an existing object
535 * an empty array is returned.
536 *
537 * @param key The configuration key.
538 * @return The associated boolean array if the key is found.
539 *
540 * @throws ConversionException is thrown if the key maps to an
541 * object that is not a list of booleans.
542 */
543 public boolean[] getBooleanArray(String key)
544 {
545 return (boolean[]) getArray(Boolean.TYPE, key);
546 }
547
548 /**
549 * Get an array of boolean primitives associated with the given
550 * configuration key. If the key doesn't map to an existing object,
551 * the default value is returned.
552 *
553 * @param key The configuration key.
554 * @param defaultValue The default value.
555 * @return The associated boolean array if the key is found.
556 *
557 * @throws ConversionException is thrown if the key maps to an
558 * object that is not a list of booleans.
559 */
560 public boolean[] getBooleanArray(String key, boolean[] defaultValue)
561 {
562 return (boolean[]) getArray(Boolean.TYPE, key, defaultValue);
563 }
564
565 /**
566 * Get a list of Byte objects associated with the given configuration key.
567 * If the key doesn't map to an existing object an empty list is returned.
568 *
569 * @param key The configuration key.
570 * @return The associated Byte list if the key is found.
571 *
572 * @throws ConversionException is thrown if the key maps to an
573 * object that is not a list of bytes.
574 */
575 public List<Byte> getByteList(String key)
576 {
577 return getByteList(key, new ArrayList<Byte>());
578 }
579
580 /**
581 * Get a list of Byte objects associated with the given configuration key.
582 * If the key doesn't map to an existing object, the default value is
583 * returned.
584 *
585 * @param key The configuration key.
586 * @param defaultValue The default value.
587 * @return The associated List of Bytes.
588 *
589 * @throws ConversionException is thrown if the key maps to an
590 * object that is not a list of bytes.
591 */
592 public List<Byte> getByteList(String key, List<Byte> defaultValue)
593 {
594 return getList(Byte.class, key, defaultValue);
595 }
596
597 /**
598 * Get an array of byte primitives associated with the given
599 * configuration key. If the key doesn't map to an existing object
600 * an empty array is returned.
601 *
602 * @param key The configuration key.
603 * @return The associated byte array if the key is found.
604 *
605 * @throws ConversionException is thrown if the key maps to an
606 * object that is not a list of bytes.
607 */
608 public byte[] getByteArray(String key)
609 {
610 return getByteArray(key, new byte[0]);
611 }
612
613 /**
614 * Get an array of byte primitives associated with the given
615 * configuration key. If the key doesn't map to an existing object
616 * an empty array is returned.
617 *
618 * @param key The configuration key.
619 * @param defaultValue the default value, which will be returned if the property is not found
620 * @return The associated byte array if the key is found.
621 *
622 * @throws ConversionException is thrown if the key maps to an
623 * object that is not a list of bytes.
624 */
625 public byte[] getByteArray(String key, byte[] defaultValue)
626 {
627 return (byte[]) getArray(Byte.TYPE, key, defaultValue);
628 }
629
630 /**
631 * Get a list of Short objects associated with the given configuration key.
632 * If the key doesn't map to an existing object an empty list is returned.
633 *
634 * @param key The configuration key.
635 * @return The associated Short list if the key is found.
636 *
637 * @throws ConversionException is thrown if the key maps to an
638 * object that is not a list of shorts.
639 */
640 public List<Short> getShortList(String key)
641 {
642 return getShortList(key, new ArrayList<Short>());
643 }
644
645 /**
646 * Get a list of Short objects associated with the given configuration key.
647 * If the key doesn't map to an existing object, the default value is
648 * returned.
649 *
650 * @param key The configuration key.
651 * @param defaultValue The default value.
652 * @return The associated List of Shorts.
653 *
654 * @throws ConversionException is thrown if the key maps to an
655 * object that is not a list of shorts.
656 */
657 public List<Short> getShortList(String key, List<Short> defaultValue)
658 {
659 return getList(Short.class, key, defaultValue);
660 }
661
662 /**
663 * Get an array of short primitives associated with the given
664 * configuration key. If the key doesn't map to an existing object
665 * an empty array is returned.
666 *
667 * @param key The configuration key.
668 * @return The associated short array if the key is found.
669 *
670 * @throws ConversionException is thrown if the key maps to an
671 * object that is not a list of shorts.
672 */
673 public short[] getShortArray(String key)
674 {
675 return getShortArray(key, new short[0]);
676 }
677
678 /**
679 * Get an array of short primitives associated with the given
680 * configuration key. If the key doesn't map to an existing object
681 * an empty array is returned.
682 *
683 * @param key The configuration key.
684 * @param defaultValue the default value, which will be returned if the property is not found
685 * @return The associated short array if the key is found.
686 *
687 * @throws ConversionException is thrown if the key maps to an
688 * object that is not a list of shorts.
689 */
690 public short[] getShortArray(String key, short[] defaultValue)
691 {
692 return (short[]) getArray(Short.TYPE, key, defaultValue);
693 }
694
695 /**
696 * Get a list of Integer objects associated with the given
697 * configuration key. If the key doesn't map to an existing object
698 * an empty list is returned.
699 *
700 * @param key The configuration key.
701 * @return The associated Integer list if the key is found.
702 *
703 * @throws ConversionException is thrown if the key maps to an
704 * object that is not a list of integers.
705 */
706 public List<Integer> getIntegerList(String key)
707 {
708 return getIntegerList(key, new ArrayList<Integer>());
709 }
710
711 /**
712 * Get a list of Integer objects associated with the given
713 * configuration key. If the key doesn't map to an existing object,
714 * the default value is returned.
715 *
716 * @param key The configuration key.
717 * @param defaultValue The default value.
718 * @return The associated List of Integers.
719 *
720 * @throws ConversionException is thrown if the key maps to an
721 * object that is not a list of integers.
722 */
723 public List<Integer> getIntegerList(String key, List<Integer> defaultValue)
724 {
725 return getList(Integer.class, key, defaultValue);
726 }
727
728 /**
729 * Get an array of int primitives associated with the given
730 * configuration key. If the key doesn't map to an existing object
731 * an empty array is returned.
732 *
733 * @param key The configuration key.
734 * @return The associated int array if the key is found.
735 *
736 * @throws ConversionException is thrown if the key maps to an
737 * object that is not a list of integers.
738 */
739 public int[] getIntArray(String key)
740 {
741 return getIntArray(key, new int[0]);
742 }
743
744 /**
745 * Get an array of int primitives associated with the given
746 * configuration key. If the key doesn't map to an existing object
747 * an empty array is returned.
748 *
749 * @param key The configuration key.
750 * @param defaultValue the default value, which will be returned if the property is not found
751 * @return The associated int array if the key is found.
752 *
753 * @throws ConversionException is thrown if the key maps to an
754 * object that is not a list of integers.
755 */
756 public int[] getIntArray(String key, int[] defaultValue)
757 {
758 return (int[]) getArray(Integer.TYPE, key, defaultValue);
759 }
760
761 /**
762 * Get a list of Long objects associated with the given configuration key.
763 * If the key doesn't map to an existing object an empty list is returned.
764 *
765 * @param key The configuration key.
766 * @return The associated Long list if the key is found.
767 *
768 * @throws ConversionException is thrown if the key maps to an
769 * object that is not a list of longs.
770 */
771 public List<Long> getLongList(String key)
772 {
773 return getLongList(key, new ArrayList<Long>());
774 }
775
776 /**
777 * Get a list of Long objects associated with the given configuration key.
778 * If the key doesn't map to an existing object, the default value is
779 * returned.
780 *
781 * @param key The configuration key.
782 * @param defaultValue The default value.
783 * @return The associated List of Longs.
784 *
785 * @throws ConversionException is thrown if the key maps to an
786 * object that is not a list of longs.
787 */
788 public List<Long> getLongList(String key, List<Long> defaultValue)
789 {
790 return getList(Long.class, key, defaultValue);
791 }
792
793 /**
794 * Get an array of long primitives associated with the given
795 * configuration key. If the key doesn't map to an existing object
796 * an empty array is returned.
797 *
798 * @param key The configuration key.
799 * @return The associated long array if the key is found.
800 *
801 * @throws ConversionException is thrown if the key maps to an
802 * object that is not a list of longs.
803 */
804 public long[] getLongArray(String key)
805 {
806 return getLongArray(key, new long[0]);
807 }
808
809 /**
810 * Get an array of long primitives associated with the given
811 * configuration key. If the key doesn't map to an existing object
812 * an empty array is returned.
813 *
814 * @param key The configuration key.
815 * @param defaultValue the default value, which will be returned if the property is not found
816 * @return The associated long array if the key is found.
817 *
818 * @throws ConversionException is thrown if the key maps to an
819 * object that is not a list of longs.
820 */
821 public long[] getLongArray(String key, long[] defaultValue)
822 {
823 return (long[]) getArray(Long.TYPE, key, defaultValue);
824 }
825
826 /**
827 * Get a list of Float objects associated with the given configuration key.
828 * If the key doesn't map to an existing object an empty list is returned.
829 *
830 * @param key The configuration key.
831 * @return The associated Float list if the key is found.
832 *
833 * @throws ConversionException is thrown if the key maps to an
834 * object that is not a list of floats.
835 */
836 public List<Float> getFloatList(String key)
837 {
838 return getFloatList(key, new ArrayList<Float>());
839 }
840
841 /**
842 * Get a list of Float objects associated with the given
843 * configuration key. If the key doesn't map to an existing object,
844 * the default value is returned.
845 *
846 * @param key The configuration key.
847 * @param defaultValue The default value.
848 * @return The associated List of Floats.
849 *
850 * @throws ConversionException is thrown if the key maps to an
851 * object that is not a list of floats.
852 */
853 public List<Float> getFloatList(String key, List<Float> defaultValue)
854 {
855 return getList(Float.class, key, defaultValue);
856 }
857
858 /**
859 * Get an array of float primitives associated with the given
860 * configuration key. If the key doesn't map to an existing object
861 * an empty array is returned.
862 *
863 * @param key The configuration key.
864 * @return The associated float array if the key is found.
865 *
866 * @throws ConversionException is thrown if the key maps to an
867 * object that is not a list of floats.
868 */
869 public float[] getFloatArray(String key)
870 {
871 return getFloatArray(key, new float[0]);
872 }
873
874 /**
875 * Get an array of float primitives associated with the given
876 * configuration key. If the key doesn't map to an existing object
877 * an empty array is returned.
878 *
879 * @param key The configuration key.
880 * @param defaultValue the default value, which will be returned if the property is not found
881 * @return The associated float array if the key is found.
882 *
883 * @throws ConversionException is thrown if the key maps to an
884 * object that is not a list of floats.
885 */
886 public float[] getFloatArray(String key, float[] defaultValue)
887 {
888 return (float[]) getArray(Float.TYPE, key, defaultValue);
889 }
890
891 /**
892 * Get a list of Double objects associated with the given
893 * configuration key. If the key doesn't map to an existing object
894 * an empty list is returned.
895 *
896 * @param key The configuration key.
897 * @return The associated Double list if the key is found.
898 *
899 * @throws ConversionException is thrown if the key maps to an
900 * object that is not a list of doubles.
901 */
902 public List<Double> getDoubleList(String key)
903 {
904 return getDoubleList(key, new ArrayList<Double>());
905 }
906
907 /**
908 * Get a list of Double objects associated with the given
909 * configuration key. If the key doesn't map to an existing object,
910 * the default value is returned.
911 *
912 * @param key The configuration key.
913 * @param defaultValue The default value.
914 * @return The associated List of Doubles.
915 *
916 * @throws ConversionException is thrown if the key maps to an
917 * object that is not a list of doubles.
918 */
919 public List<Double> getDoubleList(String key, List<Double> defaultValue)
920 {
921 return getList(Double.class, key, defaultValue);
922 }
923
924 /**
925 * Get an array of double primitives associated with the given
926 * configuration key. If the key doesn't map to an existing object
927 * an empty array is returned.
928 *
929 * @param key The configuration key.
930 * @return The associated double array if the key is found.
931 *
932 * @throws ConversionException is thrown if the key maps to an
933 * object that is not a list of doubles.
934 */
935 public double[] getDoubleArray(String key)
936 {
937 return getDoubleArray(key, new double[0]);
938 }
939
940 /**
941 * Get an array of double primitives associated with the given
942 * configuration key. If the key doesn't map to an existing object
943 * an empty array is returned.
944 *
945 * @param key The configuration key.
946 * @param defaultValue the default value, which will be returned if the property is not found
947 * @return The associated double array if the key is found.
948 *
949 * @throws ConversionException is thrown if the key maps to an
950 * object that is not a list of doubles.
951 */
952 public double[] getDoubleArray(String key, double[] defaultValue)
953 {
954 return (double[]) getArray(Double.TYPE, key, defaultValue);
955 }
956
957 /**
958 * Get a list of BigIntegers associated with the given configuration key.
959 * If the key doesn't map to an existing object an empty list is returned.
960 *
961 * @param key The configuration key.
962 * @return The associated BigInteger list if the key is found.
963 *
964 * @throws ConversionException is thrown if the key maps to an
965 * object that is not a list of BigIntegers.
966 */
967 public List<BigInteger> getBigIntegerList(String key)
968 {
969 return getBigIntegerList(key, new ArrayList<BigInteger>());
970 }
971
972 /**
973 * Get a list of BigIntegers associated with the given configuration key.
974 * If the key doesn't map to an existing object, the default value is
975 * returned.
976 *
977 * @param key The configuration key.
978 * @param defaultValue The default value.
979 * @return The associated List of BigIntegers.
980 *
981 * @throws ConversionException is thrown if the key maps to an
982 * object that is not a list of BigIntegers.
983 */
984 public List<BigInteger> getBigIntegerList(String key, List<BigInteger> defaultValue)
985 {
986 return getList(BigInteger.class, key, defaultValue);
987 }
988
989 /**
990 * Get an array of BigIntegers associated with the given
991 * configuration key. If the key doesn't map to an existing object
992 * an empty array is returned.
993 *
994 * @param key The configuration key.
995 * @return The associated BigInteger array if the key is found.
996 *
997 * @throws ConversionException is thrown if the key maps to an
998 * object that is not a list of BigIntegers.
999 */
1000 public BigInteger[] getBigIntegerArray(String key)
1001 {
1002 return getBigIntegerArray(key, new BigInteger[0]);
1003 }
1004
1005 /**
1006 * Get an array of BigIntegers associated with the given
1007 * configuration key. If the key doesn't map to an existing object
1008 * an empty array is returned.
1009 *
1010 * @param key The configuration key.
1011 * @param defaultValue the default value, which will be returned if the property is not found
1012 * @return The associated BigInteger array if the key is found.
1013 *
1014 * @throws ConversionException is thrown if the key maps to an
1015 * object that is not a list of BigIntegers.
1016 */
1017 public BigInteger[] getBigIntegerArray(String key, BigInteger[] defaultValue)
1018 {
1019 return (BigInteger[]) getArray(BigInteger.class, key, defaultValue);
1020 }
1021
1022 /**
1023 * Get a list of BigDecimals associated with the given configuration key.
1024 * If the key doesn't map to an existing object an empty list is returned.
1025 *
1026 * @param key The configuration key.
1027 * @return The associated BigDecimal list if the key is found.
1028 *
1029 * @throws ConversionException is thrown if the key maps to an
1030 * object that is not a list of BigDecimals.
1031 */
1032 public List<BigDecimal> getBigDecimalList(String key)
1033 {
1034 return getBigDecimalList(key, new ArrayList<BigDecimal>());
1035 }
1036
1037 /**
1038 * Get a list of BigDecimals associated with the given configuration key.
1039 * If the key doesn't map to an existing object, the default value is
1040 * returned.
1041 *
1042 * @param key The configuration key.
1043 * @param defaultValue The default value.
1044 * @return The associated List of BigDecimals.
1045 *
1046 * @throws ConversionException is thrown if the key maps to an
1047 * object that is not a list of BigDecimals.
1048 */
1049 public List<BigDecimal> getBigDecimalList(String key, List<BigDecimal> defaultValue)
1050 {
1051 return getList(BigDecimal.class, key, defaultValue);
1052 }
1053
1054 /**
1055 * Get an array of BigDecimals associated with the given
1056 * configuration key. If the key doesn't map to an existing object
1057 * an empty array is returned.
1058 *
1059 * @param key The configuration key.
1060 * @return The associated BigDecimal array if the key is found.
1061 *
1062 * @throws ConversionException is thrown if the key maps to an
1063 * object that is not a list of BigDecimals.
1064 */
1065 public BigDecimal[] getBigDecimalArray(String key)
1066 {
1067 return getBigDecimalArray(key, new BigDecimal[0]);
1068 }
1069
1070 /**
1071 * Get an array of BigDecimals associated with the given
1072 * configuration key. If the key doesn't map to an existing object
1073 * an empty array is returned.
1074 *
1075 * @param key The configuration key.
1076 * @param defaultValue the default value, which will be returned if the property is not found
1077 * @return The associated BigDecimal array if the key is found.
1078 *
1079 * @throws ConversionException is thrown if the key maps to an
1080 * object that is not a list of BigDecimals.
1081 */
1082 public BigDecimal[] getBigDecimalArray(String key, BigDecimal[] defaultValue)
1083 {
1084 return (BigDecimal[]) getArray(BigDecimal.class, key, defaultValue);
1085 }
1086
1087 /**
1088 * Get an URL associated with the given configuration key.
1089 *
1090 * @param key The configuration key.
1091 * @return The associated URL.
1092 *
1093 * @throws ConversionException is thrown if the key maps to an
1094 * object that is not an URL.
1095 */
1096 public URL getURL(String key)
1097 {
1098 return get(URL.class, key);
1099 }
1100
1101 /**
1102 * Get an URL associated with the given configuration key.
1103 * If the key doesn't map to an existing object, the default value
1104 * is returned.
1105 *
1106 * @param key The configuration key.
1107 * @param defaultValue The default value.
1108 * @return The associated URL.
1109 *
1110 * @throws ConversionException is thrown if the key maps to an
1111 * object that is not an URL.
1112 */
1113 public URL getURL(String key, URL defaultValue)
1114 {
1115 return get(URL.class, key, defaultValue);
1116 }
1117
1118 /**
1119 * Get a list of URLs associated with the given configuration key.
1120 * If the key doesn't map to an existing object an empty list is returned.
1121 *
1122 * @param key The configuration key.
1123 * @return The associated URL list if the key is found.
1124 *
1125 * @throws ConversionException is thrown if the key maps to an
1126 * object that is not a list of URLs.
1127 */
1128 public List<URL> getURLList(String key)
1129 {
1130 return getURLList(key, new ArrayList<URL>());
1131 }
1132
1133 /**
1134 * Get a list of URLs associated with the given configuration key.
1135 * If the key doesn't map to an existing object, the default value is
1136 * returned.
1137 *
1138 * @param key The configuration key.
1139 * @param defaultValue The default value.
1140 * @return The associated List of URLs.
1141 *
1142 * @throws ConversionException is thrown if the key maps to an
1143 * object that is not a list of URLs.
1144 */
1145 public List<URL> getURLList(String key, List<URL> defaultValue)
1146 {
1147 return getList(URL.class, key, defaultValue);
1148 }
1149
1150 /**
1151 * Get an array of URLs associated with the given configuration key.
1152 * If the key doesn't map to an existing object an empty array is returned.
1153 *
1154 * @param key The configuration key.
1155 * @return The associated URL array if the key is found.
1156 *
1157 * @throws ConversionException is thrown if the key maps to an
1158 * object that is not a list of URLs.
1159 */
1160 public URL[] getURLArray(String key)
1161 {
1162 return getURLArray(key, new URL[0]);
1163 }
1164
1165 /**
1166 * Get an array of URLs associated with the given configuration key.
1167 * If the key doesn't map to an existing object an empty array is returned.
1168 *
1169 * @param key The configuration key.
1170 * @param defaultValue the default value, which will be returned if the property is not found
1171 * @return The associated URL array if the key is found.
1172 *
1173 * @throws ConversionException is thrown if the key maps to an
1174 * object that is not a list of URLs.
1175 */
1176 public URL[] getURLArray(String key, URL[] defaultValue)
1177 {
1178 return (URL[]) getArray(URL.class, key, defaultValue);
1179 }
1180
1181 /**
1182 * Get a Date associated with the given configuration key. If the property
1183 * is a String, it will be parsed with the format defined by the user in
1184 * the {@link #DATE_FORMAT_KEY} property, or if it's not defined with the
1185 * {@link #DEFAULT_DATE_FORMAT} pattern.
1186 *
1187 * @param key The configuration key.
1188 * @return The associated Date.
1189 *
1190 * @throws ConversionException is thrown if the key maps to an
1191 * object that is not a Date.
1192 */
1193 public Date getDate(String key)
1194 {
1195 return get(Date.class, key);
1196 }
1197
1198 /**
1199 * Get a Date associated with the given configuration key. If the property
1200 * is a String, it will be parsed with the specified format pattern.
1201 *
1202 * @param key The configuration key.
1203 * @param format The non-localized {@link java.text.DateFormat} pattern.
1204 * @return The associated Date
1205 *
1206 * @throws ConversionException is thrown if the key maps to an
1207 * object that is not a Date.
1208 */
1209 public Date getDate(String key, String format)
1210 {
1211 Date value = getDate(key, null, format);
1212 if (value != null)
1213 {
1214 return value;
1215 }
1216 else if (isThrowExceptionOnMissing())
1217 {
1218 throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
1219 }
1220 else
1221 {
1222 return null;
1223 }
1224 }
1225
1226 /**
1227 * Get a Date associated with the given configuration key. If the property
1228 * is a String, it will be parsed with the format defined by the user in
1229 * the {@link #DATE_FORMAT_KEY} property, or if it's not defined with the
1230 * {@link #DEFAULT_DATE_FORMAT} pattern. If the key doesn't map to an
1231 * existing object, the default value is returned.
1232 *
1233 * @param key The configuration key.
1234 * @param defaultValue The default value.
1235 * @return The associated Date.
1236 *
1237 * @throws ConversionException is thrown if the key maps to an
1238 * object that is not a Date.
1239 */
1240 public Date getDate(String key, Date defaultValue)
1241 {
1242 return getDate(key, defaultValue, getDefaultDateFormat());
1243 }
1244
1245 /**
1246 * Get a Date associated with the given configuration key. If the property
1247 * is a String, it will be parsed with the specified format pattern.
1248 * If the key doesn't map to an existing object, the default value
1249 * is returned.
1250 *
1251 * @param key The configuration key.
1252 * @param defaultValue The default value.
1253 * @param format The non-localized {@link java.text.DateFormat} pattern.
1254 * @return The associated Date.
1255 *
1256 * @throws ConversionException is thrown if the key maps to an
1257 * object that is not a Date.
1258 */
1259 public Date getDate(String key, Date defaultValue, String format)
1260 {
1261 Object value = resolveContainerStore(key);
1262
1263 if (value == null)
1264 {
1265 return defaultValue;
1266 }
1267 else
1268 {
1269 try
1270 {
1271 return PropertyConverter.toDate(interpolate(value), format);
1272 }
1273 catch (ConversionException e)
1274 {
1275 throw new ConversionException('\'' + key + "' doesn't map to a Date", e);
1276 }
1277 }
1278 }
1279 public List<Date> getDateList(String key)
1280 {
1281 return getDateList(key, new ArrayList<Date>());
1282 }
1283
1284 /**
1285 * Get a list of Dates associated with the given configuration key.
1286 * If the property is a list of Strings, they will be parsed with the
1287 * specified format pattern. If the key doesn't map to an existing object
1288 * an empty list is returned.
1289 *
1290 * @param key The configuration key.
1291 * @param format The non-localized {@link java.text.DateFormat} pattern.
1292 * @return The associated Date list if the key is found.
1293 *
1294 * @throws ConversionException is thrown if the key maps to an
1295 * object that is not a list of Dates.
1296 */
1297 public List<Date> getDateList(String key, String format)
1298 {
1299 return getDateList(key, new ArrayList<Date>(), format);
1300 }
1301
1302 /**
1303 * Get a list of Dates associated with the given configuration key.
1304 * If the property is a list of Strings, they will be parsed with the
1305 * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
1306 * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
1307 * If the key doesn't map to an existing object, the default value is
1308 * returned.
1309 *
1310 * @param key The configuration key.
1311 * @param defaultValue The default value.
1312 * @return The associated Date list if the key is found.
1313 *
1314 * @throws ConversionException is thrown if the key maps to an
1315 * object that is not a list of Dates.
1316 */
1317 public List<Date> getDateList(String key, List<Date> defaultValue)
1318 {
1319 return getDateList(key, defaultValue, getDefaultDateFormat());
1320 }
1321
1322 /**
1323 * Get a list of Dates associated with the given configuration key.
1324 * If the property is a list of Strings, they will be parsed with the
1325 * specified format pattern. If the key doesn't map to an existing object,
1326 * the default value is returned.
1327 *
1328 * @param key The configuration key.
1329 * @param defaultValue The default value.
1330 * @param format The non-localized {@link java.text.DateFormat} pattern.
1331 * @return The associated Date list if the key is found.
1332 *
1333 * @throws ConversionException is thrown if the key maps to an
1334 * object that is not a list of Dates.
1335 */
1336 public List<Date> getDateList(String key, List<Date> defaultValue, String format)
1337 {
1338 Object value = getProperty(key);
1339
1340 List<Date> list;
1341
1342 if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
1343 {
1344 list = defaultValue;
1345 }
1346 else if (value.getClass().isArray())
1347 {
1348 list = new ArrayList<Date>();
1349 int length = Array.getLength(value);
1350 for (int i = 0; i < length; i++)
1351 {
1352 list.add(convert(Date.class, key, interpolate(Array.get(value, i)), new String[] {format}));
1353 }
1354 }
1355 else if (value instanceof Collection)
1356 {
1357 Collection<?> values = (Collection<?>) value;
1358 list = new ArrayList<Date>();
1359
1360 for (Object o : values)
1361 {
1362 list.add(convert(Date.class, key, interpolate(o), new String[] {format}));
1363 }
1364 }
1365 else
1366 {
1367 // attempt to convert a single value
1368 list = new ArrayList<Date>();
1369 list.add(convert(Date.class, key, interpolate(value), new String[] {format}));
1370 }
1371
1372 return list;
1373 }
1374
1375 /**
1376 * Get an array of Dates associated with the given configuration key.
1377 * If the property is a list of Strings, they will be parsed with the
1378 * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
1379 * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
1380 * If the key doesn't map to an existing object an empty array is returned.
1381 *
1382 * @param key The configuration key.
1383 * @return The associated Date array if the key is found.
1384 *
1385 * @throws ConversionException is thrown if the key maps to an
1386 * object that is not a list of Dates.
1387 */
1388 public Date[] getDateArray(String key)
1389 {
1390 return getDateArray(key, new Date[0]);
1391 }
1392
1393 /**
1394 * Get an array of Dates associated with the given configuration key.
1395 * If the property is a list of Strings, they will be parsed with the
1396 * specified format pattern. If the key doesn't map to an existing object
1397 * an empty array is returned.
1398 *
1399 * @param key The configuration key.
1400 * @param format The non-localized {@link java.text.DateFormat} pattern.
1401 * @return The associated Date array if the key is found.
1402 *
1403 * @throws ConversionException is thrown if the key maps to an
1404 * object that is not a list of Dates.
1405 */
1406 public Date[] getDateArray(String key, String format)
1407 {
1408 return getDateArray(key, new Date[0], format);
1409 }
1410
1411 /**
1412 * Get an array of Dates associated with the given configuration key.
1413 * If the property is a list of Strings, they will be parsed with the
1414 * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
1415 * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
1416 * If the key doesn't map to an existing object an empty array is returned.
1417 *
1418 * @param key The configuration key.
1419 * @param defaultValue the default value, which will be returned if the property is not found
1420 * @return The associated Date array if the key is found.
1421 *
1422 * @throws ConversionException is thrown if the key maps to an
1423 * object that is not a list of Dates.
1424 */
1425 public Date[] getDateArray(String key, Date[] defaultValue)
1426 {
1427 return getDateArray(key, defaultValue, getDefaultDateFormat());
1428 }
1429
1430 /**
1431 * Get an array of Dates associated with the given configuration key.
1432 * If the property is a list of Strings, they will be parsed with the
1433 * specified format pattern. If the key doesn't map to an existing object,
1434 * the default value is returned.
1435 *
1436 * @param key The configuration key.
1437 * @param defaultValue The default value.
1438 * @param format The non-localized {@link java.text.DateFormat} pattern.
1439 * @return The associated Date array if the key is found.
1440 *
1441 * @throws ConversionException is thrown if the key maps to an
1442 * object that is not a list of Dates.
1443 */
1444 public Date[] getDateArray(String key, Date[] defaultValue, String format)
1445 {
1446 List<Date> list = getDateList(key, format);
1447 if (list.isEmpty())
1448 {
1449 return defaultValue;
1450 }
1451 else
1452 {
1453 return list.toArray(new Date[list.size()]);
1454 }
1455 }
1456
1457 /**
1458 * Get a Calendar associated with the given configuration key. If the
1459 * property is a String, it will be parsed with the format defined by the
1460 * user in the {@link #DATE_FORMAT_KEY} property, or if it's not defined
1461 * with the {@link #DEFAULT_DATE_FORMAT} pattern.
1462 *
1463 * @param key The configuration key.
1464 * @return The associated Calendar.
1465 *
1466 * @throws ConversionException is thrown if the key maps to an
1467 * object that is not a Calendar.
1468 */
1469 public Calendar getCalendar(String key)
1470 {
1471 return get(Calendar.class, key);
1472 }
1473
1474 /**
1475 * Get a Calendar associated with the given configuration key. If the
1476 * property is a String, it will be parsed with the specified format
1477 * pattern.
1478 *
1479 * @param key The configuration key.
1480 * @param format The non-localized {@link java.text.DateFormat} pattern.
1481 * @return The associated Calendar
1482 *
1483 * @throws ConversionException is thrown if the key maps to an
1484 * object that is not a Calendar.
1485 */
1486 public Calendar getCalendar(String key, String format)
1487 {
1488 Calendar value = getCalendar(key, null, format);
1489 if (value != null)
1490 {
1491 return value;
1492 }
1493 else if (isThrowExceptionOnMissing())
1494 {
1495 throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
1496 }
1497 else
1498 {
1499 return null;
1500 }
1501 }
1502
1503 /**
1504 * Get a Calendar associated with the given configuration key. If the
1505 * property is a String, it will be parsed with the format defined by the
1506 * user in the {@link #DATE_FORMAT_KEY} property, or if it's not defined
1507 * with the {@link #DEFAULT_DATE_FORMAT} pattern. If the key doesn't map
1508 * to an existing object, the default value is returned.
1509 *
1510 * @param key The configuration key.
1511 * @param defaultValue The default value.
1512 * @return The associated Calendar.
1513 *
1514 * @throws ConversionException is thrown if the key maps to an
1515 * object that is not a Calendar.
1516 */
1517 public Calendar getCalendar(String key, Calendar defaultValue)
1518 {
1519 return getCalendar(key, defaultValue, getDefaultDateFormat());
1520 }
1521
1522 /**
1523 * Get a Calendar associated with the given configuration key. If the
1524 * property is a String, it will be parsed with the specified format
1525 * pattern. If the key doesn't map to an existing object, the default
1526 * value is returned.
1527 *
1528 * @param key The configuration key.
1529 * @param defaultValue The default value.
1530 * @param format The non-localized {@link java.text.DateFormat} pattern.
1531 * @return The associated Calendar.
1532 *
1533 * @throws ConversionException is thrown if the key maps to an
1534 * object that is not a Calendar.
1535 */
1536 public Calendar getCalendar(String key, Calendar defaultValue, String format)
1537 {
1538 Object value = resolveContainerStore(key);
1539
1540 if (value == null)
1541 {
1542 return defaultValue;
1543 }
1544 else
1545 {
1546 try
1547 {
1548 return PropertyConverter.toCalendar(interpolate(value), format);
1549 }
1550 catch (ConversionException e)
1551 {
1552 throw new ConversionException('\'' + key + "' doesn't map to a Calendar", e);
1553 }
1554 }
1555 }
1556
1557 /**
1558 * Get a list of Calendars associated with the given configuration key.
1559 * If the property is a list of Strings, they will be parsed with the
1560 * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
1561 * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
1562 * If the key doesn't map to an existing object an empty list is returned.
1563 *
1564 * @param key The configuration key.
1565 * @return The associated Calendar list if the key is found.
1566 *
1567 * @throws ConversionException is thrown if the key maps to an
1568 * object that is not a list of Calendars.
1569 */
1570 public List<Calendar> getCalendarList(String key)
1571 {
1572 return getCalendarList(key, new ArrayList<Calendar>());
1573 }
1574
1575 /**
1576 * Get a list of Calendars associated with the given configuration key.
1577 * If the property is a list of Strings, they will be parsed with the
1578 * specified format pattern. If the key doesn't map to an existing object
1579 * an empty list is returned.
1580 *
1581 * @param key The configuration key.
1582 * @param format The non-localized {@link java.text.DateFormat} pattern.
1583 * @return The associated Calendar list if the key is found.
1584 *
1585 * @throws ConversionException is thrown if the key maps to an
1586 * object that is not a list of Calendars.
1587 */
1588 public List<Calendar> getCalendarList(String key, String format)
1589 {
1590 return getCalendarList(key, new ArrayList<Calendar>(), format);
1591 }
1592
1593 /**
1594 * Get a list of Calendars associated with the given configuration key.
1595 * If the property is a list of Strings, they will be parsed with the
1596 * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
1597 * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
1598 * If the key doesn't map to an existing object, the default value is
1599 * returned.
1600 *
1601 * @param key The configuration key.
1602 * @param defaultValue The default value.
1603 * @return The associated Calendar list if the key is found.
1604 *
1605 * @throws ConversionException is thrown if the key maps to an
1606 * object that is not a list of Calendars.
1607 */
1608 public List<Calendar> getCalendarList(String key, List<Calendar> defaultValue)
1609 {
1610 return getCalendarList(key, defaultValue, getDefaultDateFormat());
1611 }
1612
1613 /**
1614 * Get a list of Calendars associated with the given configuration key.
1615 * If the property is a list of Strings, they will be parsed with the
1616 * specified format pattern. If the key doesn't map to an existing object,
1617 * the default value is returned.
1618 *
1619 * @param key The configuration key.
1620 * @param defaultValue The default value.
1621 * @param format The non-localized {@link java.text.DateFormat} pattern.
1622 * @return The associated Calendar list if the key is found.
1623 *
1624 * @throws ConversionException is thrown if the key maps to an
1625 * object that is not a list of Calendars.
1626 */
1627 public List<Calendar> getCalendarList(String key, List<Calendar> defaultValue, String format)
1628 {
1629 Object value = getProperty(key);
1630
1631 List<Calendar> list;
1632
1633 if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
1634 {
1635 list = defaultValue;
1636 }
1637 else if (value.getClass().isArray())
1638 {
1639 list = new ArrayList<Calendar>();
1640 int length = Array.getLength(value);
1641 for (int i = 0; i < length; i++)
1642 {
1643 list.add(convert(Calendar.class, key, interpolate(Array.get(value, i)), new String[] {format}));
1644 }
1645 }
1646 else if (value instanceof Collection)
1647 {
1648 Collection<?> values = (Collection<?>) value;
1649 list = new ArrayList<Calendar>();
1650
1651 for (Object o : values)
1652 {
1653 list.add(convert(Calendar.class, key, interpolate(o), new String[] {format}));
1654 }
1655 }
1656 else
1657 {
1658 // attempt to convert a single value
1659 list = new ArrayList<Calendar>();
1660 list.add(convert(Calendar.class, key, interpolate(value), new String[] {format}));
1661 }
1662
1663 return list;
1664 }
1665
1666 /**
1667 * Get an array of Calendars associated with the given configuration key.
1668 * If the property is a list of Strings, they will be parsed with the
1669 * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
1670 * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
1671 * If the key doesn't map to an existing object an empty array is returned.
1672 *
1673 * @param key The configuration key.
1674 * @return The associated Calendar array if the key is found.
1675 *
1676 * @throws ConversionException is thrown if the key maps to an
1677 * object that is not a list of Calendars.
1678 */
1679 public Calendar[] getCalendarArray(String key)
1680 {
1681 return getCalendarArray(key, new Calendar[0]);
1682 }
1683
1684 /**
1685 * Get an array of Calendars associated with the given configuration key.
1686 * If the property is a list of Strings, they will be parsed with the
1687 * specified format pattern. If the key doesn't map to an existing object
1688 * an empty array is returned.
1689 *
1690 * @param key The configuration key.
1691 * @param format The non-localized {@link java.text.DateFormat} pattern.
1692 * @return The associated Calendar array if the key is found.
1693 *
1694 * @throws ConversionException is thrown if the key maps to an
1695 * object that is not a list of Calendars.
1696 */
1697 public Calendar[] getCalendarArray(String key, String format)
1698 {
1699 return getCalendarArray(key, new Calendar[0], format);
1700 }
1701
1702 /**
1703 * Get an array of Calendars associated with the given configuration key.
1704 * If the property is a list of Strings, they will be parsed with the
1705 * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
1706 * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
1707 * If the key doesn't map to an existing object an empty array is returned.
1708 *
1709 * @param key The configuration key.
1710 * @param defaultValue the default value, which will be returned if the property is not found
1711 * @return The associated Calendar array if the key is found.
1712 *
1713 * @throws ConversionException is thrown if the key maps to an
1714 * object that is not a list of Calendars.
1715 */
1716 public Calendar[] getCalendarArray(String key, Calendar[] defaultValue)
1717 {
1718 return getCalendarArray(key, defaultValue, getDefaultDateFormat());
1719 }
1720
1721 /**
1722 * Get an array of Calendars associated with the given configuration key.
1723 * If the property is a list of Strings, they will be parsed with the
1724 * specified format pattern. If the key doesn't map to an existing object,
1725 * the default value is returned.
1726 *
1727 * @param key The configuration key.
1728 * @param defaultValue The default value.
1729 * @param format The non-localized {@link java.text.DateFormat} pattern.
1730 * @return The associated Calendar array if the key is found.
1731 *
1732 * @throws ConversionException is thrown if the key maps to an
1733 * object that is not a list of Calendars.
1734 */
1735 public Calendar[] getCalendarArray(String key, Calendar[] defaultValue, String format)
1736 {
1737 List<Calendar> list = getCalendarList(key, format);
1738 if (list.isEmpty())
1739 {
1740 return defaultValue;
1741 }
1742 else
1743 {
1744 return list.toArray(new Calendar[list.size()]);
1745 }
1746 }
1747
1748 /**
1749 * Returns the date format specified by the user in the DATE_FORMAT_KEY
1750 * property, or the default format otherwise.
1751 *
1752 * @return the default date format
1753 */
1754 private String getDefaultDateFormat()
1755 {
1756 return getString(DATE_FORMAT_KEY, DEFAULT_DATE_FORMAT);
1757 }
1758
1759 /**
1760 * Get a Locale associated with the given configuration key.
1761 *
1762 * @param key The configuration key.
1763 * @return The associated Locale.
1764 *
1765 * @throws ConversionException is thrown if the key maps to an
1766 * object that is not a Locale.
1767 */
1768 public Locale getLocale(String key)
1769 {
1770 return get(Locale.class, key);
1771 }
1772
1773 /**
1774 * Get a Locale associated with the given configuration key.
1775 * If the key doesn't map to an existing object, the default value
1776 * is returned.
1777 *
1778 * @param key The configuration key.
1779 * @param defaultValue The default value.
1780 * @return The associated Locale.
1781 *
1782 * @throws ConversionException is thrown if the key maps to an
1783 * object that is not a Locale.
1784 */
1785 public Locale getLocale(String key, Locale defaultValue)
1786 {
1787 return get(Locale.class, key, defaultValue);
1788 }
1789
1790 /**
1791 * Get a list of Locales associated with the given configuration key.
1792 * If the key doesn't map to an existing object an empty list is returned.
1793 *
1794 * @param key The configuration key.
1795 * @return The associated Locale list if the key is found.
1796 *
1797 * @throws ConversionException is thrown if the key maps to an
1798 * object that is not a list of Locales.
1799 */
1800 public List<Locale> getLocaleList(String key)
1801 {
1802 return getLocaleList(key, new ArrayList<Locale>());
1803 }
1804
1805 /**
1806 * Get a list of Locales associated with the given configuration key.
1807 * If the key doesn't map to an existing object, the default value is
1808 * returned.
1809 *
1810 * @param key The configuration key.
1811 * @param defaultValue The default value.
1812 * @return The associated List of Locales.
1813 *
1814 * @throws ConversionException is thrown if the key maps to an
1815 * object that is not a list of Locales.
1816 */
1817 public List<Locale> getLocaleList(String key, List<Locale> defaultValue)
1818 {
1819 return getList(Locale.class, key, defaultValue);
1820 }
1821
1822 /**
1823 * Get an array of Locales associated with the given
1824 * configuration key. If the key doesn't map to an existing object
1825 * an empty array is returned.
1826 *
1827 * @param key The configuration key.
1828 * @return The associated Locale array if the key is found.
1829 *
1830 * @throws ConversionException is thrown if the key maps to an
1831 * object that is not a list of Locales.
1832 */
1833 public Locale[] getLocaleArray(String key)
1834 {
1835 return getLocaleArray(key, new Locale[0]);
1836 }
1837
1838 /**
1839 * Get an array of Locales associated with the given
1840 * configuration key. If the key doesn't map to an existing object
1841 * an empty array is returned.
1842 *
1843 * @param key The configuration key.
1844 * @param defaultValue the default value, which will be returned if the property is not found
1845 * @return The associated Locale array if the key is found.
1846 *
1847 * @throws ConversionException is thrown if the key maps to an
1848 * object that is not a list of Locales.
1849 */
1850 public Locale[] getLocaleArray(String key, Locale[] defaultValue)
1851 {
1852 return (Locale[]) getArray(Locale.class, key, defaultValue);
1853 }
1854
1855 /**
1856 * Get a Color associated with the given configuration key.
1857 *
1858 * @param key The configuration key.
1859 * @return The associated Color.
1860 *
1861 * @throws ConversionException is thrown if the key maps to an
1862 * object that is not a Color.
1863 */
1864 public Color getColor(String key)
1865 {
1866 return get(Color.class, key);
1867 }
1868
1869 /**
1870 * Get a Color associated with the given configuration key.
1871 * If the key doesn't map to an existing object, the default value
1872 * is returned.
1873 *
1874 * @param key The configuration key.
1875 * @param defaultValue The default value.
1876 * @return The associated Color.
1877 *
1878 * @throws ConversionException is thrown if the key maps to an
1879 * object that is not a Color.
1880 */
1881 public Color getColor(String key, Color defaultValue)
1882 {
1883 return get(Color.class, key, defaultValue);
1884 }
1885
1886 /**
1887 * Get a list of Colors associated with the given configuration key.
1888 * If the key doesn't map to an existing object an empty list is returned.
1889 *
1890 * @param key The configuration key.
1891 * @return The associated Color list if the key is found.
1892 *
1893 * @throws ConversionException is thrown if the key maps to an
1894 * object that is not a list of Colors.
1895 */
1896 public List<Color> getColorList(String key)
1897 {
1898 return getColorList(key, new ArrayList<Color>());
1899 }
1900
1901 /**
1902 * Get a list of Colors associated with the given configuration key.
1903 * If the key doesn't map to an existing object, the default value is
1904 * returned.
1905 *
1906 * @param key The configuration key.
1907 * @param defaultValue The default value.
1908 * @return The associated List of Colors.
1909 *
1910 * @throws ConversionException is thrown if the key maps to an
1911 * object that is not a list of Colors.
1912 */
1913 public List<Color> getColorList(String key, List<Color> defaultValue)
1914 {
1915 return getList(Color.class, key, defaultValue);
1916 }
1917
1918 /**
1919 * Get an array of Colors associated with the given
1920 * configuration key. If the key doesn't map to an existing object
1921 * an empty array is returned.
1922 *
1923 * @param key The configuration key.
1924 * @return The associated Color array if the key is found.
1925 *
1926 * @throws ConversionException is thrown if the key maps to an
1927 * object that is not a list of Colors.
1928 */
1929 public Color[] getColorArray(String key)
1930 {
1931 return getColorArray(key, new Color[0]);
1932 }
1933
1934 /**
1935 * Get an array of Colors associated with the given
1936 * configuration key. If the key doesn't map to an existing object
1937 * an empty array is returned.
1938 *
1939 * @param key The configuration key.
1940 * @param defaultValue the default value, which will be returned if the property is not found
1941 * @return The associated Color array if the key is found.
1942 *
1943 * @throws ConversionException is thrown if the key maps to an
1944 * object that is not a list of Colors.
1945 */
1946 public Color[] getColorArray(String key, Color[] defaultValue)
1947 {
1948 return (Color[]) getArray(Color.class, key, defaultValue);
1949 }
1950
1951 /**
1952 * Helper method for performing a type conversion using the
1953 * {@code PropertyConverter} class.
1954 *
1955 * @param <T> the target type of the conversion
1956 * @param cls the target class of the conversion
1957 * @param key the configuration key
1958 * @param value the value to be converted
1959 * @param params additional parameters
1960 * @throws ConversionException if the value is not compatible with the
1961 * requested type
1962 */
1963 private static <T> T convert(Class<T> cls, String key, Object value,
1964 Object[] params)
1965 {
1966 try
1967 {
1968 Object result = PropertyConverter.to(cls, value, params);
1969 // Will not throw a ClassCastException because PropertyConverter
1970 // would have thrown a ConversionException if conversion had failed.
1971 return cls.cast(result);
1972 }
1973 catch (ConversionException e)
1974 {
1975 throw new ConversionException('\'' + key + "' doesn't map to a "
1976 + cls, e);
1977 }
1978 }
1979 }