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. package org.apache.commons.beanutils.converters;
  17. import java.io.IOException;
  18. import java.io.StreamTokenizer;
  19. import java.io.StringReader;
  20. import java.util.ArrayList;
  21. import java.util.List;
  22. import org.apache.commons.beanutils.ConversionException;
  23. import org.apache.commons.beanutils.Converter;
  24. /**
  25. * <p>Convenience base class for converters that translate the String
  26. * representation of an array into a corresponding array of primitives
  27. * object. This class encapsulates the functionality required to parse
  28. * the String into a list of String elements that can later be
  29. * individually converted to the appropriate primitive type.</p>
  30. *
  31. * <p>The input syntax accepted by the <code>parseElements()</code> method
  32. * is designed to be compatible with the syntax used to initialize arrays
  33. * in a Java source program, except that only String literal values are
  34. * supported. For maximum flexibility, the surrounding '{' and '}'
  35. * characters are optional, and individual elements may be separated by
  36. * any combination of whitespace and comma characters.</p>
  37. *
  38. * @author Craig R. McClanahan
  39. * @version $Revision: 1.6 $ $Date: 2004/02/28 13:18:34 $
  40. * @since 1.4
  41. */
  42. public abstract class AbstractArrayConverter implements Converter {
  43. // ----------------------------------------------------- Instance Variables
  44. /**
  45. * The default value specified to our Constructor, if any.
  46. */
  47. protected Object defaultValue = null;
  48. /**
  49. * <p>Model object for string arrays.</p>
  50. */
  51. protected static String strings[] = new String[0];
  52. /**
  53. * Should we return the default value on conversion errors?
  54. */
  55. protected boolean useDefault = true;
  56. // --------------------------------------------------------- Public Methods
  57. /**
  58. * Convert the specified input object into an output object of the
  59. * specified type. This method must be implemented by a concrete
  60. * subclass.
  61. *
  62. * @param type Data type to which this value should be converted
  63. * @param value The input value to be converted
  64. *
  65. * @exception ConversionException if conversion cannot be performed
  66. * successfully
  67. */
  68. public abstract Object convert(Class type, Object value);
  69. // ------------------------------------------------------ Protected Methods
  70. /**
  71. * <p>Parse an incoming String of the form similar to an array initializer
  72. * in the Java language into a <code>List</code> individual Strings
  73. * for each element, according to the following rules.</p>
  74. * <ul>
  75. * <li>The string must have matching '{' and '}' delimiters around
  76. * a comma-delimited list of values.</li>
  77. * <li>Whitespace before and after each element is stripped.
  78. * <li>If an element is itself delimited by matching single or double
  79. * quotes, the usual rules for interpreting a quoted String apply.</li>
  80. * </ul>
  81. *
  82. * @param svalue String value to be parsed
  83. *
  84. * @exception ConversionException if the syntax of <code>svalue</code>
  85. * is not syntactically valid
  86. * @exception NullPointerException if <code>svalue</code>
  87. * is <code>null</code>
  88. */
  89. protected List parseElements(String svalue) {
  90. // Validate the passed argument
  91. if (svalue == null) {
  92. throw new NullPointerException();
  93. }
  94. // Trim any matching '{' and '}' delimiters
  95. svalue = svalue.trim();
  96. if (svalue.startsWith("{") && svalue.endsWith("}")) {
  97. svalue = svalue.substring(1, svalue.length() - 1);
  98. }
  99. try {
  100. // Set up a StreamTokenizer on the characters in this String
  101. StreamTokenizer st =
  102. new StreamTokenizer(new StringReader(svalue));
  103. st.whitespaceChars(',',','); // Commas are delimiters
  104. st.ordinaryChars('0', '9'); // Needed to turn off numeric flag
  105. st.ordinaryChars('.', '.');
  106. st.ordinaryChars('-', '-');
  107. st.wordChars('0', '9'); // Needed to make part of tokens
  108. st.wordChars('.', '.');
  109. st.wordChars('-', '-');
  110. // Split comma-delimited tokens into a List
  111. ArrayList list = new ArrayList();
  112. while (true) {
  113. int ttype = st.nextToken();
  114. if ((ttype == StreamTokenizer.TT_WORD) ||
  115. (ttype > 0)) {
  116. list.add(st.sval);
  117. } else if (ttype == StreamTokenizer.TT_EOF) {
  118. break;
  119. } else {
  120. throw new ConversionException
  121. ("Encountered token of type " + ttype);
  122. }
  123. }
  124. // Return the completed list
  125. return (list);
  126. } catch (IOException e) {
  127. throw new ConversionException(e);
  128. }
  129. }
  130. }