View Javadoc

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