001    /*
002     *  Copyright 2003-2004 The Apache Software Foundation
003     *
004     *  Licensed under the Apache License, Version 2.0 (the "License");
005     *  you may not use this file except in compliance with the License.
006     *  You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     *  Unless required by applicable law or agreed to in writing, software
011     *  distributed under the License is distributed on an "AS IS" BASIS,
012     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     *  See the License for the specific language governing permissions and
014     *  limitations under the License.
015     */
016    package org.apache.commons.convert1.array;
017    
018    
019    import java.util.ArrayList;
020    import java.util.List;
021    import java.io.IOException;
022    import java.io.StreamTokenizer;
023    import java.io.StringReader;
024    
025    import org.apache.commons.convert1.ConversionException;
026    
027    /**
028     * Temporary file containing the String to String[] 
029     * parsing. 
030     */
031    public class StringArrayParser {
032    
033        // TODO: This needs to be extracted out so that the 
034        //       parsing part is not tied to an incoming String. 
035        /**
036         * <p>Parse an incoming String of the form similar to an array initializer
037         * in the Java language into a <code>List</code> individual Strings
038         * for each element, according to the following rules.</p>
039         * <ul>
040         * <li>The string must have matching '{' and '}' delimiters around
041         *     a comma-delimited list of values.</li>
042         * <li>Whitespace before and after each element is stripped.
043         * <li>If an element is itself delimited by matching single or double
044         *     quotes, the usual rules for interpreting a quoted String apply.</li>
045         * </ul>
046         *
047         * @param svalue String value to be parsed
048         *
049         * @exception ConversionException if the syntax of <code>svalue</code>
050         *  is not syntactically valid
051         * @exception NullPointerException if <code>svalue</code>
052         *  is <code>null</code>
053         */
054        static List parseElements(String svalue) {
055    
056            // Validate the passed argument
057            if (svalue == null) {
058                throw new NullPointerException();
059            }
060    
061            // Trim any matching '{' and '}' delimiters
062            svalue = svalue.trim();
063            if (svalue.startsWith("{") && svalue.endsWith("}")) {
064                svalue = svalue.substring(1, svalue.length() - 1);
065            }
066    
067            try {
068    
069                // Set up a StreamTokenizer on the characters in this String
070                StreamTokenizer st =
071                    new StreamTokenizer(new StringReader(svalue));
072                st.whitespaceChars(',',','); // Commas are delimiters
073                st.ordinaryChars('0', '9');  // Needed to turn off numeric flag
074                st.ordinaryChars('.', '.');
075                st.ordinaryChars('-', '-');
076                st.wordChars('0', '9');      // Needed to make part of tokens
077                st.wordChars('.', '.');
078                st.wordChars('-', '-');
079    
080                // Split comma-delimited tokens into a List
081                ArrayList list = new ArrayList();
082                while (true) {
083                    int ttype = st.nextToken();
084                    if ((ttype == StreamTokenizer.TT_WORD) ||
085                        (ttype > 0)) {
086                        list.add(st.sval);
087                    } else if (ttype == StreamTokenizer.TT_EOF) {
088                        break;
089                    } else {
090                        throw new ConversionException
091                            ("Encountered token of type " + ttype);
092                    }
093                }
094    
095                // Return the completed list
096                return (list);
097    
098            } catch (IOException e) {
099    
100                throw new ConversionException(e);
101    
102            }
103    
104    
105    
106        }
107    
108    }