1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.configuration;
18
19 import java.awt.Color;
20 import java.math.BigDecimal;
21 import java.math.BigInteger;
22 import java.net.MalformedURLException;
23 import java.net.URL;
24 import java.text.ParseException;
25 import java.text.SimpleDateFormat;
26 import java.util.ArrayList;
27 import java.util.Calendar;
28 import java.util.Collection;
29 import java.util.Date;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.Locale;
33
34 import org.apache.commons.collections.IteratorUtils;
35 import org.apache.commons.collections.iterators.IteratorChain;
36 import org.apache.commons.collections.iterators.SingletonIterator;
37 import org.apache.commons.lang.BooleanUtils;
38 import org.apache.commons.lang.StringUtils;
39
40 /***
41 * A utility class to convert the configuration properties into any type.
42 *
43 * @author Emmanuel Bourg
44 * @version $Revision: 155408 $, $Date: 2005-02-26 13:56:39 +0100 (Sa, 26 Feb 2005) $
45 * @since 1.1
46 */
47 public final class PropertyConverter
48 {
49 /***
50 * Convert the specified object into a Boolean.
51 *
52 * @param value the value to convert
53 * @throws ConversionException thrown if the value cannot be converted to a boolean
54 */
55 public static Boolean toBoolean(Object value) throws ConversionException
56 {
57 if (value instanceof Boolean)
58 {
59 return (Boolean) value;
60 }
61 else if (value instanceof String)
62 {
63 Boolean b = BooleanUtils.toBooleanObject((String) value);
64 if (b == null)
65 {
66 throw new ConversionException("The value " + value + " can't be converted to a Boolean object");
67 }
68 return b;
69 }
70 else
71 {
72 throw new ConversionException("The value " + value + " can't be converted to a Boolean object");
73 }
74 }
75
76 /***
77 * Convert the specified object into a Byte.
78 *
79 * @param value the value to convert
80 * @throws ConversionException thrown if the value cannot be converted to a byte
81 */
82 public static Byte toByte(Object value) throws ConversionException
83 {
84 if (value instanceof Byte)
85 {
86 return (Byte) value;
87 }
88 else if (value instanceof String)
89 {
90 try
91 {
92 String string = (String) value;
93 if (string.startsWith("0x"))
94 {
95 return new Byte((byte) Integer.parseInt(string.substring(2), 16));
96 }
97 else
98 {
99 return new Byte(string);
100 }
101 }
102 catch (NumberFormatException e)
103 {
104 throw new ConversionException("The value " + value + " can't be converted to a Byte object", e);
105 }
106 }
107 else
108 {
109 throw new ConversionException("The value " + value + " can't be converted to a Byte object");
110 }
111 }
112
113 /***
114 * Convert the specified object into a Short.
115 *
116 * @param value the value to convert
117 * @throws ConversionException thrown if the value cannot be converted to a short
118 */
119 public static Short toShort(Object value) throws ConversionException
120 {
121 if (value instanceof Short)
122 {
123 return (Short) value;
124 }
125 else if (value instanceof String)
126 {
127 try
128 {
129 String string = (String) value;
130 if (string.startsWith("0x"))
131 {
132 return new Short((short) Integer.parseInt(string.substring(2), 16));
133 }
134 else
135 {
136 return new Short(string);
137 }
138
139 }
140 catch (NumberFormatException e)
141 {
142 throw new ConversionException("The value " + value + " can't be converted to a Short object", e);
143 }
144 }
145 else
146 {
147 throw new ConversionException("The value " + value + " can't be converted to a Short object");
148 }
149 }
150
151 /***
152 * Convert the specified object into an Integer.
153 *
154 * @param value the value to convert
155 * @throws ConversionException thrown if the value cannot be converted to an integer
156 */
157 public static Integer toInteger(Object value) throws ConversionException
158 {
159 if (value instanceof Integer)
160 {
161 return (Integer) value;
162 }
163 else if (value instanceof String)
164 {
165 try
166 {
167 String string = (String) value;
168 if (string.startsWith("0x"))
169 {
170 return new Integer((int) Long.parseLong(string.substring(2), 16));
171 }
172 else
173 {
174 return new Integer(string);
175 }
176 }
177 catch (NumberFormatException e)
178 {
179 throw new ConversionException("The value " + value + " can't be converted to an Integer object", e);
180 }
181 }
182 else
183 {
184 throw new ConversionException("The value " + value + " can't be converted to an Integer object");
185 }
186 }
187
188 /***
189 * Convert the specified object into a Long.
190 *
191 * @param value the value to convert
192 * @throws ConversionException thrown if the value cannot be converted to a Long
193 */
194 public static Long toLong(Object value) throws ConversionException
195 {
196 if (value instanceof Long)
197 {
198 return (Long) value;
199 }
200 else if (value instanceof String)
201 {
202 try
203 {
204 String string = (String) value;
205 if (string.startsWith("0x"))
206 {
207 return new Long(new BigInteger(string.substring(2), 16).longValue());
208 }
209 else
210 {
211 return new Long(string);
212 }
213 }
214 catch (NumberFormatException e)
215 {
216 throw new ConversionException("The value " + value + " can't be converted to a Long object", e);
217 }
218 }
219 else
220 {
221 throw new ConversionException("The value " + value + " can't be converted to a Long object");
222 }
223 }
224
225 /***
226 * Convert the specified object into a Float.
227 *
228 * @param value the value to convert
229 * @throws ConversionException thrown if the value cannot be converted to a Float
230 */
231 public static Float toFloat(Object value) throws ConversionException
232 {
233 if (value instanceof Float)
234 {
235 return (Float) value;
236 }
237 else if (value instanceof String)
238 {
239 try
240 {
241 return new Float((String) value);
242 }
243 catch (NumberFormatException e)
244 {
245 throw new ConversionException("The value " + value + " can't be converted to a Float object", e);
246 }
247 }
248 else
249 {
250 throw new ConversionException("The value " + value + " can't be converted to a Float object");
251 }
252 }
253
254 /***
255 * Convert the specified object into a Double.
256 *
257 * @param value the value to convert
258 * @throws ConversionException thrown if the value cannot be converted to a Double
259 */
260 public static Double toDouble(Object value) throws ConversionException
261 {
262 if (value instanceof Double)
263 {
264 return (Double) value;
265 }
266 else if (value instanceof String)
267 {
268 try
269 {
270 return new Double((String) value);
271 }
272 catch (NumberFormatException e)
273 {
274 throw new ConversionException("The value " + value + " can't be converted to a Double object", e);
275 }
276 }
277 else
278 {
279 throw new ConversionException("The value " + value + " can't be converted to a Double object");
280 }
281 }
282
283 /***
284 * Convert the specified object into a BigInteger.
285 *
286 * @param value the value to convert
287 * @throws ConversionException thrown if the value cannot be converted to a BigInteger
288 */
289 public static BigInteger toBigInteger(Object value) throws ConversionException
290 {
291 if (value instanceof BigInteger)
292 {
293 return (BigInteger) value;
294 }
295 else if (value instanceof String)
296 {
297 try
298 {
299 String string = (String) value;
300 if (string.startsWith("0x"))
301 {
302 return new BigInteger(string.substring(2), 16);
303 }
304 else
305 {
306 return new BigInteger(string);
307 }
308 }
309 catch (NumberFormatException e)
310 {
311 throw new ConversionException("The value " + value + " can't be converted to a BigInteger object", e);
312 }
313 }
314 else
315 {
316 throw new ConversionException("The value " + value + " can't be converted to a BigInteger object");
317 }
318 }
319
320 /***
321 * Convert the specified object into a BigDecimal.
322 *
323 * @param value the value to convert
324 * @throws ConversionException thrown if the value cannot be converted to a BigDecimal
325 */
326 public static BigDecimal toBigDecimal(Object value) throws ConversionException
327 {
328 if (value instanceof BigDecimal)
329 {
330 return (BigDecimal) value;
331 }
332 else if (value instanceof String)
333 {
334 try
335 {
336 return new BigDecimal((String) value);
337 }
338 catch (NumberFormatException e)
339 {
340 throw new ConversionException("The value " + value + " can't be converted to a BigDecimal object", e);
341 }
342 }
343 else
344 {
345 throw new ConversionException("The value " + value + " can't be converted to a BigDecimal object");
346 }
347 }
348
349 /***
350 * Convert the specified object into an URL.
351 *
352 * @param value the value to convert
353 * @throws ConversionException thrown if the value cannot be converted to an URL
354 */
355 public static URL toURL(Object value) throws ConversionException
356 {
357 if (value instanceof URL)
358 {
359 return (URL) value;
360 }
361 else if (value instanceof String)
362 {
363 try
364 {
365 return new URL((String) value);
366 }
367 catch (MalformedURLException e)
368 {
369 throw new ConversionException("The value " + value + " can't be converted to an URL", e);
370 }
371 }
372 else
373 {
374 throw new ConversionException("The value " + value + " can't be converted to an URL");
375 }
376 }
377
378 /***
379 * Convert the specified object into a Locale.
380 *
381 * @param value the value to convert
382 * @throws ConversionException thrown if the value cannot be converted to a Locale
383 */
384 public static Locale toLocale(Object value) throws ConversionException
385 {
386 if (value instanceof Locale)
387 {
388 return (Locale) value;
389 }
390 else if (value instanceof String)
391 {
392 List elements = split((String) value, '_');
393 int size = elements.size();
394
395 if (size >= 1 && (((String) elements.get(0)).length() == 2 || ((String) elements.get(0)).length() == 0))
396 {
397 String language = (String) elements.get(0);
398 String country = (String) ((size >= 2) ? elements.get(1) : "");
399 String variant = (String) ((size >= 3) ? elements.get(2) : "");
400
401 return new Locale(language, country, variant);
402 }
403 else
404 {
405 throw new ConversionException("The value " + value + " can't be converted to a Locale");
406 }
407 }
408 else
409 {
410 throw new ConversionException("The value " + value + " can't be converted to a Locale");
411 }
412 }
413
414 /***
415 * Split a string on the specified delimiter. To be removed when
416 * commons-lang has a better replacement available (Tokenizer?).
417 *
418 * todo: replace with a commons-lang equivalent
419 *
420 * @param s the string to split
421 * @param delimiter the delimiter
422 */
423 public static List split(String s, char delimiter)
424 {
425 if (s == null)
426 {
427 return new ArrayList();
428 }
429
430 List list = new ArrayList();
431
432 StringBuffer token = new StringBuffer();
433 int begin = 0;
434 int end = 0;
435 while (begin <= s.length())
436 {
437
438 int index = s.indexOf(delimiter, end);
439
440
441 end = (index != -1) ? index : s.length();
442
443
444 String chunk = s.substring(begin , end);
445
446 if (chunk.endsWith("//") && end != s.length())
447 {
448 token.append(chunk.substring(0, chunk.length() - 1));
449 token.append(delimiter);
450 }
451 else
452 {
453
454 token.append(chunk);
455
456
457 list.add(token.toString().trim());
458
459
460 token = new StringBuffer();
461 }
462
463
464 end = end + 1;
465 begin = end;
466 }
467
468 return list;
469 }
470
471 /***
472 * Convert the specified object into a Color. If the value is a String,
473 * the format allowed is (#)?[0-9A-F]{6}([0-9A-F]{2})?. Examples:
474 * <ul>
475 * <li>FF0000 (red)</li>
476 * <li>0000FFA0 (semi transparent blue)</li>
477 * <li>#CCCCCC (gray)</li>
478 * <li>#00FF00A0 (semi transparent green)</li>
479 * </ul>
480 *
481 * @param value the value to convert
482 * @throws ConversionException thrown if the value cannot be converted to a Color
483 */
484 public static Color toColor(Object value) throws ConversionException
485 {
486 if (value instanceof Color)
487 {
488 return (Color) value;
489 }
490 else if (value instanceof String && !StringUtils.isBlank((String) value) && ((String) value).length() >= 6)
491 {
492 try
493 {
494 String color = ((String) value).trim();
495
496
497 if (color.startsWith("#"))
498 {
499 color = color.substring(1);
500 }
501
502 int red = Integer.parseInt(color.substring(0, 2), 16);
503 int green = Integer.parseInt(color.substring(2, 4), 16);
504 int blue = Integer.parseInt(color.substring(4, 6), 16);
505 int alpha = 255;
506
507
508 if (color.length() >= 8)
509 {
510 alpha = Integer.parseInt(color.substring(6, 8), 16);
511 }
512
513 return new Color(red, green, blue, alpha);
514 }
515 catch (Exception e)
516 {
517 throw new ConversionException("The value " + value + " can't be converted to a Color", e);
518 }
519 }
520 else
521 {
522 throw new ConversionException("The value " + value + " can't be converted to a Color");
523 }
524 }
525
526 /***
527 * Convert the specified object into a Calendar.
528 *
529 * @param value the value to convert
530 * @param format the DateFormat pattern to parse String values
531 * @throws ConversionException thrown if the value cannot be converted to a Calendar
532 */
533 public static Date toDate(Object value, String format) throws ConversionException
534 {
535 if (value instanceof Date)
536 {
537 return (Date) value;
538 }
539 else if (value instanceof Calendar)
540 {
541 return ((Calendar) value).getTime();
542 }
543 else if (value instanceof String)
544 {
545 try
546 {
547 return new SimpleDateFormat(format).parse((String) value);
548 }
549 catch (ParseException e)
550 {
551 throw new ConversionException("The value " + value + " can't be converted to a Date", e);
552 }
553 }
554 else
555 {
556 throw new ConversionException("The value " + value + " can't be converted to a Date");
557 }
558 }
559
560 /***
561 * Convert the specified object into a Calendar.
562 *
563 * @param value the value to convert
564 * @param format the DateFormat pattern to parse String values
565 * @throws ConversionException thrown if the value cannot be converted to a Calendar
566 */
567 public static Calendar toCalendar(Object value, String format) throws ConversionException
568 {
569 if (value instanceof Calendar)
570 {
571 return (Calendar) value;
572 }
573 else if (value instanceof Date)
574 {
575 Calendar calendar = Calendar.getInstance();
576 calendar.setTime((Date) value);
577 return calendar;
578 }
579 else if (value instanceof String)
580 {
581 try
582 {
583 Calendar calendar = Calendar.getInstance();
584 calendar.setTime(new SimpleDateFormat(format).parse((String) value));
585 return calendar;
586 }
587 catch (ParseException e)
588 {
589 throw new ConversionException("The value " + value + " can't be converted to a Calendar", e);
590 }
591 }
592 else
593 {
594 throw new ConversionException("The value " + value + " can't be converted to a Calendar");
595 }
596 }
597
598 /***
599 * Return an iterator over the simple values of a composite value. The value
600 * specified is handled depending on its type:
601 * <ul>
602 * <li>Strings are checked for delimiter characters and splitted if necessary.</li>
603 * <li>For collections the single elements are checked.</li>
604 * <li>Arrays are treated like collections.</li>
605 * <li>All other types are directly inserted.</li>
606 * <li>Recursive combinations are supported, e.g. a collection containing array that contain strings.</li>
607 * </ul>
608 *
609 * @param value the value to "split"
610 * @param delimiter the delimiter for String values
611 */
612 public static Iterator toIterator(Object value, char delimiter)
613 {
614 if (value == null)
615 {
616 return IteratorUtils.emptyIterator();
617 }
618 if (value instanceof String)
619 {
620 String s = (String) value;
621 if (s.indexOf(delimiter) > 0)
622 {
623 return split((String) value, delimiter).iterator();
624 }
625 else
626 {
627 return new SingletonIterator(value);
628 }
629 }
630 else if (value instanceof Collection)
631 {
632 return toIterator(((Collection) value).iterator(), delimiter);
633 }
634 else if (value.getClass().isArray())
635 {
636 return toIterator(IteratorUtils.arrayIterator(value), delimiter);
637 }
638 else if (value instanceof Iterator)
639 {
640 Iterator iterator = (Iterator) value;
641 IteratorChain chain = new IteratorChain();
642 while (iterator.hasNext())
643 {
644 chain.addIterator(toIterator(iterator.next(), delimiter));
645 }
646 return chain;
647 }
648 else
649 {
650 return new SingletonIterator(value);
651 }
652 }
653
654 }