1
2 package org.paneris.util;
3
4
5 /**
6 * This is a complete butchery of java.util.StringTokenizer,
7 * it needs sorting out, but appears to process lines in a .csv file correctly.
8 */
9
10 public class CSVStringTokenizer implements java.util.Enumeration {
11 private int currentPosition;
12 private int maxPosition;
13 private String str;
14 private String delimiters;
15 private boolean retTokens;
16
17
18 /**
19 * Constructs a string tokenizer for the specified string. The
20 * characters in the <code>delim</code> argument are the delimiters
21 * for separating tokens.
22 * <p>
23 * If the <code>returnTokens</code> flag is <code>true</code>, then
24 * the delimiter characters are also returned as tokens. Each
25 * delimiter is returned as a string of length one. If the flag is
26 * <code>false</code>, the delimiter characters are skipped and only
27 * serve as separators between tokens.
28 *
29 * @param str a string to be parsed.
30 * @param delim the delimiters.
31 * @param returnTokens flag indicating whether to return the delimiters
32 * as tokens.
33 * @since JDK1.0
34 */
35 public CSVStringTokenizer(String str, String delim, boolean returnTokens) {
36 currentPosition = 0;
37 this.str = str;
38 maxPosition = str.length();
39 delimiters = delim;
40 retTokens = returnTokens;
41 }
42
43 /**
44 * Constructs a string tokenizer for the specified string. The
45 * characters in the <code>delim</code> argument are the delimiters
46 * for separating tokens.
47 *
48 * @param str a string to be parsed.
49 * @param delim the delimiters.
50 * @since JDK1.0
51 */
52 public CSVStringTokenizer(String str, String delim) {
53 this(str, delim, false);
54 }
55
56 /**
57 * Constructs a string tokenizer for the specified string. The
58 * tokenizer uses the default delimiter set, which is
59 * <code>"\t\n\r"</code>: the space character, the tab
60 * character, the newline character, and the carriage-return character.
61 *
62 * @param str a string to be parsed.
63 * @since JDK1.0
64 */
65 public CSVStringTokenizer(String str) {
66 this(str, " \t\n\r", false);
67 }
68
69 /**
70 * Skips delimiters.
71 */
72 /*
73 private void skipDelimiters() {
74 while (!retTokens &&
75 (currentPosition < maxPosition) &&
76 (delimiters.indexOf(str.charAt(currentPosition)) >= 0)) {
77 currentPosition++;
78 }
79 }
80 */
81 /**
82 * Skips delimiter.
83 */
84 /*
85 private void skipDelimiter() {
86 if (!retTokens &&
87 (currentPosition < maxPosition) &&
88 (delimiters.indexOf(str.charAt(currentPosition)) >= 0)) {
89 currentPosition++;
90 }
91 }
92 */
93 /**
94 * Tests if there are more tokens available from this tokenizer's string.
95 *
96 * @return <code>true</code> if there are more tokens available from this
97 * tokenizer's string; <code>false</code> otherwise.
98 * @since JDK1.0
99 */
100 public boolean hasMoreTokens() {
101 // skipDelimiters();
102 return (currentPosition < maxPosition);
103 }
104
105 /**
106 * Returns the next token from this string tokenizer.
107 *
108 * @return the next token from this string tokenizer.
109 * @exception NoSuchElementException if there are no more tokens in this
110 * tokenizer's string.
111 * @since JDK1.0
112 */
113 public String nextToken() {
114 // always move forward (as long as we have already started
115 if ((currentPosition > 0) || (maxPosition == 0)){
116 currentPosition++;
117 }
118 if (currentPosition >= maxPosition) {
119 return "";
120 }
121
122 int start = currentPosition;
123 while ((currentPosition < maxPosition) &&
124 (delimiters.indexOf(str.charAt(currentPosition)) < 0)) {
125 currentPosition++;
126 }
127 return str.substring(start, currentPosition);
128 }
129
130 /**
131 * Returns the next token in this string tokenizer's string. The new
132 * delimiter set remains the default after this call.
133 *
134 * @param delim the new delimiters.
135 * @return the next token, after switching to the new delimiter set.
136 * @exception NoSuchElementException if there are no more tokens in this
137 * tokenizer's string.
138 * @since JDK1.0
139 */
140 public String nextToken(String delim) {
141 delimiters = delim;
142 return nextToken();
143 }
144
145 /**
146 * Returns the same value as the <code>hasMoreTokens</code>
147 * method. It exists so that this class can implement the
148 * <code>Enumeration</code> interface.
149 *
150 * @return <code>true</code> if there are more tokens;
151 * <code>false</code> otherwise.
152 * @see java.util.Enumeration
153 * @see java.util.StringTokenizer#hasMoreTokens()
154 * @since JDK1.0
155 */
156 public boolean hasMoreElements() {
157 return hasMoreTokens();
158 }
159
160 /**
161 * Returns the same value as the <code>nextToken</code> method,
162 * except that its declared return value is <code>Object</code> rather than
163 * <code>String</code>. It exists so that this class can implement the
164 * <code>Enumeration</code> interface.
165 *
166 * @return the next token in the string.
167 * @exception NoSuchElementException if there are no more tokens in this
168 * tokenizer's string.
169 * @see java.util.Enumeration
170 * @see java.util.StringTokenizer#nextToken()
171 * @since JDK1.0
172 */
173 public Object nextElement() {
174 return nextToken();
175 }
176
177 /**
178 * Calculates the number of times that this tokenizer's
179 * <code>nextToken</code> method can be called before it generates an
180 * exception.
181 *
182 * @return the number of tokens remaining in the string using the current
183 * delimiter set.
184 * @see java.util.StringTokenizer#nextToken()
185 * @since JDK1.0
186 */
187 public int countTokens() {
188 int count = 0;
189 int currpos = currentPosition;
190
191 while (currpos < maxPosition) {
192 /*
193 * This is just skipDelimiters(); but it does not affect
194 * currentPosition.
195 */
196 while (!retTokens &&
197 (currpos < maxPosition) &&
198 (delimiters.indexOf(str.charAt(currpos)) >= 0)) {
199 currpos++;
200 }
201
202 if (currpos >= maxPosition) {
203 break;
204 }
205
206 int start = currpos;
207 while ((currpos < maxPosition) &&
208 (delimiters.indexOf(str.charAt(currpos)) < 0)) {
209 currpos++;
210 }
211 if (retTokens && (start == currpos) &&
212 (delimiters.indexOf(str.charAt(currpos)) >= 0)) {
213 currpos++;
214 }
215 count++;
216
217 }
218 return count;
219 }
220 }
221