View Javadoc

1   /*
2    * Copyright 2001-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */ 
16  
17  
18  package org.apache.commons.beanutils.converters;
19  
20  
21  import java.io.IOException;
22  import java.io.StreamTokenizer;
23  import java.io.StringReader;
24  import java.util.ArrayList;
25  import java.util.List;
26  import org.apache.commons.beanutils.ConversionException;
27  import org.apache.commons.beanutils.Converter;
28  
29  
30  
31  /**
32   * <p>Convenience base class for converters that translate the String
33   * representation of an array into a corresponding array of primitives
34   * object.  This class encapsulates the functionality required to parse
35   * the String into a list of String elements that can later be
36   * individually converted to the appropriate primitive type.</p>
37   *
38   * <p>The input syntax accepted by the <code>parseElements()</code> method
39   * is designed to be compatible with the syntax used to initialize arrays
40   * in a Java source program, except that only String literal values are
41   * supported.  For maximum flexibility, the surrounding '{' and '}'
42   * characters are optional, and individual elements may be separated by
43   * any combination of whitespace and comma characters.</p>
44   *
45   * @author Craig R. McClanahan
46   * @version $Revision: 1.6 $ $Date: 2004/02/28 13:18:34 $
47   * @since 1.4
48   */
49  
50  public abstract class AbstractArrayConverter implements Converter {
51  
52  
53      // ----------------------------------------------------- Instance Variables
54  
55  
56      /**
57       * The default value specified to our Constructor, if any.
58       */
59      protected Object defaultValue = null;
60  
61  
62      /**
63       * <p>Model object for string arrays.</p>
64       */
65      protected static String strings[] = new String[0];
66  
67  
68      /**
69       * Should we return the default value on conversion errors?
70       */
71      protected boolean useDefault = true;
72  
73  
74      // --------------------------------------------------------- Public Methods
75  
76  
77      /**
78       * Convert the specified input object into an output object of the
79       * specified type.  This method must be implemented by a concrete
80       * subclass.
81       *
82       * @param type Data type to which this value should be converted
83       * @param value The input value to be converted
84       *
85       * @exception ConversionException if conversion cannot be performed
86       *  successfully
87       */
88      public abstract Object convert(Class type, Object value);
89  
90  
91      // ------------------------------------------------------ Protected Methods
92  
93  
94      /**
95       * <p>Parse an incoming String of the form similar to an array initializer
96       * in the Java language into a <code>List</code> individual Strings
97       * for each element, according to the following rules.</p>
98       * <ul>
99       * <li>The string must have matching '{' and '}' delimiters around
100      *     a comma-delimited list of values.</li>
101      * <li>Whitespace before and after each element is stripped.
102      * <li>If an element is itself delimited by matching single or double
103      *     quotes, the usual rules for interpreting a quoted String apply.</li>
104      * </ul>
105      *
106      * @param svalue String value to be parsed
107      *
108      * @exception ConversionException if the syntax of <code>svalue</code>
109      *  is not syntactically valid
110      * @exception NullPointerException if <code>svalue</code>
111      *  is <code>null</code>
112      */
113     protected List parseElements(String svalue) {
114 
115         // Validate the passed argument
116         if (svalue == null) {
117             throw new NullPointerException();
118         }
119 
120         // Trim any matching '{' and '}' delimiters
121         svalue = svalue.trim();
122         if (svalue.startsWith("{") && svalue.endsWith("}")) {
123             svalue = svalue.substring(1, svalue.length() - 1);
124         }
125 
126         try {
127 
128             // Set up a StreamTokenizer on the characters in this String
129             StreamTokenizer st =
130                 new StreamTokenizer(new StringReader(svalue));
131             st.whitespaceChars(',',','); // Commas are delimiters
132             st.ordinaryChars('0', '9');  // Needed to turn off numeric flag
133             st.ordinaryChars('.', '.');
134             st.ordinaryChars('-', '-');
135             st.wordChars('0', '9');      // Needed to make part of tokens
136             st.wordChars('.', '.');
137             st.wordChars('-', '-');
138 
139             // Split comma-delimited tokens into a List
140             ArrayList list = new ArrayList();
141             while (true) {
142                 int ttype = st.nextToken();
143                 if ((ttype == StreamTokenizer.TT_WORD) ||
144                     (ttype > 0)) {
145                     list.add(st.sval);
146                 } else if (ttype == StreamTokenizer.TT_EOF) {
147                     break;
148                 } else {
149                     throw new ConversionException
150                         ("Encountered token of type " + ttype);
151                 }
152             }
153 
154             // Return the completed list
155             return (list);
156 
157         } catch (IOException e) {
158 
159             throw new ConversionException(e);
160 
161         }
162 
163 
164 
165     }
166 
167 
168 }