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 * @version $Id$ 47 * @since 1.4 48 * @deprecated Replaced by the new {@link ArrayConverter} implementation 49 */ 50 51 @Deprecated 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 * @since 1.8.0 75 */ 76 public AbstractArrayConverter(final Object defaultValue) { 77 78 if (defaultValue == NO_DEFAULT) { 79 this.useDefault = false; 80 } else { 81 this.defaultValue = defaultValue; 82 this.useDefault = true; 83 } 84 85 } 86 87 // ------------------------------------------------------- Static Variables 88 89 /** 90 * This is a special reference that can be passed as the "default object" 91 * to the constructor to indicate that no default is desired. Note that 92 * the value 'null' cannot be used for this purpose, as the caller may 93 * want a null to be returned as the default. 94 * @since 1.8.0 95 */ 96 public static final Object NO_DEFAULT = new Object(); 97 98 // ----------------------------------------------------- Instance Variables 99 100 101 /** 102 * <p>Model object for string arrays.</p> 103 */ 104 protected static String[] strings = new String[0]; 105 106 107 /** 108 * The default value specified to our Constructor, if any. 109 */ 110 protected Object defaultValue = null; 111 112 113 /** 114 * Should we return the default value on conversion errors? 115 */ 116 protected boolean useDefault = true; 117 118 119 // --------------------------------------------------------- Public Methods 120 121 122 /** 123 * Convert the specified input object into an output object of the 124 * specified type. This method must be implemented by a concrete 125 * subclass. 126 * 127 * @param type Data type to which this value should be converted 128 * @param value The input value to be converted 129 * @return The converted value 130 * 131 * @throws ConversionException if conversion cannot be performed 132 * successfully 133 */ 134 public abstract Object convert(Class type, Object value); 135 136 137 // ------------------------------------------------------ Protected Methods 138 139 140 /** 141 * <p>Parse an incoming String of the form similar to an array initializer 142 * in the Java language into a <code>List</code> individual Strings 143 * for each element, according to the following rules.</p> 144 * <ul> 145 * <li>The string is expected to be a comma-separated list of values.</li> 146 * <li>The string may optionally have matching '{' and '}' delimiters 147 * around the list.</li> 148 * <li>Whitespace before and after each element is stripped.</li> 149 * <li>Elements in the list may be delimited by single or double quotes. 150 * Within a quoted elements, the normal Java escape sequences are valid.</li> 151 * </ul> 152 * 153 * @param svalue String value to be parsed 154 * @return The parsed list of String values 155 * 156 * @throws ConversionException if the syntax of <code>svalue</code> 157 * is not syntactically valid 158 * @throws NullPointerException if <code>svalue</code> 159 * is <code>null</code> 160 */ 161 protected List parseElements(String svalue) { 162 163 // Validate the passed argument 164 if (svalue == null) { 165 throw new NullPointerException(); 166 } 167 168 // Trim any matching '{' and '}' delimiters 169 svalue = svalue.trim(); 170 if (svalue.startsWith("{") && svalue.endsWith("}")) { 171 svalue = svalue.substring(1, svalue.length() - 1); 172 } 173 174 try { 175 176 // Set up a StreamTokenizer on the characters in this String 177 final StreamTokenizer st = 178 new StreamTokenizer(new StringReader(svalue)); 179 st.whitespaceChars(',',','); // Commas are delimiters 180 st.ordinaryChars('0', '9'); // Needed to turn off numeric flag 181 st.ordinaryChars('.', '.'); 182 st.ordinaryChars('-', '-'); 183 st.wordChars('0', '9'); // Needed to make part of tokens 184 st.wordChars('.', '.'); 185 st.wordChars('-', '-'); 186 187 // Split comma-delimited tokens into a List 188 final ArrayList list = new ArrayList(); 189 while (true) { 190 final int ttype = st.nextToken(); 191 if ((ttype == StreamTokenizer.TT_WORD) || 192 (ttype > 0)) { 193 list.add(st.sval); 194 } else if (ttype == StreamTokenizer.TT_EOF) { 195 break; 196 } else { 197 throw new ConversionException 198 ("Encountered token of type " + ttype); 199 } 200 } 201 202 // Return the completed list 203 return (list); 204 205 } catch (final IOException e) { 206 207 throw new ConversionException(e); 208 209 } 210 211 212 213 } 214 215 216 }