1 /*
2 * SSHTools - Java SSH2 API
3 *
4 * Copyright (C) 2002-2003 Lee David Painter and Contributors.
5 *
6 * Contributions made by:
7 *
8 * Brett Smith
9 * Richard Pernavas
10 * Erwin Bolwidt
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 */
26 // ===========================================================================
27 // CONTENT : CLASS StringUtil
28 // AUTHOR : Manfred Duchrow
29 // VERSION : 2.0 - 21/03/2003
30 // HISTORY :
31 // 10/07/1999 duma CREATED
32 // 09/12/1999 duma added -> SPACE, repeat()
33 // moved -> from package com.mdcs.util
34 // 25/01/2000 duma moved -> from package com.mdcs.text
35 // 09/02/2000 duma changed -> renamed SPACE to CH_SPACE
36 // added -> CH_CR, CH_TAB, ..., STR_SPACE, STR_NEWLINE, ...
37 // 11/01/2002 duma added -> indexOf(), indexOfIgnoreCase(), contains(), containsIgnoreCase()
38 // 17/05/2002 duma added -> copyFrom()
39 // 03/07/2002 duma added -> cutHead(), prefix(), suffix()
40 // 06/07/2002 duma added -> indexOf() and contains() for StringPattern and reverse()
41 // 15/08/2002 duma added -> upTo(), startingFrom(), asMap()
42 // 29/09/2002 duma added -> allParts() and allSubstrings() that don't skip empty elements
43 // 06/03/2003 duma changed -> append() now uses System.arraycopy()
44 // added -> remove( String[], String[] ), remove( String[], String )
45 // removeNull( String[] )
46 // 21/03/2003 duma added -> leftPad(), leftPadCh(), rightPad(), rightPadCh() for int values
47 //
48 // Copyright (c) 1999-2003, by Manfred Duchrow. All rights reserved.
49 // ===========================================================================
50 package com.sshtools.daemon.util;
51
52 import java.io;
53
54 import java.text;
55
56 import java.util;
57
58
59 /**
60 * The sole instance of this class provides several convienience methods for
61 * string manipulation such as substring replacement or character repetition.
62 *
63 * @author Manfred Duchrow
64 * @version 2.0
65 */
66 public class StringUtil {
67 // =========================================================================
68 // CONSTANTS
69 // =========================================================================
70
71 /** Constant for the space character */
72 public static final char CH_SPACE = '\u0020';
73
74 /** Constant for the new line character */
75 public static final char CH_NEWLINE = '\n';
76
77 /** Constant for the carriage return character */
78 public static final char CH_CR = '\r';
79
80 /** Constant for the tabulator character */
81 public static final char CH_TAB = '\t';
82
83 /** Constant for the String representation of the space character */
84 public static final String STR_SPACE = "\u0020";
85
86 /** Constant for the String representation of the new line character */
87 public static final String STR_NEWLINE = "\n";
88
89 /**
90 * Constant for the String representation of the carriage return character
91 */
92 public static final String STR_CR = "\r";
93
94 /** Constant for the String representation of the tabulator character */
95 public static final String STR_TAB = "\t";
96 private static final String WORD_DELIM = STR_SPACE + STR_TAB + STR_NEWLINE +
97 STR_CR;
98
99 // =========================================================================
100 // CLASS VARIABLES
101 // =========================================================================
102 private static StringUtil singleton = null;
103
104 private static StringUtil getSingleton() {
105 return singleton;
106 }
107
108 private static void setSingleton(StringUtil inst) {
109 singleton = inst;
110 }
111
112 // =========================================================================
113 // PUBLIC CLASS METHODS
114 // =========================================================================
115
116 /**
117 * Returns the one and only instance of this class.
118 *
119 * @return
120 */
121 public static StringUtil current() {
122 if (getSingleton() == null) {
123 setSingleton(new StringUtil());
124 }
125
126 return getSingleton();
127 }
128
129 // current()
130 // =========================================================================
131 // PUBLIC INSTANCE METHODS
132 // =========================================================================
133
134 /**
135 * Returns the given string with all found oldSubStr replaced by newSubStr. <br>
136 * Example: StringUtil.current().replaceAll( "Seven of ten", "even", "ix"
137 * ) ;<br>
138 * results in: "Six of ten"
139 *
140 * @param sourceStr The string that should be checked for occurrences of
141 * oldSubStr
142 * @param oldSubStr The string that is searched for in sourceStr
143 * @param newSubStr The new string that is placed everywhere the oldSubStr
144 * was found
145 *
146 * @return The original string with all found substrings replaced by new
147 * strings
148 */
149 public String replaceAll(String sourceStr, String oldSubStr,
150 String newSubStr) {
151 String part = null;
152 String result = "";
153 int index = -1;
154 int subLen = 0;
155 subLen = oldSubStr.length();
156 part = sourceStr;
157
158 while ((part.length() > 0) && (subLen > 0)) {
159 index = part.indexOf(oldSubStr);
160
161 if (index >= 0) {
162 result = result + part.substring(0, index) + newSubStr;
163 part = part.substring(index + subLen);
164 } else {
165 result = result + part;
166 part = "";
167 }
168 }
169
170 // while
171 return result;
172 }
173
174 // replaceAll()
175 // -------------------------------------------------------------------------
176
177 /**
178 * Returns a string with size of count and all characters initialized with
179 * ch. <br>
180 *
181 * @param ch the character to be repeated in the result string.
182 * @param count the number of times the given character should occur in the
183 * result string.
184 *
185 * @return A string containing <i>count</i> characters <i>ch</i>.
186 */
187 public String repeat(char ch, int count) {
188 StringBuffer buffer = null;
189 buffer = new StringBuffer(count);
190
191 for (int i = 1; i <= count; i++) {
192 buffer.append(ch);
193 }
194
195 return (buffer.toString());
196 }
197
198 // repeat()
199 // -------------------------------------------------------------------------
200
201 /**
202 * Returns an array of substrings of the given text. <br>
203 * The delimiters between the substrings are the whitespace characters
204 * SPACE, NEWLINE, CR and TAB.
205 *
206 * @param text The string that should be splitted into whitespace separated
207 * words
208 *
209 * @return An array of substrings of the given text
210 *
211 * @see #parts(String, String)
212 */
213 public String[] words(String text) {
214 return this.parts(text, WORD_DELIM);
215 }
216
217 // words()
218 // -------------------------------------------------------------------------
219
220 /**
221 * Returns an array of substrings of the given text. <br>
222 * The separators between the substrings are the given delimiters. Each
223 * character in the delimiter string is treated as a separator. <br>
224 * All consecutive delimiters are treated as one delimiter, that is there
225 * will be no empty strings in the result.
226 *
227 * @param text The string that should be splitted into substrings
228 * @param delimiters All characters that should be recognized as a
229 * separator or substrings
230 *
231 * @return An array of substrings of the given text
232 *
233 * @see #allParts(String, String)
234 * @see #substrings(String, String)
235 * @see #allSubstrings(String, String)
236 */
237 public String[] parts(String text, String delimiters) {
238 return this.parts(text, delimiters, false);
239 }
240
241 // parts()
242 // -------------------------------------------------------------------------
243
244 /**
245 * Returns an array of substrings of the given text. <br>
246 * The separators between the substrings are the given delimiters. Each
247 * character in the delimiter string is treated as a separator. <br>
248 * For each delimiter that is followed immediately by another delimiter an
249 * empty string will be added to the result. There are no empty strings
250 * added to the result for a delimiter at the very beginning of at the
251 * very end.
252 *
253 * <p>
254 * Examples:
255 * </p>
256 *
257 * <p>
258 * allParts( "/A/B//", "/" ) --> { "A", "B", "" }<br>
259 * allParts( "/A,B/C;D", ",;/" ) --> { "A", "B", "C", "D" }<br>
260 * allParts( "A/B,C/D", "," ) --> { "A/B", "C/D" }<br>
261 * </p>
262 *
263 * @param text The string that should be splitted into substrings
264 * @param delimiters All characters that should be recognized as a
265 * separator or substrings
266 *
267 * @return An array of substrings of the given text
268 *
269 * @see #parts(String, String)
270 * @see #substrings(String, String)
271 * @see #allSubstrings(String, String)
272 */
273 public String[] allParts(String text, String delimiters) {
274 return this.parts(text, delimiters, true);
275 }
276
277 // allParts()
278 // -------------------------------------------------------------------------
279
280 /**
281 * Returns the given text split up into an array of strings, at the
282 * occurrances of the separator string. In contrary to method parts() the
283 * separator is a one or many character sequence delimiter. That is, only
284 * the exact sequence of the characters in separator identifies the end
285 * of a substring. Subsequent occurences of separator will be skipped.
286 * Therefore no empty strings ("") will be in the result array.
287 *
288 * @param text The text to be split up
289 * @param separator The string that separates the substrings
290 *
291 * @return An array of substrings not containing any separator anymore
292 *
293 * @see #allSubstrings(String, String)
294 * @see #parts(String, String)
295 * @see #allParts(String, String)
296 */
297 public String[] substrings(String text, String separator) {
298 return this.substrings(text, separator, false);
299 }
300
301 // substrings()
302 // -------------------------------------------------------------------------
303
304 /**
305 * Returns the given text split up into an array of strings, at the
306 * occurrances of the separator string. In contrary to method allParts()
307 * the separator is a one or many character sequence delimiter. That is,
308 * only the exact sequence of the characters in separator identifies the
309 * end of a substring. Subsequent occurences of separator are not skipped.
310 * They are added as empty strings to the result.
311 *
312 * @param text The text to be split up
313 * @param separator The string that separates the substrings
314 *
315 * @return An array of substrings not containing any separator anymore
316 *
317 * @see #substrings(String, String)
318 * @see #parts(String, String)
319 * @see #allParts(String, String)
320 */
321 public String[] allSubstrings(String text, String separator) {
322 return this.substrings(text, separator, true);
323 }
324
325 // allSubstrings()
326 // -------------------------------------------------------------------------
327
328 /**
329 * Returns the first substring that is enclosed by the specified
330 * delimiters. <br>
331 * The delimiters are not included in the return string.
332 *
333 * <p>
334 * Example:<br> getDelimitedSubstring( "This {placeholder} belongs to me",
335 * "{", "}" ) --> returns "placeholder"
336 * </p>
337 *
338 * @param text The input string that contains the delimited part
339 * @param startDelimiter The start delimiter of the substring
340 * @param endDelimiter The end delimiter of the substring
341 *
342 * @return The substring or an empty string, if no delimiters are found.
343 */
344 public String getDelimitedSubstring(String text, String startDelimiter,
345 String endDelimiter) {
346 int start;
347 int stop;
348 String subStr = "";
349
350 if ((text != null) && (startDelimiter != null) &&
351 (endDelimiter != null)) {
352 start = text.indexOf(startDelimiter);
353
354 if (start >= 0) {
355 stop = text.indexOf(endDelimiter, start + 1);
356
357 if (stop > start) {
358 subStr = text.substring(start + 1, stop);
359 }
360 }
361 }
362
363 return subStr;
364 }
365
366 // getDelimitedSubstring()
367 // -------------------------------------------------------------------------
368
369 /**
370 * Returns the first substring that is enclosed by the specified delimiter. <br>
371 * The delimiters are not included in the return string.
372 *
373 * <p>
374 * Example:<br> getDelimitedSubstring( "File 'text.txt' not found.", "'",
375 * "'" ) --> returns "text.txt"
376 * </p>
377 *
378 * @param text The input string that contains the delimited part
379 * @param delimiter The start and end delimiter of the substring
380 *
381 * @return The substring or an empty string, if no delimiters are found.
382 */
383 public String getDelimitedSubstring(String text, String delimiter) {
384 return this.getDelimitedSubstring(text, delimiter, delimiter);
385 }
386
387 // getDelimitedSubstring()
388 // -------------------------------------------------------------------------
389
390 /**
391 * Prints the stack trace of the specified throwable to a string and
392 * returns it.
393 *
394 * @param throwable
395 *
396 * @return
397 */
398 public String stackTrace(Throwable throwable) {
399 StringWriter sw = new StringWriter();
400 PrintWriter pw = new PrintWriter(sw);
401 throwable.printStackTrace(pw);
402 pw.close();
403
404 return sw.toString();
405 }
406
407 // stackTrace()
408 // -------------------------------------------------------------------------
409
410 /**
411 * Returns the given string filled (on the left) up to the specified length
412 * with the given character. <br>
413 * Example: leftPadCh( "12", 6, '0' ) --> "000012"
414 *
415 * @param str
416 * @param len
417 * @param ch
418 *
419 * @return
420 */
421 public String leftPadCh(String str, int len, char ch) {
422 return this.padCh(str, len, ch, true);
423 }
424
425 // leftPadCh()
426 // -------------------------------------------------------------------------
427
428 /**
429 * Returns the given string filled (on the left) up to the specified length
430 * with spaces. <br>
431 * Example: leftPad( "XX", 4 ) --> " XX"
432 *
433 * @param str The string that has to be filled up to the specified length
434 * @param len The length of the result string
435 *
436 * @return
437 */
438 public String leftPad(String str, int len) {
439 return this.leftPadCh(str, len, CH_SPACE);
440 }
441
442 // leftPad()
443 // -------------------------------------------------------------------------
444
445 /**
446 * Returns the given integer as string filled (on the left) up to the
447 * specified length with the given fill character. <br>
448 * Example: leftPad( 24, 5, '' ) --> "24"
449 *
450 * @param value
451 * @param len
452 * @param fillChar
453 *
454 * @return
455 */
456 public String leftPadCh(int value, int len, char fillChar) {
457 return this.leftPadCh(Integer.toString(value), len, fillChar);
458 }
459
460 // leftPadCh()
461 // -------------------------------------------------------------------------
462
463 /**
464 * Returns the given integer as string filled (on the left) up to the
465 * specified length with zeroes. <br>
466 * Example: leftPad( 12, 4 ) --> "0012"
467 *
468 * @param value
469 * @param len
470 *
471 * @return
472 */
473 public String leftPad(int value, int len) {
474 return this.leftPadCh(value, len, '0');
475 }
476
477 // leftPad()
478 // -------------------------------------------------------------------------
479
480 /**
481 * Returns the given string filled (on the right) up to the specified
482 * length with the given character. <br>
483 * Example: rightPadCh( "34", 5, 'X' ) --> "34XXX"
484 *
485 * @param str
486 * @param len
487 * @param ch
488 *
489 * @return
490 */
491 public String rightPadCh(String str, int len, char ch) {
492 return this.padCh(str, len, ch, false);
493 }
494
495 // rightPadCh()
496 // -------------------------------------------------------------------------
497
498 /**
499 * Returns the given string filled (on the right) up to the specified
500 * length with spaces. <br>
501 * Example: rightPad( "88", 6 ) --> "88 "
502 *
503 * @param str
504 * @param len
505 *
506 * @return
507 */
508 public String rightPad(String str, int len) {
509 return this.rightPadCh(str, len, CH_SPACE);
510 }
511
512 // rightPad()
513 // -------------------------------------------------------------------------
514
515 /**
516 * Returns the given integer as string filled (on the right) up to the
517 * specified length with the given character. <br>
518 * Example: rightPad( "32", 4, '#' ) --> "32##"
519 *
520 * @param value
521 * @param len
522 * @param fillChar
523 *
524 * @return
525 */
526 public String rightPadCh(int value, int len, char fillChar) {
527 return this.rightPadCh(Integer.toString(value), len, fillChar);
528 }
529
530 // rightPad()
531 // -------------------------------------------------------------------------
532
533 /**
534 * Returns the given integer as string filled (on the right) up to the
535 * specified length with spaces. <br>
536 * Example: rightPad( "17", 5 ) --> "17 "
537 *
538 * @param value
539 * @param len
540 *
541 * @return
542 */
543 public String rightPad(int value, int len) {
544 return this.rightPadCh(value, len, CH_SPACE);
545 }
546
547 // rightPad()
548 // -------------------------------------------------------------------------
549
550 /**
551 * Returns the given string filled equally left and right up to the
552 * specified length with the given character. <br>
553 * Example: centerCh( "A", 5, '_' ) --> "__A__" <br>
554 * Example: centerCh( "XX", 7, '+' ) --> "++XX+++"
555 *
556 * @param str
557 * @param len
558 * @param ch
559 *
560 * @return
561 */
562 public String centerCh(String str, int len, char ch) {
563 String buffer = null;
564 int missing = len - str.length();
565 int half = 0;
566
567 if (missing <= 0) {
568 return str;
569 }
570
571 half = missing / 2;
572 buffer = this.rightPadCh(str, len - half, ch);
573
574 return this.leftPadCh(buffer, len, ch);
575 }
576
577 // centerCh()
578 // -------------------------------------------------------------------------
579
580 /**
581 * Returns the given string filled (on the right and right) up to the
582 * specified length with spaces. <br>
583 * Example: center( "Mike", 10 ) --> " Mike "
584 *
585 * @param str
586 * @param len
587 *
588 * @return
589 */
590 public String center(String str, int len) {
591 return this.centerCh(str, len, CH_SPACE);
592 }
593
594 // center()
595 // -------------------------------------------------------------------------
596
597 /**
598 * Returns the given string array extended by one element that hold the
599 * specified string.
600 *
601 * @param strings
602 * @param string
603 *
604 * @return
605 */
606 public String[] append(String[] strings, String string) {
607 String[] appStr = { string };
608
609 return this.append(strings, appStr);
610 }
611
612 // append()
613 // -------------------------------------------------------------------------
614
615 /**
616 * Returns an array of strings that contains all strings given by the first
617 * and second string array. The strings from the second array will be
618 * added at the end of the first array.
619 *
620 * @param strings The array of string to which to append
621 * @param appendStrings The string to be appended to the first array
622 *
623 * @return
624 */
625 public String[] append(String[] strings, String[] appendStrings) {
626 String[] newStrings = null;
627
628 if (strings == null) {
629 return appendStrings;
630 }
631
632 if (appendStrings == null) {
633 return strings;
634 }
635
636 newStrings = new String[strings.length + appendStrings.length];
637 System.arraycopy(strings, 0, newStrings, 0, strings.length);
638 System.arraycopy(appendStrings, 0, newStrings, strings.length,
639 appendStrings.length);
640
641 return newStrings;
642 }
643
644 // append()
645 // -------------------------------------------------------------------------
646
647 /**
648 * Returns an array of strings that contains all strings given in the first
649 * plus the specified string to append, if it is not already in the given
650 * array.
651 *
652 * @param strings
653 * @param appendString
654 *
655 * @return
656 */
657 public String[] appendIfNotThere(String[] strings, String appendString) {
658 if (this.contains(strings, appendString)) {
659 return strings;
660 } else {
661 return this.append(strings, appendString);
662 }
663 }
664
665 // appendIfNotThere()
666 // -------------------------------------------------------------------------
667
668 /**
669 * Returns an array of strings that contains all strings given in the first
670 * plus all strings of the second array that are not already in the first
671 * array.
672 *
673 * @param strings
674 * @param appendStrings
675 *
676 * @return
677 */
678 public String[] appendIfNotThere(String[] strings, String[] appendStrings) {
679 String[] newStrings = strings;
680
681 if (appendStrings == null) {
682 return newStrings;
683 }
684
685 for (int i = 0; i < appendStrings.length; i++) {
686 newStrings = this.appendIfNotThere(newStrings, appendStrings[i]);
687 }
688
689 return newStrings;
690 }
691
692 // appendIfNotThere()
693 // -------------------------------------------------------------------------
694
695 /**
696 * Removes all string of the second array from the first array. Returns a
697 * new array of string that contains all remaining strings of the original
698 * strings array.
699 *
700 * @param strings The array from which to remove the strings
701 * @param removeStrings The strings to be removed
702 *
703 * @return
704 */
705 public String[] remove(String[] strings, String[] removeStrings) {
706 if ((strings == null) || (removeStrings == null) ||
707 (strings.length == 0) || (removeStrings.length == 0)) {
708 return strings;
709 }
710
711 return this.removeFromStringArray(strings, removeStrings);
712 }
713
714 // remove()
715 // -------------------------------------------------------------------------
716
717 /**
718 * Removes the given string from the specified string array. Returns a new
719 * array of string that contains all remaining strings of the original
720 * strings array.
721 *
722 * @param strings The array from which to remove the string
723 * @param removeString The string to be removed
724 *
725 * @return
726 */
727 public String[] remove(String[] strings, String removeString) {
728 String[] removeStrings = { removeString };
729
730 return this.remove(strings, removeStrings);
731 }
732
733 // remove()
734 // -------------------------------------------------------------------------
735
736 /**
737 * Removes all null values from the given string array. Returns a new
738 * string array that contains all none null values of the input array.
739 *
740 * @param strings The array to be cleared of null values
741 *
742 * @return
743 */
744 public String[] removeNull(String[] strings) {
745 if (strings == null) {
746 return strings;
747 }
748
749 return this.removeFromStringArray(strings, null);
750 }
751
752 // removeNull()
753 // -------------------------------------------------------------------------
754
755 /**
756 * Returns a string that contains all given strings concatenated and
757 * separated by the specified separator.
758 *
759 * @param strings The array of strings that should be concatenated
760 * @param separator The separator between the strings
761 *
762 * @return One string containing the concatenated strings separated by
763 * separator
764 */
765 public String asString(String[] strings, String separator) {
766 StringBuffer buffer = null;
767 buffer = new StringBuffer(strings.length * 20);
768
769 if (strings.length > 0) {
770 buffer.append(strings[0].toString());
771
772 for (int i = 1; i < strings.length; i++) {
773 buffer.append(separator);
774
775 if (strings[i] != null) {
776 buffer.append(strings[i]);
777 }
778 }
779 }
780
781 return buffer.toString();
782 }
783
784 // asString()
785 // -------------------------------------------------------------------------
786
787 /**
788 * Returns a string that contains all given strings concatenated and
789 * separated by comma.
790 *
791 * @param strings The array of strings that should be concatenated
792 *
793 * @return One string containing the concatenated strings separated by
794 * comma (",")
795 */
796 public String asString(String[] strings) {
797 return this.asString(strings, ",");
798 }
799
800 // asString()
801 // -------------------------------------------------------------------------
802
803 /**
804 * Returns the index of the first string in the given string array that
805 * matches the specified string pattern. If no string is found in the
806 * array the result is -1.
807 *
808 * @param strArray An array of string (may contain null elements)
809 * @param pattern The pattern the searched string must match
810 *
811 * @return The index of the matching string in the array or -1 if not found
812 */
813 public int indexOf(String[] strArray, StringPattern pattern) {
814 if ((strArray == null) || (strArray.length == 0)) {
815 return -1;
816 }
817
818 boolean found = false;
819
820 for (int i = 0; i < strArray.length; i++) {
821 if (strArray[i] == null) {
822 if (pattern == null) {
823 found = true;
824 }
825 } else {
826 if (pattern != null) {
827 found = pattern.matches(strArray[i]);
828 }
829 }
830
831 if (found) {
832 return i;
833 }
834 }
835
836 return -1;
837 }
838
839 // indexOf()
840 // -------------------------------------------------------------------------
841
842 /**
843 * Returns the index of the specified string in the given string array. It
844 * returns the index of the first occurrence of the string. If the string
845 * is not found in the array the result is -1. The comparison of the
846 * strings is case-sensitive!
847 *
848 * @param strArray An array of string (may contain null elements)
849 * @param searchStr The string to be looked up in the array (null allowed)
850 *
851 * @return The index of the string in the array or -1 if not found
852 */
853 public int indexOf(String[] strArray, String searchStr) {
854 return this.indexOfString(strArray, searchStr, false);
855 }
856
857 // indexOf()
858 // -------------------------------------------------------------------------
859
860 /**
861 * Returns the index of the specified string in the given string array. It
862 * returns the index of the first occurrence of the string. If the string
863 * is not found in the array the result is -1. The comparison of the
864 * strings is case-insensitive!
865 *
866 * @param strArray An array of string (may contain null elements)
867 * @param searchStr The string to be looked up in the array (null allowed)
868 *
869 * @return The index of the string in the array or -1 if not found
870 */
871 public int indexOfIgnoreCase(String[] strArray, String searchStr) {
872 return this.indexOfString(strArray, searchStr, true);
873 }
874
875 // indexOfIgnoreCase()
876 // -------------------------------------------------------------------------
877
878 /**
879 * Returns whether or not the specified string can be found in the given
880 * string array.
881 *
882 * @param strArray An array of string (may contain null elements)
883 * @param searchStr The string to be looked up in the array (null allowed)
884 * @param ignoreCase Defines whether or not the comparison is
885 * case-sensitive.
886 *
887 * @return true, if the specified array contains the given string
888 */
889 public boolean contains(String[] strArray, String searchStr,
890 boolean ignoreCase) {
891 if (ignoreCase) {
892 return this.containsIgnoreCase(strArray, searchStr);
893 } else {
894 return this.contains(strArray, searchStr);
895 }
896 }
897
898 // contains()
899 // -------------------------------------------------------------------------
900
901 /**
902 * Returns whether or not a string can be found in the given string array
903 * that matches the specified string pattern.
904 *
905 * @param strArray An array of string (may contain null elements)
906 * @param pattern The string pattern to match against in the array (null
907 * allowed)
908 *
909 * @return true, if the specified array contains a string matching the
910 * pattern
911 */
912 public boolean contains(String[] strArray, StringPattern pattern) {
913 return (this.indexOf(strArray, pattern) >= 0);
914 }
915
916 // contains()
917 // -------------------------------------------------------------------------
918
919 /**
920 * Returns whether or not the specified string can be found in the given
921 * string array. The comparison of the strings is case-sensitive!
922 *
923 * @param strArray An array of string (may contain null elements)
924 * @param searchStr The string to be looked up in the array (null allowed)
925 *
926 * @return true, if the specified array contains the given string
927 */
928 public boolean contains(String[] strArray, String searchStr) {
929 return (this.indexOf(strArray, searchStr) >= 0);
930 }
931
932 // contains()
933 // -------------------------------------------------------------------------
934
935 /**
936 * Returns whether or not the specified string can be found in the given
937 * string array. The comparison of the strings is case-insensitive!
938 *
939 * @param strArray An array of string (may contain null elements)
940 * @param searchStr The string to be looked up in the array (null allowed)
941 *
942 * @return true, if the specified array contains the given string
943 */
944 public boolean containsIgnoreCase(String[] strArray, String searchStr) {
945 return (this.indexOfIgnoreCase(strArray, searchStr) >= 0);
946 }
947
948 // containsIgnoreCase()
949 // -------------------------------------------------------------------------
950
951 /**
952 * Returns all elements of string array <i>from</i> in a new array from
953 * index start up to the end. If start index is larger than the array's
954 * length, an empty array will be returned.
955 *
956 * @param from The string array the elements should be copied from
957 * @param start Index of the first element to copy
958 *
959 * @return
960 */
961 public String[] copyFrom(String[] from, int start) {
962 if (from == null) {
963 return null;
964 }
965
966 return this.copyFrom(from, start, from.length - 1);
967 }
968
969 // copyFrom()
970 // -------------------------------------------------------------------------
971
972 /**
973 * Returns all elements of string array <i>from</i> in a new array from
974 * index start up to index end (inclusive). If end is larger than the last
975 * valid index, it will be reduced to the last index. If end index is less
976 * than start index, an empty array will be returned.
977 *
978 * @param from The string array the elements should be copied from
979 * @param start Index of the first element to copy
980 * @param end Index of last element to be copied
981 *
982 * @return
983 */
984 public String[] copyFrom(String[] from, int start, int end) {
985 String[] result;
986 int count;
987 int stop = end;
988
989 if (from == null) {
990 return null;
991 }
992
993 if (stop > (from.length - 1)) {
994 stop = from.length - 1;
995 }
996
997 count = stop - start + 1;
998
999 if (count < 1) {
1000 return new String[0];
1001 }
1002
1003 result = new String[count];
1004 System.arraycopy(from, start, result, 0, count);
1005
1006 return result;
1007 }
1008
1009 // copyFrom()
1010 // -------------------------------------------------------------------------
1011
1012 /**
1013 * Returns the portion of the given string that comes before the last
1014 * occurance of the specified separator. <br>
1015 * If the separator could not be found in the given string, then the
1016 * string is returned unchanged.
1017 *
1018 * <p>
1019 * Examples:
1020 * </p>
1021 *
1022 * <p>
1023 * cutTail( "A/B/C", "/" ) ; // returns "A/B" <br>
1024 * cutTail( "A/B/C", "," ) ; // returns "A/B/C"
1025 * </p>
1026 *
1027 * <p></p>
1028 *
1029 * @param text The string from which to cut off the tail
1030 * @param separator The separator from where to cut off
1031 *
1032 * @return the string without the separator and without the characters
1033 * after the separator
1034 *
1035 * @see #prefix( String, String )
1036 * @see #suffix( String, String )
1037 * @see #cutHead( String, String )
1038 * @see #startingFrom( String, String )
1039 * @see #upTo( String, String )
1040 */
1041 public String cutTail(String text, String separator) {
1042 int index;
1043
1044 if ((text == null) || (separator == null)) {
1045 return text;
1046 }
1047
1048 index = text.lastIndexOf(separator);
1049
1050 if (index < 0) {
1051 return text;
1052 }
1053
1054 return text.substring(0, index);
1055 }
1056
1057 // cutTail()
1058 // ------------------------------------------------------------------------
1059
1060 /**
1061 * Returns the portion of the given string that stands after the last
1062 * occurance of the specified separator. <br>
1063 * If the separator could not be found in the given string, then the
1064 * string is returned unchanged.
1065 *
1066 * <p>
1067 * Examples:
1068 * </p>
1069 *
1070 * <p>
1071 * cutHead( "A/B/C", "/" ) ; // returns "C" <br>
1072 * cutHead( "A/B/C", "," ) ; // returns "A/B/C"
1073 * </p>
1074 *
1075 * <p></p>
1076 *
1077 * @param text The string from which to cut off the head
1078 * @param separator The separator up to which to cut off
1079 *
1080 * @return the string without the separator and without the characters
1081 * before the separator
1082 *
1083 * @see #prefix( String, String )
1084 * @see #cutTail( String, String )
1085 * @see #suffix( String, String )
1086 * @see #startingFrom( String, String )
1087 * @see #upTo( String, String )
1088 */
1089 public String cutHead(String text, String separator) {
1090 int index;
1091
1092 if ((text == null) || (separator == null)) {
1093 return text;
1094 }
1095
1096 index = text.lastIndexOf(separator);
1097
1098 if (index < 0) {
1099 return text;
1100 }
1101
1102 return text.substring(index + 1);
1103 }
1104
1105 // cutHead()
1106 // ------------------------------------------------------------------------
1107
1108 /**
1109 * Returns a string array with two elements where the first is the
1110 * attribute name and the second is the attribute value. Splits the given
1111 * string at the first occurance of separator and returns the piece before
1112 * the separator in element 0 and the piece after the separator in the
1113 * returned array. If the separator is not found, the first element
1114 * contains the full string and the second an empty string.
1115 *
1116 * @param str The string that contains the name-value pair
1117 * @param separator The separator between name and value
1118 *
1119 * @return
1120 */
1121 public String[] splitNameValue(String str, String separator) {
1122 String[] result = { "", "" };
1123 int index;
1124
1125 if (str != null) {
1126 index = str.indexOf(separator);
1127
1128 if (index > 0) {
1129 result[0] = str.substring(0, index);
1130 result[1] = str.substring(index + separator.length());
1131 } else {
1132 result[0] = str;
1133 }
1134 }
1135
1136 return result;
1137 }
1138
1139 // splitNameValue()
1140 // -------------------------------------------------------------------------
1141
1142 /**
1143 * Returns the substring of the given string that comes before the first
1144 * occurance of the specified separator. If the string starts with a
1145 * separator, the result will be an empty string. If the string doesn't
1146 * contain the separator the method returns null.
1147 *
1148 * <p>
1149 * Examples:
1150 * </p>
1151 *
1152 * <p>
1153 * prefix( "A/B/C", "/" ) ; // returns "A" <br>
1154 * prefix( "A/B/C", "," ) ; // returns null
1155 * </p>
1156 *
1157 * <p></p>
1158 *
1159 * @param str The string of which the prefix is desired
1160 * @param separator Separates the prefix from the rest of the string
1161 *
1162 * @return
1163 *
1164 * @see #suffix( String, String )
1165 * @see #cutTail( String, String )
1166 * @see #cutHead( String, String )
1167 * @see #startingFrom( String, String )
1168 * @see #upTo( String, String )
1169 */
1170 public String prefix(String str, String separator) {
1171 return this.prefix(str, separator, true);
1172 }
1173
1174 // prefix()
1175 // -------------------------------------------------------------------------
1176
1177 /**
1178 * Returns the substring of the given string that comes after the first
1179 * occurance of the specified separator. If the string ends with a
1180 * separator, the result will be an empty string. If the string doesn't
1181 * contain the separator the method returns null.
1182 *
1183 * <p>
1184 * Examples:
1185 * </p>
1186 *
1187 * <p>
1188 * suffix( "A/B/C", "/" ) ; // returns "B/C" <br>
1189 * suffix( "A/B/C", "," ) ; // returns null
1190 * </p>
1191 *
1192 * <p></p>
1193 *
1194 * @param str The string of which the suffix is desired
1195 * @param separator Separates the suffix from the rest of the string
1196 *
1197 * @return
1198 *
1199 * @see #prefix( String, String )
1200 * @see #cutTail( String, String )
1201 * @see #cutHead( String, String )
1202 * @see #startingFrom( String, String )
1203 * @see #upTo( String, String )
1204 */
1205 public String suffix(String str, String separator) {
1206 return this.suffix(str, separator, true);
1207 }
1208
1209 // suffix()
1210 // -------------------------------------------------------------------------
1211
1212 /**
1213 * Returns the substring of the given string that comes before the first
1214 * occurance of the specified separator. If the string starts with a
1215 * separator, the result will be an empty string. If the string doesn't
1216 * contain the separator the method returns the whole string unchanged.
1217 *
1218 * <p>
1219 * Examples:
1220 * </p>
1221 *
1222 * <p>
1223 * upTo( "A/B/C", "/" ) ; // returns "A" <br>
1224 * upTo( "A/B/C", "," ) ; // returns "A/B/C" <br>
1225 * upTo( "/A/B/C", "/" ) ; // returns ""
1226 * </p>
1227 *
1228 * <p></p>
1229 *
1230 * @param str The string of which the prefix is desired
1231 * @param separator Separates the prefix from the rest of the string
1232 *
1233 * @return
1234 *
1235 * @see #prefix( String, String )
1236 * @see #cutTail( String, String )
1237 * @see #cutHead( String, String )
1238 * @see #startingFrom( String, String )
1239 * @see #suffix( String, String )
1240 */
1241 public String upTo(String str, String separator) {
1242 return this.prefix(str, separator, false);
1243 }
1244
1245 // upTo()
1246 // -------------------------------------------------------------------------
1247
1248 /**
1249 * Returns the substring of the given string that comes after the first
1250 * occurance of the specified separator. If the string doesn't contain the
1251 * separator the method returns the whole string unchanged.
1252 *
1253 * <p>
1254 * Examples:
1255 * </p>
1256 *
1257 * <p>
1258 * startingFrom( "A/B/C", "/" ) ; // returns "B/C" <br>
1259 * startingFrom( "A/B/C", "," ) ; // returns "A/B/C"
1260 * </p>
1261 *
1262 * <p></p>
1263 *
1264 * @param str The string of which the suffix is desired
1265 * @param separator Separates the suffix from the rest of the string
1266 *
1267 * @return
1268 *
1269 * @see #prefix( String, String )
1270 * @see #cutTail( String, String )
1271 * @see #cutHead( String, String )
1272 * @see #suffix( String, String )
1273 * @see #upTo( String, String )
1274 */
1275 public String startingFrom(String str, String separator) {
1276 return this.suffix(str, separator, false);
1277 }
1278
1279 // startingFrom()
1280 // -------------------------------------------------------------------------
1281
1282 /**
1283 * Returns a string that contains all characters of the given string in
1284 * reverse order.
1285 *
1286 * @param str
1287 *
1288 * @return
1289 */
1290 public String reverse(String str) {
1291 if (str == null) {
1292 return null;
1293 }
1294
1295 char[] newStr = new char[str.length()];
1296 StringCharacterIterator iterator = new StringCharacterIterator(str);
1297 int i = 0;
1298
1299 for (char ch = iterator.last(); ch != CharacterIterator.DONE;
1300 ch = iterator.previous()) {
1301 newStr[i] = ch;
1302 i++;
1303 }
1304
1305 return new String(newStr);
1306 }
1307
1308 // reverse()
1309 // -------------------------------------------------------------------------
1310
1311 /**
1312 * Returns the given map with new entries from the specified String. If the
1313 * specified map is null a new empty java.util.Hashtable will be created. <br>
1314 * The string is split up into elements separated by the elementSeparator
1315 * parameter. If this parameter is null the default separator "," is used. <br>
1316 * After that each part is split up to a key-value pair separated by the
1317 * keyValueSeparator parameter. If this parameter is null the default "="
1318 * is used. <br>
1319 * Then the key-value pairs are added to the map and the map is returned.
1320 *
1321 * <p>
1322 * <b>Be aware that all leading and trailing whitespaces of keys and values
1323 * will be removed!</b>
1324 * </p>
1325 *
1326 * @param str The string that contains the list of key-value pairs
1327 * @param elementSeparator The separator between the elements of the list
1328 * @param keyValueSeparator The separator between the keys and values
1329 * @param map The map to which the key-value pairs are added
1330 *
1331 * @return
1332 */
1333 public Map toMap(String str, String elementSeparator,
1334 String keyValueSeparator, Map map) {
1335 Map result;
1336 String elemSep;
1337 String kvSep;
1338 String[] assignments;
1339 String[] nameValue;
1340
1341 if (str == null) {
1342 return map;
1343 }
1344
1345 result = ((map == null) ? new Hashtable() : map);
1346 elemSep = (elementSeparator == null) ? "," : elementSeparator;
1347 kvSep = (keyValueSeparator == null) ? "=" : keyValueSeparator;
1348 assignments = this.parts(str, elemSep);
1349
1350 for (int i = 0; i < assignments.length; i++) {
1351 nameValue = this.splitNameValue(assignments[i], kvSep);
1352 nameValue[0] = nameValue[0].trim();
1353 nameValue[1] = nameValue[1].trim();
1354
1355 if (nameValue[0].length() > 0) {
1356 result.put(nameValue[0], nameValue[1]);
1357 }
1358 }
1359
1360 return result;
1361 }
1362
1363 // asMap()
1364 // -------------------------------------------------------------------------
1365
1366 /**
1367 * Returns a new map object that contains all key-value pairs of the
1368 * specified string. <br>
1369 * The separator between the elements is assumed to be "," and "=" between
1370 * key and value.
1371 *
1372 * <p>
1373 * Example:<br> "main=Fred,support1=John,support2=Stella,manager=Oscar"
1374 * </p>
1375 *
1376 * <p>
1377 * <b>Be aware that all leading and trailing whitespaces of keys and values
1378 * will be removed!</b>
1379 * </p>
1380 *
1381 * @param str The string with the list of key-value pairs
1382 *
1383 * @return
1384 */
1385 public Map asMap(String str) {
1386 return this.toMap(str, null, null, null);
1387 }
1388
1389 // asMap()
1390 // -------------------------------------------------------------------------
1391
1392 /**
1393 * Returns a new map object that contains all key-value pairs of the
1394 * specified string. <br>
1395 * The separator between the keys and values is assumed to be "=".
1396 *
1397 * <p>
1398 * <b>Be aware that all leading and trailing whitespaces of keys and values
1399 * will be removed!</b>
1400 * </p>
1401 *
1402 * @param str The string that contains the list of key-value pairs
1403 * @param elementSeparator The separator between the elements of the list
1404 *
1405 * @return
1406 */
1407 public Map asMap(String str, String elementSeparator) {
1408 return this.toMap(str, elementSeparator, null, null);
1409 }
1410
1411 // asMap()
1412 // -------------------------------------------------------------------------
1413
1414 /**
1415 * Returns a new map object that contains all key-value pairs of the
1416 * specified string.
1417 *
1418 * <p>
1419 * <b>Be aware that all leading and trailing whitespaces of keys and values
1420 * will be removed!</b>
1421 * </p>
1422 *
1423 * @param str The string that contains the list of key-value pairs
1424 * @param elementSeparator The separator between the elements of the list
1425 * @param keyValueSeparator The separator between the keys and values
1426 *
1427 * @return
1428 */
1429 public Map asMap(String str, String elementSeparator,
1430 String keyValueSeparator) {
1431 return this.toMap(str, elementSeparator, keyValueSeparator, null);
1432 }
1433
1434 // asMap()
1435 // -------------------------------------------------------------------------
1436
1437 /**
1438 * Returns the given map object with all key-value pairs of the specified
1439 * string added to it. <br>
1440 * The separator between the keys and values is assumed to be "=".
1441 *
1442 * <p>
1443 * <b>Be aware that all leading and trailing whitespaces of keys and values
1444 * will be removed!</b>
1445 * </p>
1446 *
1447 * @param str The string that contains the list of key-value pairs
1448 * @param elementSeparator The separator between the elements of the list
1449 * @param map The map to which the key-value pairs are added
1450 *
1451 * @return
1452 */
1453 public Map toMap(String str, String elementSeparator, Map map) {
1454 return this.toMap(str, elementSeparator, null, map);
1455 }
1456
1457 // toMap()
1458 // -------------------------------------------------------------------------
1459
1460 /**
1461 * Adds all key-value pairs of the given string to the specified map. <br>
1462 * The separator between the elements is assumed to be "," and "=" between
1463 * key and value.
1464 *
1465 * <p>
1466 * <b>Be aware that all leading and trailing whitespaces of keys and values
1467 * will be removed!</b>
1468 * </p>
1469 *
1470 * @param str The string that contains the list of key-value pairs
1471 * @param map The map to which the key-value pairs are added
1472 *
1473 * @return
1474 */
1475 public Map toMap(String str, Map map) {
1476 return this.toMap(str, null, null, map);
1477 }
1478
1479 // toMap()
1480 // -------------------------------------------------------------------------
1481
1482 /**
1483 * Adds all key-value pairs of the given string to a new properties object. <br>
1484 * The separator between the elements is assumed to be "," and "=" between
1485 * key and value.
1486 *
1487 * <p>
1488 * <b>Be aware that all leading and trailing whitespaces of keys and values
1489 * will be removed!</b>
1490 * </p>
1491 *
1492 * @param str The string that contains the list of key-value pairs
1493 *
1494 * @return
1495 */
1496 public Properties asProperties(String str) {
1497 return this.toProperties(str, null);
1498 }
1499
1500 // asProperties()
1501 // -------------------------------------------------------------------------
1502
1503 /**
1504 * Adds all key-value pairs of the given string to the specified
1505 * properties. <br>
1506 * The separator between the elements is assumed to be "," and "=" between
1507 * key and value.
1508 *
1509 * <p>
1510 * <b>Be aware that all leading and trailing whitespaces of keys and values
1511 * will be removed!</b>
1512 * </p>
1513 *
1514 * @param str The string that contains the list of key-value pairs
1515 * @param properties The properties where the key-value pairs should be
1516 * added
1517 *
1518 * @return
1519 */
1520 public Properties toProperties(String str, Properties properties) {
1521 Properties props = (properties == null) ? new Properties() : properties;
1522
1523 return (Properties) this.toMap(str, null, null, props);
1524 }
1525
1526 // toProperties()
1527 // -------------------------------------------------------------------------
1528 // =========================================================================
1529 // PROTECTED INSTANCE METHODS
1530 // =========================================================================
1531
1532 /**
1533 * Cuts off all leading and trailing occurences of separator in text.
1534 *
1535 * @param text
1536 * @param separator
1537 *
1538 * @return
1539 */
1540 protected String trimSeparator(String text, String separator) {
1541 int sepLen = separator.length();
1542
1543 while (text.startsWith(separator)) {
1544 text = text.substring(separator.length());
1545 }
1546
1547 while (text.endsWith(separator)) {
1548 text = text.substring(0, text.length() - sepLen);
1549 }
1550
1551 return text;
1552 }
1553
1554 // trimSeparator()
1555 // -------------------------------------------------------------------------
1556
1557 /**
1558 * Returns an array of substrings of the given text. <br>
1559 * The separators between the substrings are the given delimiters. Each
1560 * character in the delimiter string is treated as a separator.
1561 *
1562 * @param text The string that should be splitted into substrings
1563 * @param delimiters All characters that should be recognized as a
1564 * separator or substrings
1565 * @param all If true, empty elements will be returned, otherwise thye are
1566 * skipped
1567 *
1568 * @return An array of substrings of the given text
1569 */
1570 protected String[] parts(String text, String delimiters, boolean all) {
1571 ArrayList result = null;
1572 StringTokenizer tokenizer = null;
1573
1574 if (text == null) {
1575 return null;
1576 }
1577
1578 if ((delimiters == null) || (delimiters.length() == 0)) {
1579 String[] resultArray = { text };
1580
1581 return resultArray;
1582 }
1583
1584 if (text.length() == 0) {
1585 return new String[0];
1586 } else {
1587 result = new ArrayList();
1588 tokenizer = new StringTokenizer(text, delimiters, all);
1589
1590 if (all) {
1591 this.collectParts(result, tokenizer, delimiters);
1592 } else {
1593 this.collectParts(result, tokenizer);
1594 }
1595 }
1596
1597 return (String[]) result.toArray(new String[0]);
1598 }
1599
1600 // parts()
1601 // -------------------------------------------------------------------------
1602 protected void collectParts(List list, StringTokenizer tokenizer) {
1603 while (tokenizer.hasMoreTokens()) {
1604 list.add(tokenizer.nextToken());
1605 }
1606 }
1607
1608 // collectParts()
1609 // -------------------------------------------------------------------------
1610 protected void collectParts(List list, StringTokenizer tokenizer,
1611 String delimiter) {
1612 String token;
1613 boolean lastWasDelimiter = false;
1614
1615 while (tokenizer.hasMoreTokens()) {
1616 token = tokenizer.nextToken();
1617
1618 if (delimiter.indexOf(token) >= 0) {
1619 if (lastWasDelimiter) {
1620 list.add("");
1621 }
1622
1623 lastWasDelimiter = true;
1624 } else {
1625 list.add(token);
1626 lastWasDelimiter = false;
1627 }
1628 }
1629 }
1630
1631 // collectParts()
1632 // -------------------------------------------------------------------------
1633
1634 /**
1635 * Returns the given text split up into an array of strings, at the
1636 * occurrances of the separator string. In contrary to method parts() the
1637 * separator is a one or many character sequence delimiter. That is, only
1638 * the exact sequence of the characters in separator identifies the end
1639 * of a substring. Parameter all defines whether empty strings between
1640 * consecutive separators are added to the result or not.
1641 *
1642 * @param text The text to be split up
1643 * @param separator The string that separates the substrings
1644 * @param all If true, empty strings are added, otherwise skipped
1645 *
1646 * @return An array of substrings not containing any separator anymore
1647 *
1648 * @see #parts(String, String, boolean)
1649 */
1650 protected String[] substrings(String text, String separator, boolean all) {
1651 int index = 0;
1652 int start = 0;
1653 int sepLen = 0;
1654 int strLen = 0;
1655 String str = text;
1656 ArrayList strings = new ArrayList();
1657
1658 if (text == null) {
1659 return new String[0];
1660 }
1661
1662 if ((separator == null) || (separator.length() == 0)) {
1663 if (text.length() == 0) {
1664 return new String[0];
1665 }
1666
1667 String[] resultArray = { text };
1668
1669 return resultArray;
1670 }
1671
1672 if (!all) {
1673 str = this.trimSeparator(text, separator);
1674 }
1675
1676 strLen = str.length();
1677
1678 if (strLen > 0) {
1679 sepLen = separator.length();
1680 index = str.indexOf(separator, start);
1681
1682 while (index >= 0) {
1683 if (all) {
1684 if (index > 0) {
1685 strings.add(str.substring(start, index));
1686 }
1687 } else {
1688 if (index > (start + sepLen)) {
1689 strings.add(str.substring(start, index));
1690 }
1691 }
1692
1693 start = index + sepLen;
1694 index = str.indexOf(separator, start);
1695 }
1696
1697 if (start < strLen) {
1698 strings.add(str.substring(start));
1699 }
1700 }
1701
1702 return (String[]) strings.toArray(new String[0]);
1703 }
1704
1705 // substrings()
1706 // -------------------------------------------------------------------------
1707 protected String padCh(String str, int len, char ch, boolean left) {
1708 StringBuffer buffer = null;
1709 int missing = len - str.length();
1710
1711 if (missing <= 0) {
1712 return str;
1713 }
1714
1715 buffer = new StringBuffer(len);
1716
1717 if (!left) {
1718 buffer.append(str);
1719 }
1720
1721 for (int i = 1; i <= missing; i++) {
1722 buffer.append(ch);
1723 }
1724
1725 if (left) {
1726 buffer.append(str);
1727 }
1728
1729 return buffer.toString();
1730 }
1731
1732 // padCh()
1733 // -------------------------------------------------------------------------
1734 protected int indexOfString(String[] strArray, String searchStr,
1735 boolean ignoreCase) {
1736 if ((strArray == null) || (strArray.length == 0)) {
1737 return -1;
1738 }
1739
1740 boolean found = false;
1741
1742 for (int i = 0; i < strArray.length; i++) {
1743 if (strArray[i] == null) {
1744 if (searchStr == null) {
1745 found = true;
1746 }
1747 } else {
1748 if (ignoreCase) {
1749 found = strArray[i].equalsIgnoreCase(searchStr);
1750 } else {
1751 found = strArray[i].equals(searchStr);
1752 }
1753 }
1754
1755 if (found) {
1756 return i;
1757 }
1758 }
1759
1760 return -1;
1761 }
1762
1763 // indexOfString()
1764 // -------------------------------------------------------------------------
1765
1766 /**
1767 * Returns the substring of the given string that comes before the first
1768 * occurance of the specified separator. If the string starts with a
1769 * separator, the result will be an empty string. If the string doesn't
1770 * contain the separator the method returns null or the whole string,
1771 * depending on the returnNull flag.
1772 *
1773 * @param str The string of which the prefix is desired
1774 * @param separator Separates the prefix from the rest of the string
1775 * @param returnNull Specifies if null will be returned if no separator is
1776 * found
1777 *
1778 * @return
1779 */
1780 protected String prefix(String str, String separator, boolean returnNull) {
1781 if (str == null) {
1782 return null;
1783 }
1784
1785 if (separator == null) {
1786 return (returnNull ? null : str);
1787 }
1788
1789 int index = str.indexOf(separator);
1790
1791 if (index >= 0) {
1792 return str.substring(0, index);
1793 } else {
1794 return (returnNull ? null : str);
1795 }
1796 }
1797
1798 // prefix()
1799 // -------------------------------------------------------------------------
1800
1801 /**
1802 * Returns the substring of the given string that comes after the first
1803 * occurance of the specified separator. If the string ends with a
1804 * separator, the result will be an empty string. If the string doesn't
1805 * contain the separator the method returns null or the whole string,
1806 * depending on the returnNull flag.
1807 *
1808 * @param str The string of which the suffix is desired
1809 * @param separator Separates the suffix from the rest of the string
1810 * @param returnNull Specifies if null will be returned if no separator is
1811 * found
1812 *
1813 * @return
1814 */
1815 protected String suffix(String str, String separator, boolean returnNull) {
1816 if (str == null) {
1817 return null;
1818 }
1819
1820 if (separator == null) {
1821 return (returnNull ? null : str);
1822 }
1823
1824 int index = str.indexOf(separator);
1825
1826 if (index >= 0) {
1827 return str.substring(index + separator.length());
1828 } else {
1829 return (returnNull ? null : str);
1830 }
1831 }
1832
1833 // suffix()
1834 // -------------------------------------------------------------------------
1835
1836 /**
1837 * Removes the given strings from the array. If removeStrings is null it
1838 * means that all null values are removed from the first array.
1839 *
1840 * @param strings
1841 * @param removeStrings
1842 *
1843 * @return
1844 */
1845 protected String[] removeFromStringArray(String[] strings,
1846 String[] removeStrings) {
1847 List list;
1848 boolean remains;
1849 list = new ArrayList(strings.length);
1850
1851 for (int i = 0; i < strings.length; i++) {
1852 if (removeStrings == null) {
1853 remains = strings[i] != null;
1854 } else {
1855 remains = !this.contains(removeStrings, strings[i]);
1856 }
1857
1858 if (remains) {
1859 list.add(strings[i]);
1860 }
1861 }
1862
1863 return (String[]) list.toArray(new String[list.size()]);
1864 }
1865
1866 // removeFromStringArray()
1867 // -------------------------------------------------------------------------
1868 }
1869
1870
1871 // class StringUtil