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 package java.util;
19 
20 /**
21  * Breaks a string into tokens; new code should probably use {@link String#split}.
22  *
23  * <blockquote>
24  * <pre>
25  * // Legacy code:
26  * StringTokenizer st = new StringTokenizer("a:b:c", ":");
27  * while (st.hasMoreTokens()) {
28  *     System.err.println(st.nextToken());
29  * }
30  *
31  * // New code:
32  * for (String token : "a:b:c".split(":")) {
33  *     System.err.println(token);
34  * }
35  * </pre>
36  * </blockquote>
37  *
38  * @since 1.0
39  */
40 public class StringTokenizer implements Enumeration<Object> {
41 
42     private String string;
43 
44     private String delimiters;
45 
46     private boolean returnDelimiters;
47 
48     private int position;
49 
50     /**
51      * Constructs a new {@code StringTokenizer} for the parameter string using
52      * whitespace as the delimiter. The {@code returnDelimiters} flag is set to
53      * {@code false}.
54      *
55      * @param string
56      *            the string to be tokenized.
57      */
StringTokenizer(String string)58     public StringTokenizer(String string) {
59         this(string, " \t\n\r\f", false);
60     }
61 
62     /**
63      * Constructs a new {@code StringTokenizer} for the parameter string using
64      * the specified delimiters. The {@code returnDelimiters} flag is set to
65      * {@code false}. If {@code delimiters} is {@code null}, this constructor
66      * doesn't throw an {@code Exception}, but later calls to some methods might
67      * throw a {@code NullPointerException}.
68      *
69      * @param string
70      *            the string to be tokenized.
71      * @param delimiters
72      *            the delimiters to use.
73      */
StringTokenizer(String string, String delimiters)74     public StringTokenizer(String string, String delimiters) {
75         this(string, delimiters, false);
76     }
77 
78     /**
79      * Constructs a new {@code StringTokenizer} for the parameter string using
80      * the specified delimiters, returning the delimiters as tokens if the
81      * parameter {@code returnDelimiters} is {@code true}. If {@code delimiters}
82      * is null this constructor doesn't throw an {@code Exception}, but later
83      * calls to some methods might throw a {@code NullPointerException}.
84      *
85      * @param string
86      *            the string to be tokenized.
87      * @param delimiters
88      *            the delimiters to use.
89      * @param returnDelimiters
90      *            {@code true} to return each delimiter as a token.
91      */
StringTokenizer(String string, String delimiters, boolean returnDelimiters)92     public StringTokenizer(String string, String delimiters,
93             boolean returnDelimiters) {
94         if (string == null) {
95             throw new NullPointerException("string == null");
96         }
97         this.string = string;
98         this.delimiters = delimiters;
99         this.returnDelimiters = returnDelimiters;
100         this.position = 0;
101     }
102 
103     /**
104      * Returns the number of unprocessed tokens remaining in the string.
105      *
106      * @return number of tokens that can be retreived before an {@code
107      *         Exception} will result from a call to {@code nextToken()}.
108      */
countTokens()109     public int countTokens() {
110         int count = 0;
111         boolean inToken = false;
112         for (int i = position, length = string.length(); i < length; i++) {
113             if (delimiters.indexOf(string.charAt(i), 0) >= 0) {
114                 if (returnDelimiters)
115                     count++;
116                 if (inToken) {
117                     count++;
118                     inToken = false;
119                 }
120             } else {
121                 inToken = true;
122             }
123         }
124         if (inToken)
125             count++;
126         return count;
127     }
128 
129     /**
130      * Returns {@code true} if unprocessed tokens remain. This method is
131      * implemented in order to satisfy the {@code Enumeration} interface.
132      *
133      * @return {@code true} if unprocessed tokens remain.
134      */
hasMoreElements()135     public boolean hasMoreElements() {
136         return hasMoreTokens();
137     }
138 
139     /**
140      * Returns {@code true} if unprocessed tokens remain.
141      *
142      * @return {@code true} if unprocessed tokens remain.
143      */
hasMoreTokens()144     public boolean hasMoreTokens() {
145         if (delimiters == null) {
146             throw new NullPointerException("delimiters == null");
147         }
148         int length = string.length();
149         if (position < length) {
150             if (returnDelimiters)
151                 return true; // there is at least one character and even if
152             // it is a delimiter it is a token
153 
154             // otherwise find a character which is not a delimiter
155             for (int i = position; i < length; i++)
156                 if (delimiters.indexOf(string.charAt(i), 0) == -1)
157                     return true;
158         }
159         return false;
160     }
161 
162     /**
163      * Returns the next token in the string as an {@code Object}. This method is
164      * implemented in order to satisfy the {@code Enumeration} interface.
165      *
166      * @return next token in the string as an {@code Object}
167      * @throws NoSuchElementException
168      *                if no tokens remain.
169      */
nextElement()170     public Object nextElement() {
171         return nextToken();
172     }
173 
174     /**
175      * Returns the next token in the string as a {@code String}.
176      *
177      * @return next token in the string as a {@code String}.
178      * @throws NoSuchElementException
179      *                if no tokens remain.
180      */
nextToken()181     public String nextToken() {
182         if (delimiters == null) {
183             throw new NullPointerException("delimiters == null");
184         }
185         int i = position;
186         int length = string.length();
187 
188         if (i < length) {
189             if (returnDelimiters) {
190                 if (delimiters.indexOf(string.charAt(position), 0) >= 0)
191                     return String.valueOf(string.charAt(position++));
192                 for (position++; position < length; position++)
193                     if (delimiters.indexOf(string.charAt(position), 0) >= 0)
194                         return string.substring(i, position);
195                 return string.substring(i);
196             }
197 
198             while (i < length && delimiters.indexOf(string.charAt(i), 0) >= 0)
199                 i++;
200             position = i;
201             if (i < length) {
202                 for (position++; position < length; position++)
203                     if (delimiters.indexOf(string.charAt(position), 0) >= 0)
204                         return string.substring(i, position);
205                 return string.substring(i);
206             }
207         }
208         throw new NoSuchElementException();
209     }
210 
211     /**
212      * Returns the next token in the string as a {@code String}. The delimiters
213      * used are changed to the specified delimiters.
214      *
215      * @param delims
216      *            the new delimiters to use.
217      * @return next token in the string as a {@code String}.
218      * @throws NoSuchElementException
219      *                if no tokens remain.
220      */
nextToken(String delims)221     public String nextToken(String delims) {
222         this.delimiters = delims;
223         return nextToken();
224     }
225 }
226