Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
StringUtil |
|
| 9.0625;9.062 |
1 | /** | |
2 | * Distribution License: | |
3 | * JSword is free software; you can redistribute it and/or modify it under | |
4 | * the terms of the GNU Lesser General Public License, version 2.1 or later | |
5 | * as published by the Free Software Foundation. This program is distributed | |
6 | * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even | |
7 | * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
8 | * See the GNU Lesser General Public License for more details. | |
9 | * | |
10 | * The License is available on the internet at: | |
11 | * http://www.gnu.org/copyleft/lgpl.html | |
12 | * or by writing to: | |
13 | * Free Software Foundation, Inc. | |
14 | * 59 Temple Place - Suite 330 | |
15 | * Boston, MA 02111-1307, USA | |
16 | * | |
17 | * © CrossWire Bible Society, 2005 - 2016 | |
18 | * | |
19 | */ | |
20 | package org.crosswire.common.util; | |
21 | ||
22 | import java.io.BufferedReader; | |
23 | import java.io.IOException; | |
24 | import java.io.Reader; | |
25 | ||
26 | /** | |
27 | * A generic class of String utilities. | |
28 | * | |
29 | * @see gnu.lgpl.License The GNU Lesser General Public License for details. | |
30 | * @author Joe Walker | |
31 | */ | |
32 | public final class StringUtil { | |
33 | /** | |
34 | * Prevent instantiation | |
35 | */ | |
36 | 0 | private StringUtil() { |
37 | 0 | } |
38 | ||
39 | /** | |
40 | * The newline character | |
41 | */ | |
42 | 0 | public static final String NEWLINE = System.getProperty("line.separator", "\r\n"); |
43 | ||
44 | /** | |
45 | * Compare two strings for equality such that both can be null. | |
46 | * | |
47 | * @param string1 the first string | |
48 | * @param string2 the second string | |
49 | * @return true when both are null or both have the same string value | |
50 | */ | |
51 | public static boolean equals(String string1, String string2) { | |
52 | 0 | if (string1 == null) { |
53 | 0 | return string2 == null; |
54 | } | |
55 | 0 | return string1.equals(string2); |
56 | } | |
57 | ||
58 | /** | |
59 | * This method reads an InputStream <b>In its entirety</b>, and passes The | |
60 | * text back as a string. If you are reading from a source that can block | |
61 | * then be prepared for a long wait for this to return. | |
62 | * | |
63 | * @param in | |
64 | * The Stream to read from. | |
65 | * @return A string containing all the text from the Stream. | |
66 | * @throws IOException when an I/O error occurred | |
67 | */ | |
68 | public static String read(Reader in) throws IOException { | |
69 | 0 | StringBuilder retcode = new StringBuilder(); |
70 | // Quiet Android from complaining about using the default BufferReader buffer size. | |
71 | // The actual buffer size is undocumented. So this is a good idea any way. | |
72 | 0 | BufferedReader din = new BufferedReader(in, 8192); |
73 | ||
74 | while (true) { | |
75 | 0 | String line = din.readLine(); |
76 | ||
77 | 0 | if (line == null) { |
78 | 0 | break; |
79 | } | |
80 | ||
81 | 0 | retcode.append(line); |
82 | 0 | retcode.append(NEWLINE); |
83 | 0 | } |
84 | ||
85 | 0 | return retcode.toString(); |
86 | } | |
87 | ||
88 | /** | |
89 | * This function creates a readable title from a variable name type input. | |
90 | * For example calling: StringUtil.createTitle("one_two") = "One Two" | |
91 | * StringUtil.createTitle("oneTwo") = "One Two" | |
92 | * | |
93 | * @param variable the name of a variable | |
94 | * @return the generated title | |
95 | */ | |
96 | public static String createTitle(String variable) { | |
97 | 0 | StringBuilder retcode = new StringBuilder(); |
98 | 0 | boolean lastlower = false; |
99 | 0 | boolean lastspace = true; |
100 | ||
101 | 0 | for (int i = 0; i < variable.length(); i++) { |
102 | 0 | char c = variable.charAt(i); |
103 | ||
104 | 0 | if (lastlower && Character.isUpperCase(c) && !lastspace) { |
105 | 0 | retcode.append(' '); |
106 | } | |
107 | ||
108 | 0 | lastlower = !Character.isUpperCase(c); |
109 | ||
110 | 0 | if (lastspace) { |
111 | 0 | c = Character.toUpperCase(c); |
112 | } | |
113 | ||
114 | 0 | if (c == '_') { |
115 | 0 | c = ' '; |
116 | } | |
117 | ||
118 | 0 | if (!lastspace || c != ' ') { |
119 | 0 | retcode.append(c); |
120 | } | |
121 | ||
122 | 0 | lastspace = c == ' '; |
123 | } | |
124 | ||
125 | 0 | return retcode.toString(); |
126 | } | |
127 | ||
128 | /** | |
129 | * For example getInitials("Java DataBase Connectivity") = "JDC" and | |
130 | * getInitials("Church of England") = "CoE". | |
131 | * | |
132 | * @param sentence | |
133 | * The phrase from which to get the initial letters. | |
134 | * @return The initial letters in the given words. | |
135 | */ | |
136 | public static String getInitials(String sentence) { | |
137 | 0 | String[] words = StringUtil.split(sentence); |
138 | ||
139 | 0 | StringBuilder retcode = new StringBuilder(); |
140 | 0 | for (int i = 0; i < words.length; i++) { |
141 | 0 | String word = words[i]; |
142 | ||
143 | 0 | char first = 0; |
144 | 0 | for (int j = 0; first == 0 && j < word.length(); j++) { |
145 | 0 | char c = word.charAt(j); |
146 | 0 | if (Character.isLetter(c)) { |
147 | 0 | first = c; |
148 | } | |
149 | } | |
150 | ||
151 | 0 | if (first != 0) { |
152 | 0 | retcode.append(first); |
153 | } | |
154 | } | |
155 | ||
156 | 0 | return retcode.toString(); |
157 | } | |
158 | ||
159 | /** | |
160 | * Splits the provided text into an array, using whitespace as the | |
161 | * separator. Whitespace is defined by {@link Character#isWhitespace(char)}. | |
162 | * | |
163 | * <p> | |
164 | * The separator is not included in the returned String array. Adjacent | |
165 | * separators are treated as one separator. | |
166 | * </p> | |
167 | * | |
168 | * <pre> | |
169 | * StringUtil.split(null) = [] | |
170 | * StringUtil.split("") = [] | |
171 | * StringUtil.split("abc def") = ["abc", "def"] | |
172 | * StringUtil.split("abc def") = ["abc", "def"] | |
173 | * StringUtil.split(" abc ") = ["abc"] | |
174 | * </pre> | |
175 | * | |
176 | * @param str | |
177 | * the String to parse, may be null | |
178 | * @return an array of parsed Strings, <code>null</code> if null String | |
179 | * input | |
180 | */ | |
181 | public static String[] split(String str) { | |
182 | 0 | if (str == null) { |
183 | 0 | return EMPTY_STRING_ARRAY.clone(); |
184 | } | |
185 | ||
186 | 0 | int len = str.length(); |
187 | 0 | if (len == 0) { |
188 | 0 | return EMPTY_STRING_ARRAY.clone(); |
189 | } | |
190 | ||
191 | 0 | char[] cstr = str.toCharArray(); |
192 | ||
193 | 0 | int count = 0; |
194 | 0 | int start = 0; |
195 | 0 | int i = 0; |
196 | 0 | while ((i = indexOfWhitespace(cstr, start)) != -1) { |
197 | // Don't count separator at beginning, | |
198 | // after another or at the end | |
199 | 0 | if (i > start) { |
200 | 0 | ++count; |
201 | } | |
202 | 0 | start = i + 1; |
203 | } | |
204 | ||
205 | // If it didn't end with a separator then add in the last part | |
206 | 0 | if (start < len) { |
207 | 0 | ++count; |
208 | } | |
209 | ||
210 | // Create the array | |
211 | 0 | String[] list = new String[count]; |
212 | ||
213 | // If there were no separators | |
214 | // then we have one big part | |
215 | 0 | if (start == 0) { |
216 | 0 | list[0] = str; |
217 | 0 | return list; |
218 | } | |
219 | ||
220 | 0 | start = 0; |
221 | 0 | i = 0; |
222 | 0 | int x = 0; |
223 | 0 | while ((i = indexOfWhitespace(cstr, start)) != -1) { |
224 | // Don't count separator at beginning, | |
225 | // after another or at the end | |
226 | 0 | if (i > start) { |
227 | 0 | list[x++] = str.substring(start, i); |
228 | } | |
229 | 0 | start = i + 1; |
230 | } | |
231 | // If it didn't end with a separator then add in the last part | |
232 | 0 | if (start < len) { |
233 | 0 | list[x++] = str.substring(start); |
234 | } | |
235 | ||
236 | 0 | return list; |
237 | } | |
238 | ||
239 | /** | |
240 | * Splits the provided text into an array, using whitespace as the | |
241 | * separator. Whitespace is defined by {@link Character#isWhitespace(char)}. | |
242 | * | |
243 | * <p> | |
244 | * The separator is not included in the returned String array. Adjacent | |
245 | * separators are treated as one separator. | |
246 | * </p> | |
247 | * | |
248 | * <pre> | |
249 | * StringUtil.split(null) = [] | |
250 | * StringUtil.split("") = [] | |
251 | * StringUtil.split("abc def") = ["abc", "def"] | |
252 | * StringUtil.split("abc def") = ["abc", "def"] | |
253 | * StringUtil.split(" abc ") = ["abc"] | |
254 | * </pre> | |
255 | * | |
256 | * @param str | |
257 | * the String to parse, may be null | |
258 | * @param max the maximum number of elements to return | |
259 | * @return an array of parsed Strings, <code>null</code> if null String | |
260 | * input | |
261 | */ | |
262 | public static String[] split(String str, int max) { | |
263 | 0 | if (str == null) { |
264 | 0 | return EMPTY_STRING_ARRAY.clone(); |
265 | } | |
266 | ||
267 | 0 | int len = str.length(); |
268 | 0 | if (len == 0) { |
269 | 0 | return EMPTY_STRING_ARRAY.clone(); |
270 | } | |
271 | ||
272 | 0 | char[] cstr = str.toCharArray(); |
273 | ||
274 | 0 | int count = 0; |
275 | 0 | int start = 0; |
276 | 0 | int i = 0; |
277 | 0 | while ((i = indexOfWhitespace(cstr, start)) != -1) { |
278 | // Don't count separator at beginning, | |
279 | // after another or at the end | |
280 | 0 | if (i > start) { |
281 | 0 | ++count; |
282 | } | |
283 | 0 | start = i + 1; |
284 | } | |
285 | ||
286 | // If it didn't end with a separator then add in the last part | |
287 | 0 | if (start < len) { |
288 | 0 | ++count; |
289 | } | |
290 | ||
291 | // If there were no separators | |
292 | // then we have one big part | |
293 | 0 | if (start == 0) { |
294 | 0 | String[] list = new String[count]; |
295 | 0 | list[0] = str; |
296 | 0 | return list; |
297 | } | |
298 | ||
299 | // Limit the result | |
300 | 0 | if (max > 0 && count > max) { |
301 | 0 | count = max; |
302 | } | |
303 | ||
304 | // Create the array | |
305 | 0 | String[] list = new String[count]; |
306 | ||
307 | 0 | start = 0; |
308 | 0 | i = 0; |
309 | 0 | int x = 0; |
310 | 0 | while ((i = indexOfWhitespace(cstr, start)) != -1) { |
311 | // Don't count separator at beginning, | |
312 | // after another or at the end | |
313 | 0 | if (i > start && x < count) { |
314 | 0 | list[x++] = str.substring(start, i); |
315 | } | |
316 | 0 | start = i + 1; |
317 | } | |
318 | // If it didn't end with a separator then add in the last part | |
319 | 0 | if (start < len && x < count) { |
320 | 0 | list[x++] = str.substring(start); |
321 | } | |
322 | ||
323 | 0 | return list; |
324 | } | |
325 | ||
326 | /** | |
327 | * Splits the provided text into an array, separator specified. This is an | |
328 | * alternative to using StringTokenizer. | |
329 | * | |
330 | * <p> | |
331 | * The separator is not included in the returned String array. Adjacent | |
332 | * separators are treated as one separator. | |
333 | * </p> | |
334 | * | |
335 | * <p> | |
336 | * A <code>null</code> input String returns <code>null</code>. | |
337 | * </p> | |
338 | * | |
339 | * <pre> | |
340 | * StringUtil.split(null, *) = [] | |
341 | * StringUtil.split("", *) = [] | |
342 | * StringUtil.split("a.b.c", '.') = ["a", "b", "c"] | |
343 | * StringUtil.split("a..b.c", '.') = ["a", "b", "c"] | |
344 | * StringUtil.split("a:b:c", '.') = ["a:b:c"] | |
345 | * StringUtil.split("a b c", ' ') = ["a", "b", "c"] | |
346 | * </pre> | |
347 | * | |
348 | * @param str | |
349 | * the String to parse, may be null | |
350 | * @param separatorChar | |
351 | * the character used as the delimiter | |
352 | * @return an array of parsed Strings | |
353 | */ | |
354 | public static String[] split(String str, char separatorChar) { | |
355 | 0 | if (str == null) { |
356 | 0 | return EMPTY_STRING_ARRAY.clone(); |
357 | } | |
358 | ||
359 | 0 | int len = str.length(); |
360 | 0 | if (len == 0) { |
361 | 0 | return EMPTY_STRING_ARRAY.clone(); |
362 | } | |
363 | ||
364 | // Determine the size of the array | |
365 | 0 | int count = 0; |
366 | 0 | int start = 0; |
367 | 0 | int i = 0; |
368 | 0 | while ((i = str.indexOf(separatorChar, start)) != -1) { |
369 | // Don't count separator at beginning, | |
370 | // after another or at the end | |
371 | 0 | if (i > start && i < len) { |
372 | 0 | ++count; |
373 | } | |
374 | 0 | start = i + 1; |
375 | } | |
376 | // If it didn't end with a separator then add in the last part | |
377 | 0 | if (start < len) { |
378 | 0 | ++count; |
379 | } | |
380 | ||
381 | // Create the array | |
382 | 0 | String[] list = new String[count]; |
383 | ||
384 | // If there were no separators | |
385 | // then we have one big part | |
386 | 0 | if (count == 1) { |
387 | 0 | list[0] = str; |
388 | 0 | return list; |
389 | } | |
390 | ||
391 | 0 | start = 0; |
392 | 0 | i = 0; |
393 | 0 | int x = 0; |
394 | 0 | while ((i = str.indexOf(separatorChar, start)) != -1) { |
395 | // Don't count separator at beginning, | |
396 | // after another or at the end | |
397 | 0 | if (i > start) { |
398 | 0 | list[x++] = str.substring(start, i); |
399 | } | |
400 | 0 | start = i + 1; |
401 | } | |
402 | // If it didn't end with a separator then add in the last part | |
403 | 0 | if (start < len) { |
404 | 0 | list[x++] = str.substring(start, len); |
405 | } | |
406 | ||
407 | 0 | return list; |
408 | } | |
409 | ||
410 | /** | |
411 | * <p> | |
412 | * Splits the provided text into an array, separator specified. This is an | |
413 | * alternative to using StringTokenizer. | |
414 | * </p> | |
415 | * | |
416 | * <p> | |
417 | * The separator is not included in the returned String array. Adjacent | |
418 | * separators are treated as one separator. | |
419 | * </p> | |
420 | * | |
421 | * <p> | |
422 | * A <code>null</code> input String returns <code>null</code>. | |
423 | * </p> | |
424 | * | |
425 | * <pre> | |
426 | * StringUtil.split(null, *, 2) = [] | |
427 | * StringUtil.split("", *, 2) = [] | |
428 | * StringUtil.split("a.b.c", '.', 2) = ["a", "b"] | |
429 | * StringUtil.split("a..b.c", '.', 2) = ["a", "b"] | |
430 | * StringUtil.split("a:b:c", '.', 2) = ["a:b:c"] | |
431 | * StringUtil.split("a b c", ' ', 2) = ["a", "b"] | |
432 | * </pre> | |
433 | * | |
434 | * @param str | |
435 | * the String to parse, may be null | |
436 | * @param separatorChar | |
437 | * the character used as the delimiter | |
438 | * @param max | |
439 | * the maximum number of elements to include in the array. | |
440 | * A zero or negative value implies no limit | |
441 | * @return an array of parsed Strings | |
442 | */ | |
443 | public static String[] split(String str, char separatorChar, int max) { | |
444 | 0 | if (str == null) { |
445 | 0 | return EMPTY_STRING_ARRAY.clone(); |
446 | } | |
447 | ||
448 | 0 | int len = str.length(); |
449 | 0 | if (len == 0) { |
450 | 0 | return EMPTY_STRING_ARRAY.clone(); |
451 | } | |
452 | ||
453 | // Determine the size of the array | |
454 | 0 | int count = 0; |
455 | 0 | int start = 0; |
456 | 0 | int i = 0; |
457 | 0 | while ((i = str.indexOf(separatorChar, start)) != -1) { |
458 | // Don't count separator at beginning, | |
459 | // after another or at the end | |
460 | 0 | if (i > start) { |
461 | 0 | ++count; |
462 | } | |
463 | 0 | start = i + 1; |
464 | } | |
465 | ||
466 | // If it didn't end with a separator then add in the last part | |
467 | 0 | if (start < len) { |
468 | 0 | ++count; |
469 | } | |
470 | ||
471 | // If there were no separators | |
472 | // then we have one big part | |
473 | 0 | if (count == 1) { |
474 | 0 | String[] list = new String[count]; |
475 | 0 | list[0] = str; |
476 | 0 | return list; |
477 | } | |
478 | ||
479 | // Limit the result | |
480 | 0 | if (max > 0 && count > max) { |
481 | 0 | count = max; |
482 | } | |
483 | ||
484 | // Create the array | |
485 | 0 | String[] list = new String[count]; |
486 | ||
487 | 0 | start = 0; |
488 | 0 | i = 0; |
489 | 0 | int x = 0; |
490 | 0 | while ((i = str.indexOf(separatorChar, start)) != -1) { |
491 | // Don't count separator at beginning, | |
492 | // after another or at the end | |
493 | 0 | if (i > start && x < count) { |
494 | 0 | list[x++] = str.substring(start, i); |
495 | } | |
496 | 0 | start = i + 1; |
497 | } | |
498 | // If it didn't end with a separator then add in the last part | |
499 | 0 | if (start < len && x < count) { |
500 | 0 | list[x++] = str.substring(start); |
501 | } | |
502 | ||
503 | 0 | return list; |
504 | } | |
505 | ||
506 | /** | |
507 | * <p> | |
508 | * Splits the provided text into an array, separators specified. This is an | |
509 | * alternative to using StringTokenizer. | |
510 | * </p> | |
511 | * | |
512 | * <p> | |
513 | * The separator is not included in the returned String array. Adjacent | |
514 | * separators are treated as one separator. | |
515 | * </p> | |
516 | * | |
517 | * <p> | |
518 | * A <code>null</code> input String returns <code>null</code>. A | |
519 | * <code>null</code> separatorChars splits on whitespace. | |
520 | * </p> | |
521 | * | |
522 | * <pre> | |
523 | * StringUtil.split(null, *) = [] | |
524 | * StringUtil.split("", *) = [] | |
525 | * StringUtil.split("abc def", null) = ["abc", "def"] | |
526 | * StringUtil.split("abc def", " ") = ["abc", "def"] | |
527 | * StringUtil.split("abc def", " ") = ["abc", "def"] | |
528 | * StringUtil.split("ab:cd:ef", ":") = ["ab", "cd", "ef"] | |
529 | * </pre> | |
530 | * | |
531 | * @param str | |
532 | * the String to parse, may be null | |
533 | * @param separatorChars | |
534 | * the characters used as the delimiters, <code>null</code> | |
535 | * splits on whitespace | |
536 | * @return an array of parsed Strings, <code>null</code> if null String | |
537 | * input | |
538 | */ | |
539 | public static String[] split(String str, String separatorChars) { | |
540 | 0 | return split(str, separatorChars, -1); |
541 | } | |
542 | ||
543 | /** | |
544 | * <p> | |
545 | * Splits the provided text into an array, separators specified. This is an | |
546 | * alternative to using StringTokenizer. | |
547 | * </p> | |
548 | * | |
549 | * <p> | |
550 | * The separator is not included in the returned String array. Adjacent | |
551 | * separators are treated as one separator. | |
552 | * </p> | |
553 | * | |
554 | * <p> | |
555 | * A <code>null</code> input String returns <code>null</code>. A | |
556 | * <code>null</code> separatorChars splits on whitespace. | |
557 | * </p> | |
558 | * | |
559 | * <pre> | |
560 | * StringUtil.split(null, *, *) = [] | |
561 | * StringUtil.split("", *, *) = [] | |
562 | * StringUtil.split("ab de fg", null, 0) = ["ab", "cd", "ef"] | |
563 | * StringUtil.split("ab de fg", null, 0) = ["ab", "cd", "ef"] | |
564 | * StringUtil.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"] | |
565 | * StringUtil.split("ab:cd:ef", ":", 2) = ["ab", "cd:ef"] | |
566 | * </pre> | |
567 | * | |
568 | * @param str | |
569 | * the String to parse, may be null | |
570 | * @param separatorStr | |
571 | * the characters used as the delimiters, <code>null</code> | |
572 | * splits on whitespace | |
573 | * @param max | |
574 | * the maximum number of elements to include in the array. A zero | |
575 | * or negative value implies no limit | |
576 | * @return an array of parsed Strings | |
577 | */ | |
578 | public static String[] split(String str, String separatorStr, int max) { | |
579 | // Performance tuned for 2.0 (JDK1.4) | |
580 | // Direct code is quicker than StringTokenizer. | |
581 | // Also, StringTokenizer uses isSpace() not isWhitespace() | |
582 | ||
583 | 0 | if (separatorStr == null) { |
584 | 0 | return split(str, max); |
585 | } | |
586 | ||
587 | 0 | if (separatorStr.length() == 1) { |
588 | 0 | return split(str, separatorStr.charAt(0), max); |
589 | } | |
590 | ||
591 | 0 | if (str == null) { |
592 | 0 | return EMPTY_STRING_ARRAY.clone(); |
593 | } | |
594 | ||
595 | 0 | int len = str.length(); |
596 | 0 | if (len == 0) { |
597 | 0 | return EMPTY_STRING_ARRAY.clone(); |
598 | } | |
599 | ||
600 | 0 | char[] cstr = str.toCharArray(); |
601 | 0 | char[] separatorChars = separatorStr.toCharArray(); |
602 | ||
603 | 0 | int count = 0; |
604 | 0 | int start = 0; |
605 | 0 | int i = 0; |
606 | 0 | while ((i = indexOfAny(cstr, separatorChars, start)) != -1) { |
607 | // Don't count separator at beginning, | |
608 | // after another or at the end | |
609 | 0 | if (i > start) { |
610 | 0 | ++count; |
611 | } | |
612 | 0 | start = i + 1; |
613 | } | |
614 | ||
615 | // If it didn't end with a separator then add in the last part | |
616 | 0 | if (start < len) { |
617 | 0 | ++count; |
618 | } | |
619 | ||
620 | // If there were no separators | |
621 | // then we have one big part | |
622 | 0 | if (count == 1) { |
623 | 0 | String[] list = new String[count]; |
624 | 0 | list[0] = str; |
625 | 0 | return list; |
626 | } | |
627 | ||
628 | // Limit the result | |
629 | 0 | if (max > 0 && count > max) { |
630 | 0 | count = max; |
631 | } | |
632 | ||
633 | // Create the array | |
634 | 0 | String[] list = new String[count]; |
635 | ||
636 | 0 | start = 0; |
637 | 0 | i = 0; |
638 | 0 | int x = 0; |
639 | 0 | while ((i = indexOfAny(cstr, separatorChars, start)) != -1) { |
640 | // Don't count separator at beginning, | |
641 | // after another or at the end | |
642 | 0 | if (i > start && x < count) { |
643 | 0 | list[x++] = str.substring(start, i); |
644 | } | |
645 | 0 | start = i + 1; |
646 | } | |
647 | // If it didn't end with a separator then add in the last part | |
648 | 0 | if (start < len && x < count) { |
649 | 0 | list[x++] = str.substring(start); |
650 | } | |
651 | ||
652 | 0 | return list; |
653 | } | |
654 | ||
655 | /** | |
656 | * <p> | |
657 | * Splits the provided text into an array, separator specified. This is an | |
658 | * alternative to using StringTokenizer. | |
659 | * </p> | |
660 | * | |
661 | * <p> | |
662 | * The separator is not included in the returned String array. Adjacent | |
663 | * separators are treated individually. | |
664 | * </p> | |
665 | * | |
666 | * <p> | |
667 | * A <code>null</code> input String returns <code>null</code>. | |
668 | * </p> | |
669 | * | |
670 | * <pre> | |
671 | * StringUtil.splitAll(null, *) = [] | |
672 | * StringUtil.splitAll("", *) = [] | |
673 | * StringUtil.splitAll("a.b.c", '.') = ["a", "b", "c"] | |
674 | * StringUtil.splitAll("a..b.c", '.') = ["a", "", "b", "c"] | |
675 | * StringUtil.splitAll("a:b:c", '.') = ["a:b:c"] | |
676 | * </pre> | |
677 | * | |
678 | * @param str | |
679 | * the String to parse, may be null | |
680 | * @param separatorChar | |
681 | * the character used as the delimiter | |
682 | * @return an array of parsed Strings | |
683 | */ | |
684 | public static String[] splitAll(String str, char separatorChar) { | |
685 | 0 | if (str == null) { |
686 | 0 | return EMPTY_STRING_ARRAY.clone(); |
687 | } | |
688 | ||
689 | 0 | int len = str.length(); |
690 | 0 | if (len == 0) { |
691 | 0 | return EMPTY_STRING_ARRAY.clone(); |
692 | } | |
693 | ||
694 | // Determine the size of the array | |
695 | 0 | int count = 1; |
696 | 0 | int start = 0; |
697 | 0 | int i = 0; |
698 | 0 | while ((i = str.indexOf(separatorChar, start)) != -1) { |
699 | 0 | ++count; |
700 | 0 | start = i + 1; |
701 | } | |
702 | ||
703 | // Create the array | |
704 | 0 | String[] list = new String[count]; |
705 | ||
706 | // If there were no separators | |
707 | // then we have one big part | |
708 | 0 | if (count == 1) { |
709 | 0 | list[0] = str; |
710 | 0 | return list; |
711 | } | |
712 | ||
713 | 0 | start = 0; |
714 | 0 | i = 0; |
715 | 0 | for (int x = 0; x < count; x++) { |
716 | 0 | i = str.indexOf(separatorChar, start); |
717 | 0 | if (i != -1) { |
718 | 0 | list[x] = str.substring(start, i); |
719 | } else { | |
720 | 0 | list[x] = str.substring(start); |
721 | } | |
722 | 0 | start = i + 1; |
723 | } | |
724 | ||
725 | 0 | return list; |
726 | } | |
727 | ||
728 | /** | |
729 | * <p> | |
730 | * Splits the provided text into an array, separator specified. This is an | |
731 | * alternative to using StringTokenizer. | |
732 | * </p> | |
733 | * | |
734 | * <p> | |
735 | * The separator is not included in the returned String array. Adjacent | |
736 | * separators are treated individually. | |
737 | * </p> | |
738 | * | |
739 | * <p> | |
740 | * A <code>null</code> input String returns <code>null</code>. | |
741 | * </p> | |
742 | * | |
743 | * <pre> | |
744 | * StringUtil.splitAll(null, *, 2) = [] | |
745 | * StringUtil.splitAll("", *, 2) = [] | |
746 | * StringUtil.splitAll("a.b.c", '.', 2) = ["a", "b"] | |
747 | * StringUtil.splitAll("a..b.c", '.', 2) = ["a", ""] | |
748 | * StringUtil.splitAll("a:b:c", '.', 2) = ["a:b:c"] | |
749 | * StringUtil.splitAll("a b c", ' ', 2) = ["a", "b"] | |
750 | * </pre> | |
751 | * | |
752 | * @param str | |
753 | * the String to parse, may be null | |
754 | * @param separatorChar | |
755 | * the character used as the delimiter | |
756 | * @param max | |
757 | * the maximum number of elements to include in the array. | |
758 | * A zero or negative value implies no limit | |
759 | * @return an array of parsed Strings | |
760 | */ | |
761 | public static String[] splitAll(String str, char separatorChar, int max) { | |
762 | 0 | if (str == null) { |
763 | 0 | return EMPTY_STRING_ARRAY.clone(); |
764 | } | |
765 | ||
766 | 0 | int len = str.length(); |
767 | 0 | if (len == 0) { |
768 | 0 | return EMPTY_STRING_ARRAY.clone(); |
769 | } | |
770 | ||
771 | // Determine the size of the array | |
772 | 0 | int count = 1; |
773 | 0 | int start = 0; |
774 | 0 | int i = 0; |
775 | 0 | while ((i = str.indexOf(separatorChar, start)) != -1) { |
776 | 0 | ++count; |
777 | 0 | start = i + 1; |
778 | } | |
779 | ||
780 | // If there were no separators | |
781 | // then we have one big part | |
782 | 0 | if (count == 1) { |
783 | 0 | String[] list = new String[count]; |
784 | 0 | list[0] = str; |
785 | 0 | return list; |
786 | } | |
787 | ||
788 | // Limit the result | |
789 | 0 | if (max > 0 && count > max) { |
790 | 0 | count = max; |
791 | } | |
792 | ||
793 | // Create the array | |
794 | 0 | String[] list = new String[count]; |
795 | ||
796 | 0 | start = 0; |
797 | 0 | i = 0; |
798 | 0 | for (int x = 0; x < count; x++) { |
799 | 0 | i = str.indexOf(separatorChar, start); |
800 | 0 | if (i != -1) { |
801 | 0 | list[x] = str.substring(start, i); |
802 | } else { | |
803 | 0 | list[x] = str.substring(start, len); |
804 | } | |
805 | 0 | start = i + 1; |
806 | } | |
807 | ||
808 | 0 | return list; |
809 | } | |
810 | ||
811 | /** | |
812 | * <p> | |
813 | * Joins the elements of the provided array into a single String containing | |
814 | * the provided list of elements. | |
815 | * </p> | |
816 | * | |
817 | * <p> | |
818 | * No delimiter is added before or after the list. A <code>null</code> | |
819 | * separator is the same as an empty String (""). Null objects or empty | |
820 | * strings within the array are represented by empty strings. | |
821 | * </p> | |
822 | * | |
823 | * <pre> | |
824 | * StringUtil.join(null, *) = null | |
825 | * StringUtil.join([], *) = "" | |
826 | * StringUtil.join([null], *) = "" | |
827 | * StringUtil.join(["a", "b", "c"], "--") = "a--b--c" | |
828 | * StringUtil.join(["a", "b", "c"], null) = "abc" | |
829 | * StringUtil.join(["a", "b", "c"], "") = "abc" | |
830 | * StringUtil.join([null, "", "a"], ',') = ",,a" | |
831 | * </pre> | |
832 | * | |
833 | * @param array | |
834 | * the array of values to join together, may be null | |
835 | * @param aSeparator | |
836 | * the separator character to use, null treated as "" | |
837 | * @return the joined String, <code>null</code> if null array input | |
838 | */ | |
839 | public static String join(Object[] array, String aSeparator) { | |
840 | 0 | String separator = aSeparator; |
841 | 0 | if (array == null) { |
842 | 0 | return null; |
843 | } | |
844 | 0 | if (separator == null) { |
845 | 0 | separator = ""; |
846 | } | |
847 | 0 | int arraySize = array.length; |
848 | ||
849 | // ArraySize == 0: Len = 0 | |
850 | // ArraySize > 0: Len = NofStrings *(len(firstString) + len(separator)) | |
851 | // (Assuming that all Strings are roughly equally long) | |
852 | 0 | int bufSize = arraySize == 0 ? 0 : arraySize * ((array[0] == null ? 16 : array[0].toString().length()) + separator.length()); |
853 | ||
854 | 0 | StringBuilder buf = new StringBuilder(bufSize); |
855 | ||
856 | 0 | for (int i = 0; i < arraySize; i++) { |
857 | 0 | if (i > 0) { |
858 | 0 | buf.append(separator); |
859 | } | |
860 | 0 | if (array[i] != null) { |
861 | 0 | buf.append(array[i]); |
862 | } | |
863 | } | |
864 | 0 | return buf.toString(); |
865 | } | |
866 | ||
867 | /** | |
868 | * Find the first occurrence of a separator in the character buffer beginning | |
869 | * at the given offset. | |
870 | * | |
871 | * @param str | |
872 | * the String to parse, may be null | |
873 | * @param separatorChars | |
874 | * the characters used as the delimiters, <code>null</code> | |
875 | * splits on whitespace | |
876 | * @param offset | |
877 | * the index of the first character to consider | |
878 | * @return the index of a separator char in the string or -1 | |
879 | */ | |
880 | public static int indexOfAny(char[] str, char[] separatorChars, int offset) { | |
881 | 0 | int strlen = str.length; |
882 | 0 | int seplen = separatorChars.length; |
883 | 0 | for (int i = offset; i < strlen; i++) { |
884 | 0 | char ch = str[i]; |
885 | 0 | for (int j = 0; j < seplen; j++) { |
886 | 0 | if (separatorChars[j] == ch) { |
887 | 0 | return i; |
888 | } | |
889 | } | |
890 | } | |
891 | 0 | return -1; |
892 | } | |
893 | ||
894 | /** | |
895 | * Find the first occurrence of a whitespace in the character buffer beginning | |
896 | * at the given offset. | |
897 | * Whitespace is defined by {@link Character#isWhitespace(char)}. | |
898 | * | |
899 | * @param str | |
900 | * the String to parse, may be null | |
901 | * @param offset | |
902 | * the index of the first character to consider | |
903 | * @return the index of a separator char in the string or -1 | |
904 | */ | |
905 | public static int indexOfWhitespace(char[] str, int offset) { | |
906 | 0 | int strlen = str.length; |
907 | 0 | for (int i = offset; i < strlen; i++) { |
908 | 0 | if (Character.isWhitespace(str[i])) { |
909 | 0 | return i; |
910 | } | |
911 | } | |
912 | 0 | return -1; |
913 | } | |
914 | ||
915 | /** | |
916 | * An empty immutable <code>String</code> array. | |
917 | */ | |
918 | 0 | public static final String[] EMPTY_STRING_ARRAY = new String[0]; |
919 | ||
920 | } |