View Javadoc

1   /*
2    * Copyright 2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License")
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
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             // find the next delimiter
438             int index = s.indexOf(delimiter, end);
439 
440             // move the end index at the end of the string if the delimiter is not found
441             end = (index != -1) ? index : s.length();
442 
443             // extract the chunk
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                 // append the chunk to the token
454                 token.append(chunk);
455 
456                 // add the token to the list
457                 list.add(token.toString().trim());
458 
459                 // reset the token
460                 token = new StringBuffer();
461             }
462 
463             // move to the next chunk
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                 // remove the leading #
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                 // parse the transparency
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 }