View Javadoc
1   /*
2    * $Source$
3    * $Revision$
4    *
5    * Copyright (C) 2001 William Chesters
6    *
7    * Part of Melati (http://melati.org), a framework for the rapid
8    * development of clean, maintainable web applications.
9    *
10   * Melati is free software; Permission is granted to copy, distribute
11   * and/or modify this software under the terms either:
12   *
13   * a) the GNU General Public License as published by the Free Software
14   *    Foundation; either version 2 of the License, or (at your option)
15   *    any later version,
16   *
17   *    or
18   *
19   * b) any version of the Melati Software License, as published
20   *    at http://melati.org
21   *
22   * You should have received a copy of the GNU General Public License and
23   * the Melati Software License along with this program;
24   * if not, write to the Free Software Foundation, Inc.,
25   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the
26   * GNU General Public License and visit http://melati.org to obtain the
27   * Melati Software License.
28   *
29   * Feel free to contact the Developers of Melati (http://melati.org),
30   * if you would like to work out a different arrangement than the options
31   * outlined here.  It is our intention to allow Melati to be used by as
32   * wide an audience as possible.
33   *
34   * This program is distributed in the hope that it will be useful,
35   * but WITHOUT ANY WARRANTY; without even the implied warranty of
36   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37   * GNU General Public License for more details.
38   *
39   * Contact details for copyright holder:
40   *
41   *     William Chesters <williamc At paneris.org>
42   */
43  package org.melati.util;
44  
45  import java.util.Enumeration;
46  import java.util.NoSuchElementException;
47  
48  /**
49   * A utility for tokenising a string made up of comma-separated
50   * variables.  Unlike Tim's effort, it handles quoted variables as
51   * well.
52   *
53   * <PRE>
54   *   foo, bar om,,"baz, ,oof",xyz,   -&lt;
55   *     "foo", " bar om", "", "baz, , oof", "xyz", ""
56   * </PRE>
57   *
58   * @author      williamc AT paneris.org
59   */
60  
61  public class CSVStringEnumeration implements Enumeration<String> {
62  
63    private String line = "";
64    private boolean emptyLastField = false;
65    int p = 0;
66  
67    /**
68     * Look at a new string.
69     */
70    public void reset(String lineP) {
71      this.line = lineP;
72      p = 0;
73    }
74  
75    /**
76     * Are there any more tokens to come?
77     * {@inheritDoc}
78     * @see java.util.Enumeration#hasMoreElements()
79     */
80    public boolean hasMoreElements() {
81      return emptyLastField || p < line.length();
82    }
83  
84    /**
85     * Return the next token as an <TT>Object</TT>.
86     * {@inheritDoc}
87     * @see java.util.Enumeration#nextElement()
88     */
89    public final String nextElement() {
90      return nextToken();
91    }
92  
93    /**
94     * @return the next token as a <TT>String</TT>.
95     */
96    public String nextToken() {
97  
98      if (emptyLastField) {
99        emptyLastField = false;
100       return "";
101     }
102 
103     if (p >= line.length()) throw new NoSuchElementException();
104 
105     if (line.charAt(p) == '"') {
106       ++p;
107       // we need to allow for quotes inside quoted fields, so now test for ",
108       int q = line.indexOf("\",", p);
109       // if it is not there, we are (hopefully) at the end of a line
110       if (q == -1 && (line.indexOf('"', p) == line.length()-1)) 
111         q = line.length()-1;
112         
113       if (q == -1) {
114          p = line.length();
115          throw new IllegalArgumentException("Unclosed quotes");
116       }
117 
118       String it = line.substring(p, q);
119 
120       ++q;
121       p = q+1;
122       if (q < line.length()) {
123         if (line.charAt(q) != ',') {
124           p = line.length();
125           throw new IllegalArgumentException("No comma after quotes");
126         }
127         else if (q == line.length() - 1)
128           emptyLastField = true;
129       }
130       return it;
131     } else {
132       int q = line.indexOf(',', p);
133       if (q == -1) {
134         String it = line.substring(p);
135         p = line.length();
136         return it;
137       } else {
138           String it = line.substring(p, q);
139           if (q == line.length() - 1)
140             emptyLastField = true;
141           p = q + 1;
142           return it;
143       }
144     }
145   }
146 
147 }