001 /*
002 * Copyright (c) Holger Pfaff - http://pfaff.ws
003 *
004 * This software maybe used for any purpose provided the
005 * above copyright notice is retained. It is supplied as is.
006 * No warranty expressed or implied - Use at your own risk.
007 */
008
009 import java.util.Enumeration;
010 import java.util.Vector;
011
012 /**
013 * (#)StringSplitter.java
014 * @author Holger Pfaff
015 * @version
016 * Behaves much like StringTokenizer except that <code>delimiter</code>
017 * is used as whole as a delimiter instead of single delim characters,
018 * and the 'null space' between two delimiters is honored by default e.g:
019 *
020 * <code>delimiter</code> = "@-@"
021 * <code>string</code> = "one@-@@-@two@-@three@four-five@-@"
022 *
023 * StringTokenizer -> "one" "two" "three" "four" "five"
024 * StringSplitter -> "one" "" "two" "three@four-five" "" or
025 * StringSplitter -> "one" "two" "three@four-five"
026 *
027 */
028
029 public class StringSplitter implements Enumeration {
030
031 /**
032 * pointer into string
033 */
034 private int curpos = 0;
035
036 /**
037 * handle strings with zero length between to delims as separate tokens ?
038 */
039 private boolean splitNull;
040
041 /**
042 * the string to work on
043 */
044 private String string;
045
046 /**
047 * the delimiter to use
048 */
049 private String delimiter;
050
051 /**
052 * length of origin string
053 */
054 private int stringlen;
055
056 /**
057 * length of delimiter
058 */
059 private int delimiterlen;
060
061 /**
062 * Construct a new StringSplitter. <code>null</code> strings will
063 * be handled as empty ones.
064 *
065 * @param string string to split.
066 * @param delimiter string to use as delimiter.
067 *
068 */
069 public StringSplitter(String string, String delimiter) {
070 this(string, delimiter, true);
071 }
072
073 /**
074 * Construct a new StringSplitter. <code>null</code> strings will
075 * be handled as empty ones.
076 *
077 * @param string string to split.
078 * @param delimiter string to use as delimiter.
079 * @param splitNull handle strings with zero length between to delims as separate tokens?.
080 */
081 public StringSplitter(String string, String delimiter, boolean splitNull) {
082 this.string = string == null ? new String("") : string;
083 this.stringlen = this.string.length();
084 this.delimiter = delimiter == null ? new String(" ") : delimiter;
085 this.delimiterlen = this.delimiter.length();
086 this.splitNull = splitNull;
087 }
088
089 /**
090 * Tests if there are more tokens/splitter available from this string.
091 */
092 public boolean hasMoreTokens() {
093 return hasMoreTokens(curpos);
094 }
095
096 /**
097 * Tests if there are more tokens/splitter available from this string.
098 *
099 * @param pos position to start from.
100 */
101 public boolean hasMoreTokens(int pos) {
102 return getNextPosition(pos) == -1 ? false : true;
103 }
104
105 /**
106 * Return index of next position within string. return -1 for none
107 *
108 * @param pos position to start from.
109 */
110 public int getNextPosition(int pos) {
111 return getNextPosition(pos, false);
112 }
113
114 /**
115 * Return index of next position within string. return -1 for none
116 *
117 * @param pos position to start from.
118 * @param modcurpos should the curpos var be modified ?
119 */
120 private int getNextPosition(int pos, boolean modcurpos) {
121 if(stringlen == 0 || pos > stringlen) {
122 return -1;
123 } else {
124 if(delimiterlen == 0) {
125 return pos == 0 ? stringlen : -1;
126 } else {
127 int end = string.indexOf(delimiter, pos);
128 if(end == -1) end = stringlen;
129 if(end == pos && splitNull == false) {
130 if(modcurpos) curpos += delimiterlen;
131 return getNextPosition(end + delimiterlen); // skip empty token
132 } else {
133 return end;
134 }
135 }
136 }
137 }
138
139 /**
140 * Returns the next token available from this string or null
141 */
142 public String nextToken() {
143 int beg, end = getNextPosition(curpos, true);
144 if(end == -1) {
145 return null;
146 } else {
147 beg = curpos; curpos = end + delimiterlen;
148 return string.substring(beg, end);
149 }
150 }
151
152 /**
153 * Returns the remaining String of this string or null
154 */
155 public String remainingString() {
156 return getNextPosition(curpos, false) == -1 ? null : string.substring(curpos);
157 }
158
159 /**
160 * Same as hasMoreTokens(). Implements Enumeration interface.
161 */
162 public boolean hasMoreElements() {
163 return hasMoreTokens();
164 }
165
166 /**
167 * Same as nextToken(). Implements Enumeration interface.
168 */
169 public Object nextElement() {
170 return nextToken();
171 }
172
173 /**
174 * Utility method to convert this splitter to a String array.
175 * Requires Util.class
176 */
177 public String[] toArray() {
178 curpos = 0; return Util.enum2Array(this);
179 }
180
181 /**
182 * Utility method to convert this splitter to a Vector of Strings.
183 * Requires Util.class
184 */
185 public Vector toVector() {
186 curpos = 0; return Util.enum2Vector(this);
187 }
188
189 /**
190 * Utility method to convert this splitter to a new String using
191 * <code>delimiter</code> as separator.
192 * Requires Util.class
193 *
194 * @param delimiter string to use as separator.
195 */
196 public String toString(String delimiter) {
197 curpos = 0; return Util.enum2String(this, delimiter);
198 }
199 };