1 /* ====================================================================
2 * The Apache Software License, Version 1.1
3 *
4 * Copyright (c) 2002 The Apache Software Foundation. All rights
5 * reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * 3. The end-user documentation included with the redistribution, if
20 * any, must include the following acknowledgement:
21 * "This product includes software developed by the
22 * Apache Software Foundation (http://www.codehaus.org/)."
23 * Alternately, this acknowledgement may appear in the software itself,
24 * if and wherever such third-party acknowledgements normally appear.
25 *
26 * 4. The names "The Jakarta Project", "Commons", and "Apache Software
27 * Foundation" must not be used to endorse or promote products derived
28 * from this software without prior written permission. For written
29 * permission, please contact codehaus@codehaus.org.
30 *
31 * 5. Products derived from this software may not be called "Apache"
32 * nor may "Apache" appear in their names without prior written
33 * permission of the Apache Software Foundation.
34 *
35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46 * SUCH DAMAGE.
47 * ====================================================================
48 *
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Apache Software Foundation. For more
51 * information on the Apache Software Foundation, please see
52 * <http://www.codehaus.org/>.
53 */
54 package org.codehaus.plexus.util;
55
56 import java.util.Arrays;
57 import java.util.Iterator;
58 import java.util.Locale;
59 import java.util.Map;
60 import java.util.Objects;
61 import java.util.StringTokenizer;
62
63 /**
64 * <p>
65 * Common <code>String</code> manipulation routines.
66 * </p>
67 * <p>
68 * Originally from <a href="http://jakarta.apache.org/turbine/">Turbine</a> and the GenerationJavaCore library.
69 * </p>
70 *
71 * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
72 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
73 * @author <a href="mailto:gcoladonato@yahoo.com">Greg Coladonato</a>
74 * @author <a href="mailto:bayard@generationjava.com">Henri Yandell</a>
75 * @author <a href="mailto:ed@codehaus.org">Ed Korthof</a>
76 * @author <a href="mailto:rand_mcneely@yahoo.com">Rand McNeely</a>
77 * @author Stephen Colebourne
78 * @author <a href="mailto:fredrik@westermarck.com">Fredrik Westermarck</a>
79 * @author Holger Krauth
80 * @author <a href="mailto:alex@purpletech.com">Alexander Day Chaffee</a>
81 * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
82 * @since 1.0
83 *
84 */
85 public class StringUtils {
86 /**
87 * <p>
88 * <code>StringUtils</code> instances should NOT be constructed in standard programming. Instead, the class should
89 * be used as <code>StringUtils.trim(" foo ");</code>.
90 * </p>
91 * <p>
92 * This constructor is public to permit tools that require a JavaBean manager to operate.
93 * </p>
94 */
95 public StringUtils() {}
96
97 // Empty
98 // --------------------------------------------------------------------------
99
100 /**
101 * <p>
102 * Removes control characters, including whitespace, from both ends of this String, handling <code>null</code> by
103 * returning an empty String.
104 * </p>
105 *
106 * @see java.lang.String#trim()
107 * @param str the String to check
108 * @return the trimmed text (never <code>null</code>)
109 */
110 public static String clean(String str) {
111 return (str == null ? "" : str.trim());
112 }
113
114 /**
115 * <p>
116 * Removes control characters, including whitespace, from both ends of this String, handling <code>null</code> by
117 * returning <code>null</code>.
118 * </p>
119 *
120 * @see java.lang.String#trim()
121 * @param str the String to check
122 * @return the trimmed text (or <code>null</code>)
123 */
124 public static String trim(String str) {
125 return (str == null ? null : str.trim());
126 }
127
128 /**
129 * <p>
130 * Deletes all whitespaces from a String.
131 * </p>
132 * <p>
133 * Whitespace is defined by {@link Character#isWhitespace(char)}.
134 * </p>
135 *
136 * @param str String target to delete whitespace from
137 * @return the String without whitespaces
138 */
139 public static String deleteWhitespace(String str) {
140 StringBuilder buffer = new StringBuilder();
141 int sz = str.length();
142 for (int i = 0; i < sz; i++) {
143 if (!Character.isWhitespace(str.charAt(i))) {
144 buffer.append(str.charAt(i));
145 }
146 }
147 return buffer.toString();
148 }
149
150 /**
151 * Checks if a String is non <code>null</code> and is not empty (<code>length > 0</code>).
152 *
153 * @param str the String to check
154 * @return true if the String is non-null, and not length zero
155 */
156 public static boolean isNotEmpty(String str) {
157 return ((str != null) && (!str.isEmpty()));
158 }
159
160 /**
161 * Checks if a String is <code>null</code> or empty.
162 * <p>
163 * <strong>Note:</strong> In releases prior 3.5.0, this method trimmed the input string such that it worked
164 * the same as {@link #isBlank(String)}. Since release 3.5.0 it no longer returns {@code true} for strings
165 * containing only whitespace characters.
166 *
167 * @param str the String to check
168 * @return <code>true</code> if the String is <code>null</code>, or length zero
169 */
170 public static boolean isEmpty(String str) {
171 return ((str == null) || (str.isEmpty()));
172 }
173
174 /**
175 * <p>
176 * Checks if a String is whitespace, empty ("") or null.
177 * </p>
178 *
179 * <pre>
180 * StringUtils.isBlank(null) = true
181 * StringUtils.isBlank("") = true
182 * StringUtils.isBlank(" ") = true
183 * StringUtils.isBlank("bob") = false
184 * StringUtils.isBlank(" bob ") = false
185 * </pre>
186 *
187 * @param str the String to check, may be null
188 * @return <code>true</code> if the String is null, empty or whitespace
189 * @since 1.5.2
190 */
191 public static boolean isBlank(String str) {
192 int strLen;
193 if (str == null || (strLen = str.length()) == 0) {
194 return true;
195 }
196 for (int i = 0; i < strLen; i++) {
197 if (!Character.isWhitespace(str.charAt(i))) {
198 return false;
199 }
200 }
201 return true;
202 }
203
204 /**
205 * <p>
206 * Checks if a String is not empty (""), not null and not whitespace only.
207 * </p>
208 *
209 * <pre>
210 * StringUtils.isNotBlank(null) = false
211 * StringUtils.isNotBlank("") = false
212 * StringUtils.isNotBlank(" ") = false
213 * StringUtils.isNotBlank("bob") = true
214 * StringUtils.isNotBlank(" bob ") = true
215 * </pre>
216 *
217 * @param str the String to check, may be null
218 * @return <code>true</code> if the String is not empty and not null and not whitespace
219 * @since 1.5.2
220 */
221 public static boolean isNotBlank(String str) {
222 return !StringUtils.isBlank(str);
223 }
224
225 // Equals and IndexOf
226 // --------------------------------------------------------------------------
227
228 /**
229 * <p>
230 * Compares two Strings, returning <code>true</code> if they are equal.
231 * </p>
232 * <p>
233 * <code>null</code>s are handled without exceptions. Two <code>null</code> references are considered to be equal.
234 * The comparison is case sensitive.
235 * </p>
236 *
237 * @see java.lang.String#equals(Object)
238 * @param str1 the first string
239 * @param str2 the second string
240 * @return <code>true</code> if the Strings are equal, case sensitive, or both <code>null</code>
241 * @see Objects#equals(Object, Object)
242 */
243 @Deprecated
244 public static boolean equals(String str1, String str2) {
245 return Objects.equals(str1, str2);
246 }
247
248 /**
249 * <p>
250 * Compares two Strings, returning <code>true</code> if they are equal ignoring the case.
251 * </p>
252 * <p>
253 * <code>Nulls</code> are handled without exceptions. Two <code>null</code> references are considered equal.
254 * Comparison is case insensitive.
255 * </p>
256 *
257 * @see java.lang.String#equalsIgnoreCase(String)
258 * @param str1 the first string
259 * @param str2 the second string
260 * @return <code>true</code> if the Strings are equal, case insensitive, or both <code>null</code>
261 */
262 public static boolean equalsIgnoreCase(String str1, String str2) {
263 return (str1 == null ? str2 == null : str1.equalsIgnoreCase(str2));
264 }
265
266 /**
267 * <p>
268 * Find the first index of any of a set of potential substrings.
269 * </p>
270 * <p>
271 * <code>null</code> String will return <code>-1</code>.
272 * </p>
273 *
274 * @param str the String to check
275 * @param searchStrs the Strings to search for
276 * @return the first index of any of the searchStrs in str
277 * @throws NullPointerException if any of searchStrs[i] is <code>null</code>
278 */
279 public static int indexOfAny(String str, String[] searchStrs) {
280 if ((str == null) || (searchStrs == null)) {
281 return -1;
282 }
283 int sz = searchStrs.length;
284
285 // String's can't have a MAX_VALUEth index.
286 int ret = Integer.MAX_VALUE;
287
288 int tmp;
289 for (String searchStr : searchStrs) {
290 tmp = str.indexOf(searchStr);
291 if (tmp == -1) {
292 continue;
293 }
294
295 if (tmp < ret) {
296 ret = tmp;
297 }
298 }
299
300 return (ret == Integer.MAX_VALUE) ? -1 : ret;
301 }
302
303 /**
304 * <p>
305 * Find the latest index of any of a set of potential substrings.
306 * </p>
307 * <p>
308 * <code>null</code> string will return <code>-1</code>.
309 * </p>
310 *
311 * @param str the String to check
312 * @param searchStrs the Strings to search for
313 * @return the last index of any of the Strings
314 * @throws NullPointerException if any of searchStrs[i] is <code>null</code>
315 */
316 public static int lastIndexOfAny(String str, String[] searchStrs) {
317 if ((str == null) || (searchStrs == null)) {
318 return -1;
319 }
320 int ret = -1;
321 int tmp;
322 for (String searchStr : searchStrs) {
323 tmp = str.lastIndexOf(searchStr);
324 if (tmp > ret) {
325 ret = tmp;
326 }
327 }
328 return ret;
329 }
330
331 // Substring
332 // --------------------------------------------------------------------------
333
334 /**
335 * <p>
336 * Gets a substring from the specified string avoiding exceptions.
337 * </p>
338 * <p>
339 * A negative start position can be used to start <code>n</code> characters from the end of the String.
340 * </p>
341 *
342 * @param str the String to get the substring from
343 * @param start the position to start from, negative means count back from the end of the String by this many
344 * characters
345 * @return substring from start position
346 */
347 public static String substring(String str, int start) {
348 if (str == null) {
349 return null;
350 }
351
352 // handle negatives, which means last n characters
353 if (start < 0) {
354 start = str.length() + start; // remember start is negative
355 }
356
357 if (start < 0) {
358 start = 0;
359 }
360 if (start > str.length()) {
361 return "";
362 }
363
364 return str.substring(start);
365 }
366
367 /**
368 * <p>
369 * Gets a substring from the specified String avoiding exceptions.
370 * </p>
371 * <p>
372 * A negative start position can be used to start/end <code>n</code> characters from the end of the String.
373 * </p>
374 *
375 * @param str the String to get the substring from
376 * @param start the position to start from, negative means count back from the end of the string by this many
377 * characters
378 * @param end the position to end at (exclusive), negative means count back from the end of the String by this many
379 * characters
380 * @return substring from start position to end position
381 */
382 public static String substring(String str, int start, int end) {
383 if (str == null) {
384 return null;
385 }
386
387 // handle negatives
388 if (end < 0) {
389 end = str.length() + end; // remember end is negative
390 }
391 if (start < 0) {
392 start = str.length() + start; // remember start is negative
393 }
394
395 // check length next
396 if (end > str.length()) {
397 // check this works.
398 end = str.length();
399 }
400
401 // if start is greater than end, return ""
402 if (start > end) {
403 return "";
404 }
405
406 if (start < 0) {
407 start = 0;
408 }
409 if (end < 0) {
410 end = 0;
411 }
412
413 return str.substring(start, end);
414 }
415
416 /**
417 * <p>
418 * Gets the leftmost <code>n</code> characters of a String.
419 * </p>
420 * <p>
421 * If <code>n</code> characters are not available, or the String is <code>null</code>, the String will be returned
422 * without an exception.
423 * </p>
424 *
425 * @param str the String to get the leftmost characters from
426 * @param len the length of the required String
427 * @return the leftmost characters
428 * @throws IllegalArgumentException if len is less than zero
429 */
430 public static String left(String str, int len) {
431 if (len < 0) {
432 throw new IllegalArgumentException("Requested String length " + len + " is less than zero");
433 }
434 if ((str == null) || (str.length() <= len)) {
435 return str;
436 } else {
437 return str.substring(0, len);
438 }
439 }
440
441 /**
442 * <p>
443 * Gets the rightmost <code>n</code> characters of a String.
444 * </p>
445 * <p>
446 * If <code>n</code> characters are not available, or the String is <code>null</code>, the String will be returned
447 * without an exception.
448 * </p>
449 *
450 * @param str the String to get the rightmost characters from
451 * @param len the length of the required String
452 * @return the leftmost characters
453 * @throws IllegalArgumentException if len is less than zero
454 */
455 public static String right(String str, int len) {
456 if (len < 0) {
457 throw new IllegalArgumentException("Requested String length " + len + " is less than zero");
458 }
459 if ((str == null) || (str.length() <= len)) {
460 return str;
461 } else {
462 return str.substring(str.length() - len);
463 }
464 }
465
466 /**
467 * <p>
468 * Gets <code>n</code> characters from the middle of a String.
469 * </p>
470 * <p>
471 * If <code>n</code> characters are not available, the remainder of the String will be returned without an
472 * exception. If the String is <code>null</code>, <code>null</code> will be returned.
473 * </p>
474 *
475 * @param str the String to get the characters from
476 * @param pos the position to start from
477 * @param len the length of the required String
478 * @return the leftmost characters
479 * @throws IndexOutOfBoundsException if pos is out of bounds
480 * @throws IllegalArgumentException if len is less than zero
481 */
482 public static String mid(String str, int pos, int len) {
483 if ((pos < 0) || ((str != null) && (pos > str.length()))) {
484 throw new StringIndexOutOfBoundsException("String index " + pos + " is out of bounds");
485 }
486 if (len < 0) {
487 throw new IllegalArgumentException("Requested String length " + len + " is less than zero");
488 }
489 if (str == null) {
490 return null;
491 }
492 if (str.length() <= (pos + len)) {
493 return str.substring(pos);
494 } else {
495 return str.substring(pos, pos + len);
496 }
497 }
498
499 // Splitting
500 // --------------------------------------------------------------------------
501
502 /**
503 * <p>
504 * Splits the provided text into a array, using whitespace as the separator.
505 * </p>
506 * <p>
507 * The separator is not included in the returned String array.
508 * </p>
509 *
510 * @param str the String to parse
511 * @return an array of parsed Strings
512 */
513 public static String[] split(String str) {
514 return split(str, null, -1);
515 }
516
517 /**
518 * @param text The string to parse.
519 * @param separator Characters used as the delimiters. If <code>null</code>, splits on whitespace.
520 * @return an array of parsed Strings
521 */
522 public static String[] split(String text, String separator) {
523 return split(text, separator, -1);
524 }
525
526 /**
527 * <p>
528 * Splits the provided text into a array, based on a given separator.
529 * </p>
530 * <p>
531 * The separator is not included in the returned String array. The maximum number of splits to perform can be
532 * controlled. A <code>null</code> separator will cause parsing to be on whitespace.
533 * </p>
534 * <p>
535 * This is useful for quickly splitting a String directly into an array of tokens, instead of an enumeration of
536 * tokens (as <code>StringTokenizer</code> does).
537 * </p>
538 *
539 * @param str The string to parse.
540 * @param separator Characters used as the delimiters. If <code>null</code>, splits on whitespace.
541 * @param max The maximum number of elements to include in the array. A zero or negative value implies no limit.
542 * @return an array of parsed Strings
543 */
544 public static String[] split(String str, String separator, int max) {
545 StringTokenizer tok;
546 if (separator == null) {
547 // Null separator means we're using StringTokenizer's default
548 // delimiter, which comprises all whitespace characters.
549 tok = new StringTokenizer(str);
550 } else {
551 tok = new StringTokenizer(str, separator);
552 }
553
554 int listSize = tok.countTokens();
555 if ((max > 0) && (listSize > max)) {
556 listSize = max;
557 }
558
559 String[] list = new String[listSize];
560 int i = 0;
561 int lastTokenBegin;
562 int lastTokenEnd = 0;
563 while (tok.hasMoreTokens()) {
564 if ((max > 0) && (i == listSize - 1)) {
565 // In the situation where we hit the max yet have
566 // tokens left over in our input, the last list
567 // element gets all remaining text.
568 String endToken = tok.nextToken();
569 lastTokenBegin = str.indexOf(endToken, lastTokenEnd);
570 list[i] = str.substring(lastTokenBegin);
571 break;
572 } else {
573 list[i] = tok.nextToken();
574 lastTokenBegin = str.indexOf(list[i], lastTokenEnd);
575 lastTokenEnd = lastTokenBegin + list[i].length();
576 }
577 i++;
578 }
579 return list;
580 }
581
582 // Joining
583 // --------------------------------------------------------------------------
584 /**
585 * <p>
586 * Concatenates elements of an array into a single String.
587 * </p>
588 * <p>
589 * The difference from join is that concatenate has no delimiter.
590 * </p>
591 *
592 * @param array the array of values to concatenate.
593 * @return the concatenated string.
594 */
595 public static String concatenate(Object[] array) {
596 return join(array, "");
597 }
598
599 /**
600 * <p>
601 * Joins the elements of the provided array into a single String containing the provided list of elements.
602 * </p>
603 * <p>
604 * No delimiter is added before or after the list. A <code>null</code> separator is the same as a blank String.
605 * </p>
606 *
607 * @param array the array of values to join together
608 * @param separator the separator character to use
609 * @return the joined String
610 */
611 public static String join(Object[] array, String separator) {
612 if (separator == null) {
613 separator = "";
614 }
615 int arraySize = array.length;
616 int bufSize = (arraySize == 0 ? 0 : (array[0].toString().length() + separator.length()) * arraySize);
617 StringBuilder buf = new StringBuilder(bufSize);
618
619 for (int i = 0; i < arraySize; i++) {
620 if (i > 0) {
621 buf.append(separator);
622 }
623 buf.append(array[i]);
624 }
625 return buf.toString();
626 }
627
628 /**
629 * <p>
630 * Joins the elements of the provided <code>Iterator</code> into a single String containing the provided elements.
631 * </p>
632 * <p>
633 * No delimiter is added before or after the list. A <code>null</code> separator is the same as a blank String.
634 * </p>
635 *
636 * @param iterator the <code>Iterator</code> of values to join together
637 * @param separator the separator character to use
638 * @return the joined String
639 */
640 public static String join(Iterator<?> iterator, String separator) {
641 if (separator == null) {
642 separator = "";
643 }
644 StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small
645 while (iterator.hasNext()) {
646 buf.append(iterator.next());
647 if (iterator.hasNext()) {
648 buf.append(separator);
649 }
650 }
651 return buf.toString();
652 }
653
654 // Replacing
655 // --------------------------------------------------------------------------
656
657 /**
658 * <p>
659 * Replace a char with another char inside a larger String, once.
660 * </p>
661 * <p>
662 * A <code>null</code> reference passed to this method is a no-op.
663 * </p>
664 *
665 * @see #replace(String text, char repl, char with, int max)
666 * @param text text to search and replace in
667 * @param repl char to search for
668 * @param with char to replace with
669 * @return the text with any replacements processed
670 */
671 public static String replaceOnce(String text, char repl, char with) {
672 return replace(text, repl, with, 1);
673 }
674
675 /**
676 * <p>
677 * Replace all occurrences of a char within another char.
678 * </p>
679 * <p>
680 * A <code>null</code> reference passed to this method is a no-op.
681 * </p>
682 *
683 * @see #replace(String text, char repl, char with, int max)
684 * @param text text to search and replace in
685 * @param repl char to search for
686 * @param with char to replace with
687 * @return the text with any replacements processed
688 */
689 public static String replace(String text, char repl, char with) {
690 return replace(text, repl, with, -1);
691 }
692
693 /**
694 * <p>
695 * Replace a char with another char inside a larger String, for the first <code>max</code> values of the search
696 * char.
697 * </p>
698 * <p>
699 * A <code>null</code> reference passed to this method is a no-op.
700 * </p>
701 *
702 * @param text text to search and replace in
703 * @param repl char to search for
704 * @param with char to replace with
705 * @param max maximum number of values to replace, or <code>-1</code> if no maximum
706 * @return the text with any replacements processed
707 */
708 public static String replace(String text, char repl, char with, int max) {
709 return replace(text, String.valueOf(repl), String.valueOf(with), max);
710 }
711
712 /**
713 * <p>
714 * Replace a String with another String inside a larger String, once.
715 * </p>
716 * <p>
717 * A <code>null</code> reference passed to this method is a no-op.
718 * </p>
719 *
720 * @see #replace(String text, String repl, String with, int max)
721 * @param text text to search and replace in
722 * @param repl String to search for
723 * @param with String to replace with
724 * @return the text with any replacements processed
725 */
726 public static String replaceOnce(String text, String repl, String with) {
727 return replace(text, repl, with, 1);
728 }
729
730 /**
731 * <p>
732 * Replace all occurrences of a String within another String.
733 * </p>
734 * <p>
735 * A <code>null</code> reference passed to this method is a no-op.
736 * </p>
737 *
738 * @see #replace(String text, String repl, String with, int max)
739 * @param text text to search and replace in
740 * @param repl String to search for
741 * @param with String to replace with
742 * @return the text with any replacements processed
743 */
744 public static String replace(String text, String repl, String with) {
745 return replace(text, repl, with, -1);
746 }
747
748 /**
749 * <p>
750 * Replace a String with another String inside a larger String, for the first <code>max</code> values of the search
751 * String.
752 * </p>
753 * <p>
754 * A <code>null</code> reference passed to this method is a no-op.
755 * </p>
756 *
757 * @param text text to search and replace in
758 * @param repl String to search for
759 * @param with String to replace with
760 * @param max maximum number of values to replace, or <code>-1</code> if no maximum
761 * @return the text with any replacements processed
762 */
763 public static String replace(String text, String repl, String with, int max) {
764 if ((text == null) || (repl == null) || (with == null) || (repl.length() == 0)) {
765 return text;
766 }
767
768 StringBuilder buf = new StringBuilder(text.length());
769 int start = 0, end;
770 while ((end = text.indexOf(repl, start)) != -1) {
771 buf.append(text, start, end).append(with);
772 start = end + repl.length();
773
774 if (--max == 0) {
775 break;
776 }
777 }
778 buf.append(text, start, text.length());
779 return buf.toString();
780 }
781
782 /**
783 * <p>
784 * Overlay a part of a String with another String.
785 * </p>
786 *
787 * @param text String to do overlaying in
788 * @param overlay String to overlay
789 * @param start int to start overlaying at
790 * @param end int to stop overlaying before
791 * @return String with overlayed text
792 * @throws NullPointerException if text or overlay is <code>null</code>
793 */
794 public static String overlayString(String text, String overlay, int start, int end) {
795 return new StringBuilder(start + overlay.length() + text.length() - end + 1)
796 .append(text, 0, start)
797 .append(overlay)
798 .append(text, end, text.length())
799 .toString();
800 }
801
802 // Centering
803 // --------------------------------------------------------------------------
804
805 /**
806 * <p>
807 * Center a String in a larger String of size <code>n</code>.
808 * </p>
809 * <p>
810 * Uses spaces as the value to buffer the String with. Equivalent to <code>center(str, size, " ")</code>.
811 * </p>
812 *
813 * @param str String to center
814 * @param size int size of new String
815 * @return String containing centered String
816 * @throws NullPointerException if str is <code>null</code>
817 */
818 public static String center(String str, int size) {
819 return center(str, size, " ");
820 }
821
822 /**
823 * <p>
824 * Center a String in a larger String of size <code>n</code>.
825 * </p>
826 * <p>
827 * Uses a supplied String as the value to buffer the String with.
828 * </p>
829 *
830 * @param str String to center
831 * @param size int size of new String
832 * @param delim String to buffer the new String with
833 * @return String containing centered String
834 * @throws NullPointerException if str or delim is <code>null</code>
835 * @throws ArithmeticException if delim is the empty String
836 */
837 public static String center(String str, int size, String delim) {
838 int sz = str.length();
839 int p = size - sz;
840 if (p < 1) {
841 return str;
842 }
843 str = leftPad(str, sz + p / 2, delim);
844 str = rightPad(str, size, delim);
845 return str;
846 }
847
848 // Chomping
849 // --------------------------------------------------------------------------
850
851 /**
852 * <p>
853 * Remove the last newline, and everything after it from a String.
854 * </p>
855 *
856 * @param str String to chomp the newline from
857 * @return String without chomped newline
858 * @throws NullPointerException if str is <code>null</code>
859 */
860 public static String chomp(String str) {
861 return chomp(str, "\n");
862 }
863
864 /**
865 * <p>
866 * Remove the last value of a supplied String, and everything after it from a String.
867 * </p>
868 *
869 * @param str String to chomp from
870 * @param sep String to chomp
871 * @return String without chomped ending
872 * @throws NullPointerException if str or sep is <code>null</code>
873 */
874 public static String chomp(String str, String sep) {
875 int idx = str.lastIndexOf(sep);
876 if (idx != -1) {
877 return str.substring(0, idx);
878 } else {
879 return str;
880 }
881 }
882
883 /**
884 * <p>
885 * Remove a newline if and only if it is at the end of the supplied String.
886 * </p>
887 *
888 * @param str String to chomp from
889 * @return String without chomped ending
890 * @throws NullPointerException if str is <code>null</code>
891 */
892 public static String chompLast(String str) {
893 return chompLast(str, "\n");
894 }
895
896 /**
897 * <p>
898 * Remove a value if and only if the String ends with that value.
899 * </p>
900 *
901 * @param str String to chomp from
902 * @param sep String to chomp
903 * @return String without chomped ending
904 * @throws NullPointerException if str or sep is <code>null</code>
905 */
906 public static String chompLast(String str, String sep) {
907 if (str.length() == 0) {
908 return str;
909 }
910 String sub = str.substring(str.length() - sep.length());
911 if (sep.equals(sub)) {
912 return str.substring(0, str.length() - sep.length());
913 } else {
914 return str;
915 }
916 }
917
918 /**
919 * <p>
920 * Remove everything and return the last value of a supplied String, and everything after it from a String.
921 * </p>
922 *
923 * @param str String to chomp from
924 * @param sep String to chomp
925 * @return String chomped
926 * @throws NullPointerException if str or sep is <code>null</code>
927 */
928 public static String getChomp(String str, String sep) {
929 int idx = str.lastIndexOf(sep);
930 if (idx == str.length() - sep.length()) {
931 return sep;
932 } else if (idx != -1) {
933 return str.substring(idx);
934 } else {
935 return "";
936 }
937 }
938
939 /**
940 * <p>
941 * Remove the first value of a supplied String, and everything before it from a String.
942 * </p>
943 *
944 * @param str String to chomp from
945 * @param sep String to chomp
946 * @return String without chomped beginning
947 * @throws NullPointerException if str or sep is <code>null</code>
948 */
949 public static String prechomp(String str, String sep) {
950 int idx = str.indexOf(sep);
951 if (idx != -1) {
952 return str.substring(idx + sep.length());
953 } else {
954 return str;
955 }
956 }
957
958 /**
959 * <p>
960 * Remove and return everything before the first value of a supplied String from another String.
961 * </p>
962 *
963 * @param str String to chomp from
964 * @param sep String to chomp
965 * @return String prechomped
966 * @throws NullPointerException if str or sep is <code>null</code>
967 */
968 public static String getPrechomp(String str, String sep) {
969 int idx = str.indexOf(sep);
970 if (idx != -1) {
971 return str.substring(0, idx + sep.length());
972 } else {
973 return "";
974 }
975 }
976
977 // Chopping
978 // --------------------------------------------------------------------------
979
980 /**
981 * <p>
982 * Remove the last character from a String.
983 * </p>
984 * <p>
985 * If the String ends in <code>\r\n</code>, then remove both of them.
986 * </p>
987 *
988 * @param str String to chop last character from
989 * @return String without last character
990 * @throws NullPointerException if str is <code>null</code>
991 */
992 public static String chop(String str) {
993 if ("".equals(str)) {
994 return "";
995 }
996 if (str.length() == 1) {
997 return "";
998 }
999 int lastIdx = str.length() - 1;
1000 String ret = str.substring(0, lastIdx);
1001 char last = str.charAt(lastIdx);
1002 if (last == '\n') {
1003 if (ret.charAt(lastIdx - 1) == '\r') {
1004 return ret.substring(0, lastIdx - 1);
1005 }
1006 }
1007 return ret;
1008 }
1009
1010 /**
1011 * <p>
1012 * Remove <code>\n</code> from end of a String if it's there. If a <code>\r</code> precedes it, then remove that
1013 * too.
1014 * </p>
1015 *
1016 * @param str String to chop a newline from
1017 * @return String without newline
1018 * @throws NullPointerException if str is <code>null</code>
1019 */
1020 public static String chopNewline(String str) {
1021 int lastIdx = str.length() - 1;
1022 char last = str.charAt(lastIdx);
1023 if (last == '\n') {
1024 if (str.charAt(lastIdx - 1) == '\r') {
1025 lastIdx--;
1026 }
1027 } else {
1028 lastIdx++;
1029 }
1030 return str.substring(0, lastIdx);
1031 }
1032
1033 // Conversion
1034 // --------------------------------------------------------------------------
1035
1036 // spec 3.10.6
1037 /**
1038 * <p>
1039 * Escapes any values it finds into their String form.
1040 * </p>
1041 * <p>
1042 * So a tab becomes the characters <code>'\\'</code> and <code>'t'</code>.
1043 * </p>
1044 *
1045 * @param str String to escape values in
1046 * @return String with escaped values
1047 * @throws NullPointerException if str is <code>null</code>
1048 */
1049 public static String escape(String str) {
1050 // improved with code from cybertiger@cyberiantiger.org
1051 // unicode from him, and default for < 32's.
1052 int sz = str.length();
1053 StringBuilder buffer = new StringBuilder(2 * sz);
1054 for (int i = 0; i < sz; i++) {
1055 char ch = str.charAt(i);
1056
1057 // handle unicode
1058 if (ch > 0xfff) {
1059 buffer.append("\\u" + Integer.toHexString(ch));
1060 } else if (ch > 0xff) {
1061 buffer.append("\\u0" + Integer.toHexString(ch));
1062 } else if (ch > 0x7f) {
1063 buffer.append("\\u00" + Integer.toHexString(ch));
1064 } else if (ch < 32) {
1065 switch (ch) {
1066 case '\b':
1067 buffer.append('\\');
1068 buffer.append('b');
1069 break;
1070 case '\n':
1071 buffer.append('\\');
1072 buffer.append('n');
1073 break;
1074 case '\t':
1075 buffer.append('\\');
1076 buffer.append('t');
1077 break;
1078 case '\f':
1079 buffer.append('\\');
1080 buffer.append('f');
1081 break;
1082 case '\r':
1083 buffer.append('\\');
1084 buffer.append('r');
1085 break;
1086 default:
1087 if (ch > 0xf) {
1088 buffer.append("\\u00" + Integer.toHexString(ch));
1089 } else {
1090 buffer.append("\\u000" + Integer.toHexString(ch));
1091 }
1092 break;
1093 }
1094 } else {
1095 switch (ch) {
1096 case '\'':
1097 buffer.append('\\');
1098 buffer.append('\'');
1099 break;
1100 case '"':
1101 buffer.append('\\');
1102 buffer.append('"');
1103 break;
1104 case '\\':
1105 buffer.append('\\');
1106 buffer.append('\\');
1107 break;
1108 default:
1109 buffer.append(ch);
1110 break;
1111 }
1112 }
1113 }
1114 return buffer.toString();
1115 }
1116
1117 // Padding
1118 // --------------------------------------------------------------------------
1119
1120 /**
1121 * <p>
1122 * Repeat a String <code>n</code> times to form a new string.
1123 * </p>
1124 *
1125 * @param str String to repeat
1126 * @param repeat number of times to repeat str
1127 * @return String with repeated String
1128 * @throws NegativeArraySizeException if <code>repeat < 0</code>
1129 * @throws NullPointerException if str is <code>null</code>
1130 */
1131 public static String repeat(String str, int repeat) {
1132 StringBuilder buffer = new StringBuilder(repeat * str.length());
1133 for (int i = 0; i < repeat; i++) {
1134 buffer.append(str);
1135 }
1136 return buffer.toString();
1137 }
1138
1139 /**
1140 * <p>
1141 * Right pad a String with spaces.
1142 * </p>
1143 * <p>
1144 * The String is padded to the size of <code>n</code>.
1145 * </p>
1146 *
1147 * @param str String to repeat
1148 * @param size number of times to repeat str
1149 * @return right padded String
1150 * @throws NullPointerException if str is <code>null</code>
1151 */
1152 public static String rightPad(String str, int size) {
1153 return rightPad(str, size, " ");
1154 }
1155
1156 /**
1157 * <p>
1158 * Right pad a String with a specified string.
1159 * </p>
1160 * <p>
1161 * The String is padded to the size of <code>n</code>.
1162 * </p>
1163 *
1164 * @param str String to pad out
1165 * @param size size to pad to
1166 * @param delim String to pad with
1167 * @return right padded String
1168 * @throws NullPointerException if str or delim is <code>null</code>
1169 * @throws ArithmeticException if delim is the empty String
1170 */
1171 public static String rightPad(String str, int size, String delim) {
1172 size = (size - str.length()) / delim.length();
1173 if (size > 0) {
1174 str += repeat(delim, size);
1175 }
1176 return str;
1177 }
1178
1179 /**
1180 * <p>
1181 * Left pad a String with spaces.
1182 * </p>
1183 * <p>
1184 * The String is padded to the size of <code>n</code>.
1185 * </p>
1186 *
1187 * @param str String to pad out
1188 * @param size size to pad to
1189 * @return left padded String
1190 * @throws NullPointerException if str or delim is <code>null</code>
1191 */
1192 public static String leftPad(String str, int size) {
1193 return leftPad(str, size, " ");
1194 }
1195
1196 /**
1197 * Left pad a String with a specified string. Pad to a size of n.
1198 *
1199 * @param str String to pad out
1200 * @param size size to pad to
1201 * @param delim String to pad with
1202 * @return left padded String
1203 * @throws NullPointerException if str or delim is null
1204 * @throws ArithmeticException if delim is the empty string
1205 */
1206 public static String leftPad(String str, int size, String delim) {
1207 size = (size - str.length()) / delim.length();
1208 if (size > 0) {
1209 str = repeat(delim, size) + str;
1210 }
1211 return str;
1212 }
1213
1214 // Stripping
1215 // --------------------------------------------------------------------------
1216
1217 /**
1218 * <p>
1219 * Remove whitespace from the front and back of a String.
1220 * </p>
1221 *
1222 * @param str the String to remove whitespace from
1223 * @return the stripped String
1224 */
1225 public static String strip(String str) {
1226 return strip(str, null);
1227 }
1228
1229 /**
1230 * <p>
1231 * Remove a specified String from the front and back of a String.
1232 * </p>
1233 * <p>
1234 * If whitespace is wanted to be removed, used the {@link #strip(java.lang.String)} method.
1235 * </p>
1236 *
1237 * @param str the String to remove a string from
1238 * @param delim the String to remove at start and end
1239 * @return the stripped String
1240 */
1241 public static String strip(String str, String delim) {
1242 str = stripStart(str, delim);
1243 return stripEnd(str, delim);
1244 }
1245
1246 /**
1247 * <p>
1248 * Strip whitespace from the front and back of every String in the array.
1249 * </p>
1250 *
1251 * @param strs the Strings to remove whitespace from
1252 * @return the stripped Strings
1253 */
1254 public static String[] stripAll(String[] strs) {
1255 return stripAll(strs, null);
1256 }
1257
1258 /**
1259 * <p>
1260 * Strip the specified delimiter from the front and back of every String in the array.
1261 * </p>
1262 *
1263 * @param strs the Strings to remove a String from
1264 * @param delimiter the String to remove at start and end
1265 * @return the stripped Strings
1266 */
1267 public static String[] stripAll(String[] strs, String delimiter) {
1268 if ((strs == null) || (strs.length == 0)) {
1269 return strs;
1270 }
1271 int sz = strs.length;
1272 String[] newArr = new String[sz];
1273 for (int i = 0; i < sz; i++) {
1274 newArr[i] = strip(strs[i], delimiter);
1275 }
1276 return newArr;
1277 }
1278
1279 /**
1280 * <p>
1281 * Strip any of a supplied String from the end of a String.
1282 * </p>
1283 * <p>
1284 * If the strip String is <code>null</code>, whitespace is stripped.
1285 * </p>
1286 *
1287 * @param str the String to remove characters from
1288 * @param strip the String to remove
1289 * @return the stripped String
1290 */
1291 public static String stripEnd(String str, String strip) {
1292 if (str == null) {
1293 return null;
1294 }
1295 int end = str.length();
1296
1297 if (strip == null) {
1298 while ((end != 0) && Character.isWhitespace(str.charAt(end - 1))) {
1299 end--;
1300 }
1301 } else {
1302 while ((end != 0) && (strip.indexOf(str.charAt(end - 1)) != -1)) {
1303 end--;
1304 }
1305 }
1306 return str.substring(0, end);
1307 }
1308
1309 /**
1310 * <p>
1311 * Strip any of a supplied String from the start of a String.
1312 * </p>
1313 * <p>
1314 * If the strip String is <code>null</code>, whitespace is stripped.
1315 * </p>
1316 *
1317 * @param str the String to remove characters from
1318 * @param strip the String to remove
1319 * @return the stripped String
1320 */
1321 public static String stripStart(String str, String strip) {
1322 if (str == null) {
1323 return null;
1324 }
1325
1326 int start = 0;
1327
1328 int sz = str.length();
1329
1330 if (strip == null) {
1331 while ((start != sz) && Character.isWhitespace(str.charAt(start))) {
1332 start++;
1333 }
1334 } else {
1335 while ((start != sz) && (strip.indexOf(str.charAt(start)) != -1)) {
1336 start++;
1337 }
1338 }
1339 return str.substring(start);
1340 }
1341
1342 // Case conversion
1343 // --------------------------------------------------------------------------
1344
1345 /**
1346 * <p>
1347 * Convert a String to upper case, <code>null</code> String returns <code>null</code>.
1348 * </p>
1349 *
1350 * @param str the String to uppercase
1351 * @return the upper cased String
1352 */
1353 public static String upperCase(String str) {
1354 if (str == null) {
1355 return null;
1356 }
1357 return str.toUpperCase();
1358 }
1359
1360 /**
1361 * <p>
1362 * Convert a String to lower case, <code>null</code> String returns <code>null</code>.
1363 * </p>
1364 *
1365 * @param str the string to lowercase
1366 * @return the lower cased String
1367 */
1368 public static String lowerCase(String str) {
1369 if (str == null) {
1370 return null;
1371 }
1372 return str.toLowerCase();
1373 }
1374
1375 /**
1376 * <p>
1377 * Uncapitalise a String.
1378 * </p>
1379 * <p>
1380 * That is, convert the first character into lower-case. <code>null</code> is returned as <code>null</code>.
1381 * </p>
1382 *
1383 * @param str the String to uncapitalise
1384 * @return uncapitalised String
1385 */
1386 public static String uncapitalise(String str) {
1387 if (str == null) {
1388 return null;
1389 } else if (str.length() == 0) {
1390 return "";
1391 } else {
1392 return new StringBuilder(str.length())
1393 .append(Character.toLowerCase(str.charAt(0)))
1394 .append(str, 1, str.length())
1395 .toString();
1396 }
1397 }
1398
1399 /**
1400 * <p>
1401 * Capitalise a String.
1402 * </p>
1403 * <p>
1404 * That is, convert the first character into title-case. <code>null</code> is returned as <code>null</code>.
1405 * </p>
1406 *
1407 * @param str the String to capitalise
1408 * @return capitalised String
1409 */
1410 public static String capitalise(String str) {
1411 if (str == null) {
1412 return null;
1413 } else if (str.length() == 0) {
1414 return "";
1415 } else {
1416 return new StringBuilder(str.length())
1417 .append(Character.toTitleCase(str.charAt(0)))
1418 .append(str, 1, str.length())
1419 .toString();
1420 }
1421 }
1422
1423 /**
1424 * <p>
1425 * Swaps the case of String.
1426 * </p>
1427 * <p>
1428 * Properly looks after making sure the start of words are Titlecase and not Uppercase.
1429 * </p>
1430 * <p>
1431 * <code>null</code> is returned as <code>null</code>.
1432 * </p>
1433 *
1434 * @param str the String to swap the case of
1435 * @return the modified String
1436 */
1437 public static String swapCase(String str) {
1438 if (str == null) {
1439 return null;
1440 }
1441 int sz = str.length();
1442 StringBuilder buffer = new StringBuilder(sz);
1443
1444 boolean whitespace = false;
1445 char ch;
1446 char tmp;
1447
1448 for (int i = 0; i < sz; i++) {
1449 ch = str.charAt(i);
1450 if (Character.isUpperCase(ch)) {
1451 tmp = Character.toLowerCase(ch);
1452 } else if (Character.isTitleCase(ch)) {
1453 tmp = Character.toLowerCase(ch);
1454 } else if (Character.isLowerCase(ch)) {
1455 if (whitespace) {
1456 tmp = Character.toTitleCase(ch);
1457 } else {
1458 tmp = Character.toUpperCase(ch);
1459 }
1460 } else {
1461 tmp = ch;
1462 }
1463 buffer.append(tmp);
1464 whitespace = Character.isWhitespace(ch);
1465 }
1466 return buffer.toString();
1467 }
1468
1469 /**
1470 * <p>
1471 * Capitalise all the words in a String.
1472 * </p>
1473 * <p>
1474 * Uses {@link Character#isWhitespace(char)} as a separator between words.
1475 * </p>
1476 * <p>
1477 * <code>null</code> will return <code>null</code>.
1478 * </p>
1479 *
1480 * @param str the String to capitalise
1481 * @return capitalised String
1482 */
1483 public static String capitaliseAllWords(String str) {
1484 if (str == null) {
1485 return null;
1486 }
1487 int sz = str.length();
1488 StringBuilder buffer = new StringBuilder(sz);
1489 boolean space = true;
1490 for (int i = 0; i < sz; i++) {
1491 char ch = str.charAt(i);
1492 if (Character.isWhitespace(ch)) {
1493 buffer.append(ch);
1494 space = true;
1495 } else if (space) {
1496 buffer.append(Character.toTitleCase(ch));
1497 space = false;
1498 } else {
1499 buffer.append(ch);
1500 }
1501 }
1502 return buffer.toString();
1503 }
1504
1505 /**
1506 * <p>
1507 * Uncapitalise all the words in a string.
1508 * </p>
1509 * <p>
1510 * Uses {@link Character#isWhitespace(char)} as a separator between words.
1511 * </p>
1512 * <p>
1513 * <code>null</code> will return <code>null</code>.
1514 * </p>
1515 *
1516 * @param str the string to uncapitalise
1517 * @return uncapitalised string
1518 */
1519 public static String uncapitaliseAllWords(String str) {
1520 if (str == null) {
1521 return null;
1522 }
1523 int sz = str.length();
1524 StringBuilder buffer = new StringBuilder(sz);
1525 boolean space = true;
1526 for (int i = 0; i < sz; i++) {
1527 char ch = str.charAt(i);
1528 if (Character.isWhitespace(ch)) {
1529 buffer.append(ch);
1530 space = true;
1531 } else if (space) {
1532 buffer.append(Character.toLowerCase(ch));
1533 space = false;
1534 } else {
1535 buffer.append(ch);
1536 }
1537 }
1538 return buffer.toString();
1539 }
1540
1541 // Nested extraction
1542 // --------------------------------------------------------------------------
1543
1544 /**
1545 * <p>
1546 * Get the String that is nested in between two instances of the same String.
1547 * </p>
1548 * <p>
1549 * If <code>str</code> is <code>null</code>, will return <code>null</code>.
1550 * </p>
1551 *
1552 * @param str the String containing nested-string
1553 * @param tag the String before and after nested-string
1554 * @return the String that was nested, or <code>null</code>
1555 * @throws NullPointerException if tag is <code>null</code>
1556 */
1557 public static String getNestedString(String str, String tag) {
1558 return getNestedString(str, tag, tag);
1559 }
1560
1561 /**
1562 * <p>
1563 * Get the String that is nested in between two Strings.
1564 * </p>
1565 *
1566 * @param str the String containing nested-string
1567 * @param open the String before nested-string
1568 * @param close the String after nested-string
1569 * @return the String that was nested, or <code>null</code>
1570 * @throws NullPointerException if open or close is <code>null</code>
1571 */
1572 public static String getNestedString(String str, String open, String close) {
1573 if (str == null) {
1574 return null;
1575 }
1576 int start = str.indexOf(open);
1577 if (start != -1) {
1578 int end = str.indexOf(close, start + open.length());
1579 if (end != -1) {
1580 return str.substring(start + open.length(), end);
1581 }
1582 }
1583 return null;
1584 }
1585
1586 /**
1587 * <p>
1588 * How many times is the substring in the larger String.
1589 * </p>
1590 * <p>
1591 * <code>null</code> returns <code>0</code>.
1592 * </p>
1593 *
1594 * @param str the String to check
1595 * @param sub the substring to count
1596 * @return the number of occurrences, 0 if the String is <code>null</code>
1597 * @throws NullPointerException if sub is <code>null</code>
1598 */
1599 public static int countMatches(String str, String sub) {
1600 if (sub.equals("")) {
1601 return 0;
1602 }
1603 if (str == null) {
1604 return 0;
1605 }
1606 int count = 0;
1607 int idx = 0;
1608 while ((idx = str.indexOf(sub, idx)) != -1) {
1609 count++;
1610 idx += sub.length();
1611 }
1612 return count;
1613 }
1614
1615 // Character Tests
1616 // --------------------------------------------------------------------------
1617
1618 /**
1619 * <p>
1620 * Checks if the String contains only unicode letters.
1621 * </p>
1622 * <p>
1623 * <code>null</code> will return <code>false</code>. An empty String will return <code>true</code>.
1624 * </p>
1625 *
1626 * @param str the String to check
1627 * @return <code>true</code> if only contains letters, and is non-null
1628 */
1629 public static boolean isAlpha(String str) {
1630 if (str == null) {
1631 return false;
1632 }
1633 int sz = str.length();
1634 for (int i = 0; i < sz; i++) {
1635 if (Character.isLetter(str.charAt(i)) == false) {
1636 return false;
1637 }
1638 }
1639 return true;
1640 }
1641
1642 /**
1643 * <p>
1644 * Checks if the String contains only whitespace.
1645 * </p>
1646 * <p>
1647 * <code>null</code> will return <code>false</code>. An empty String will return <code>true</code>.
1648 * </p>
1649 *
1650 * @param str the String to check
1651 * @return <code>true</code> if only contains whitespace, and is non-null
1652 */
1653 public static boolean isWhitespace(String str) {
1654 if (str == null) {
1655 return false;
1656 }
1657 int sz = str.length();
1658 for (int i = 0; i < sz; i++) {
1659 if ((Character.isWhitespace(str.charAt(i)) == false)) {
1660 return false;
1661 }
1662 }
1663 return true;
1664 }
1665
1666 /**
1667 * <p>
1668 * Checks if the String contains only unicode letters and space (<code>' '</code>).
1669 * </p>
1670 * <p>
1671 * <code>null</code> will return <code>false</code>. An empty String will return <code>true</code>.
1672 * </p>
1673 *
1674 * @param str the String to check
1675 * @return <code>true</code> if only contains letters and space, and is non-null
1676 */
1677 public static boolean isAlphaSpace(String str) {
1678 if (str == null) {
1679 return false;
1680 }
1681 int sz = str.length();
1682 for (int i = 0; i < sz; i++) {
1683 if ((Character.isLetter(str.charAt(i)) == false) && (str.charAt(i) != ' ')) {
1684 return false;
1685 }
1686 }
1687 return true;
1688 }
1689
1690 /**
1691 * <p>
1692 * Checks if the String contains only unicode letters or digits.
1693 * </p>
1694 * <p>
1695 * <code>null</code> will return <code>false</code>. An empty String will return <code>true</code>.
1696 * </p>
1697 *
1698 * @param str the String to check
1699 * @return <code>true</code> if only contains letters or digits, and is non-null
1700 */
1701 public static boolean isAlphanumeric(String str) {
1702 if (str == null) {
1703 return false;
1704 }
1705 int sz = str.length();
1706 for (int i = 0; i < sz; i++) {
1707 if (Character.isLetterOrDigit(str.charAt(i)) == false) {
1708 return false;
1709 }
1710 }
1711 return true;
1712 }
1713
1714 /**
1715 * <p>
1716 * Checks if the String contains only unicode letters, digits or space (<code>' '</code>).
1717 * </p>
1718 * <p>
1719 * <code>null</code> will return <code>false</code>. An empty String will return <code>true</code>.
1720 * </p>
1721 *
1722 * @param str the String to check
1723 * @return <code>true</code> if only contains letters, digits or space, and is non-null
1724 */
1725 public static boolean isAlphanumericSpace(String str) {
1726 if (str == null) {
1727 return false;
1728 }
1729 int sz = str.length();
1730 for (int i = 0; i < sz; i++) {
1731 if ((Character.isLetterOrDigit(str.charAt(i)) == false) && (str.charAt(i) != ' ')) {
1732 return false;
1733 }
1734 }
1735 return true;
1736 }
1737
1738 /**
1739 * <p>
1740 * Checks if the String contains only unicode digits.
1741 * </p>
1742 * <p>
1743 * <code>null</code> will return <code>false</code>. An empty String will return <code>true</code>.
1744 * </p>
1745 *
1746 * @param str the String to check
1747 * @return <code>true</code> if only contains digits, and is non-null
1748 */
1749 public static boolean isNumeric(String str) {
1750 if (str == null) {
1751 return false;
1752 }
1753 int sz = str.length();
1754 for (int i = 0; i < sz; i++) {
1755 if (Character.isDigit(str.charAt(i)) == false) {
1756 return false;
1757 }
1758 }
1759 return true;
1760 }
1761
1762 /**
1763 * <p>
1764 * Checks if the String contains only unicode digits or space (<code>' '</code>).
1765 * </p>
1766 * <p>
1767 * <code>null</code> will return <code>false</code>. An empty String will return <code>true</code>.
1768 * </p>
1769 *
1770 * @param str the String to check
1771 * @return <code>true</code> if only contains digits or space, and is non-null
1772 */
1773 public static boolean isNumericSpace(String str) {
1774 if (str == null) {
1775 return false;
1776 }
1777 int sz = str.length();
1778 for (int i = 0; i < sz; i++) {
1779 if ((Character.isDigit(str.charAt(i)) == false) && (str.charAt(i) != ' ')) {
1780 return false;
1781 }
1782 }
1783 return true;
1784 }
1785
1786 // Defaults
1787 // --------------------------------------------------------------------------
1788
1789 /**
1790 * <p>
1791 * Returns either the passed in <code>Object</code> as a String, or, if the <code>Object</code> is
1792 * <code>null</code>, an empty String.
1793 * </p>
1794 *
1795 * @param obj the Object to check
1796 * @return the passed in Object's toString, or blank if it was <code>null</code>
1797 * @see Objects#toString(Object, String)
1798 */
1799 @Deprecated
1800 public static String defaultString(Object obj) {
1801 return defaultString(obj, "");
1802 }
1803
1804 /**
1805 * <p>
1806 * Returns either the passed in <code>Object</code> as a String, or, if the <code>Object</code> is
1807 * <code>null</code>, a passed in default String.
1808 * </p>
1809 *
1810 * @param obj the Object to check
1811 * @param defaultString the default String to return if str is <code>null</code>
1812 * @return the passed in string, or the default if it was <code>null</code>
1813 * @see Objects#toString(Object, String)
1814 */
1815 @Deprecated
1816 public static String defaultString(Object obj, String defaultString) {
1817 return Objects.toString(obj, defaultString);
1818 }
1819
1820 // Reversing
1821 // --------------------------------------------------------------------------
1822
1823 /**
1824 * <p>
1825 * Reverse a String.
1826 * </p>
1827 * <p>
1828 * <code>null</code> String returns <code>null</code>.
1829 * </p>
1830 *
1831 * @param str the String to reverse
1832 * @return the reversed String
1833 */
1834 public static String reverse(String str) {
1835 if (str == null) {
1836 return null;
1837 }
1838 return new StringBuilder(str).reverse().toString();
1839 }
1840
1841 /**
1842 * <p>
1843 * Reverses a String that is delimited by a specific character.
1844 * </p>
1845 * <p>
1846 * The Strings between the delimiters are not reversed. Thus java.lang.String becomes String.lang.java (if the
1847 * delimiter is <code>'.'</code>).
1848 * </p>
1849 *
1850 * @param str the String to reverse
1851 * @param delimiter the delimiter to use
1852 * @return the reversed String
1853 */
1854 public static String reverseDelimitedString(String str, String delimiter) {
1855 // could implement manually, but simple way is to reuse other,
1856 // probably slower, methods.
1857 String[] strs = split(str, delimiter);
1858 reverseArray(strs);
1859 return join(strs, delimiter);
1860 }
1861
1862 /**
1863 * <p>
1864 * Reverses an array.
1865 * </p>
1866 * <p>
1867 * TAKEN FROM CollectionsUtils.
1868 * </p>
1869 *
1870 * @param array the array to reverse
1871 */
1872 private static void reverseArray(Object[] array) {
1873 int i = 0;
1874 int j = array.length - 1;
1875 Object tmp;
1876
1877 while (j > i) {
1878 tmp = array[j];
1879 array[j] = array[i];
1880 array[i] = tmp;
1881 j--;
1882 i++;
1883 }
1884 }
1885
1886 // Abbreviating
1887 // --------------------------------------------------------------------------
1888
1889 /**
1890 * @return Turn "Now is the time for all good men" into "Now is the time for..."
1891 * <p>
1892 * Specifically:
1893 * <p>
1894 * If str is less than max characters long, return it. Else abbreviate it to (substring(str, 0, max-3) + "..."). If
1895 * maxWidth is less than 3, throw an IllegalArgumentException. In no case will it return a string of length greater
1896 * than maxWidth.
1897 * @param s string
1898 * @param maxWidth maximum length of result string
1899 **/
1900 public static String abbreviate(String s, int maxWidth) {
1901 return abbreviate(s, 0, maxWidth);
1902 }
1903
1904 /**
1905 * @return Turn "Now is the time for all good men" into "...is the time for..."
1906 *
1907 * Works like abbreviate(String, int), but allows you to specify a "left edge" offset. Note that this left edge is
1908 * not necessarily going to be the leftmost character in the result, or the first character following the ellipses,
1909 * but it will appear somewhere in the result. In no case will it return a string of length greater than maxWidth.
1910 * @param s string
1911 * @param offset left edge of source string
1912 * @param maxWidth maximum length of result string
1913 **/
1914 public static String abbreviate(String s, int offset, int maxWidth) {
1915 if (maxWidth < 4) {
1916 throw new IllegalArgumentException("Minimum abbreviation width is 4");
1917 }
1918 if (s.length() <= maxWidth) {
1919 return s;
1920 }
1921 if (offset > s.length()) {
1922 offset = s.length();
1923 }
1924 if ((s.length() - offset) < (maxWidth - 3)) {
1925 offset = s.length() - (maxWidth - 3);
1926 }
1927 if (offset <= 4) {
1928 return s.substring(0, maxWidth - 3) + "...";
1929 }
1930 if (maxWidth < 7) {
1931 throw new IllegalArgumentException("Minimum abbreviation width with offset is 7");
1932 }
1933 if ((offset + (maxWidth - 3)) < s.length()) {
1934 return "..." + abbreviate(s.substring(offset), maxWidth - 3);
1935 }
1936 return "..." + s.substring(s.length() - (maxWidth - 3));
1937 }
1938
1939 // Difference
1940 // --------------------------------------------------------------------------
1941
1942 /**
1943 * Compare two strings, and return the portion where they differ. (More precisely, return the remainder of the
1944 * second string, starting from where it's different from the first.)
1945 * <p>
1946 * E.g. strdiff("i am a machine", "i am a robot") -> "robot"
1947 * @param s1 string
1948 * @param s2 string
1949 * @return the portion of s2 where it differs from s1; returns the empty string ("") if they are equal
1950 **/
1951 public static String difference(String s1, String s2) {
1952 int at = differenceAt(s1, s2);
1953 if (at == -1) {
1954 return "";
1955 }
1956 return s2.substring(at);
1957 }
1958
1959 /**
1960 * Compare two strings, and return the index at which the strings begin to differ.
1961 * <p>
1962 * E.g. strdiff("i am a machine", "i am a robot") -> 7
1963 * </p>
1964 * @param s1 string
1965 * @param s2 string
1966 * @return the index where s2 and s1 begin to differ; -1 if they are equal
1967 **/
1968 public static int differenceAt(String s1, String s2) {
1969 int i;
1970 for (i = 0; (i < s1.length()) && (i < s2.length()); ++i) {
1971 if (s1.charAt(i) != s2.charAt(i)) {
1972 break;
1973 }
1974 }
1975 if ((i < s2.length()) || (i < s1.length())) {
1976 return i;
1977 }
1978 return -1;
1979 }
1980
1981 public static String interpolate(String text, Map<?, ?> namespace) {
1982 Iterator<?> keys = namespace.keySet().iterator();
1983
1984 while (keys.hasNext()) {
1985 String key = keys.next().toString();
1986
1987 Object obj = namespace.get(key);
1988
1989 if (obj == null) {
1990 throw new NullPointerException("The value of the key '" + key + "' is null.");
1991 }
1992
1993 String value = obj.toString();
1994
1995 text = replace(text, "${" + key + "}", value);
1996
1997 if (!key.contains(" ")) {
1998 text = replace(text, "$" + key, value);
1999 }
2000 }
2001 return text;
2002 }
2003
2004 public static String removeAndHump(String data, String replaceThis) {
2005 String temp;
2006
2007 StringBuilder out = new StringBuilder();
2008
2009 temp = data;
2010
2011 StringTokenizer st = new StringTokenizer(temp, replaceThis);
2012
2013 while (st.hasMoreTokens()) {
2014 String element = (String) st.nextElement();
2015
2016 out.append(capitalizeFirstLetter(element));
2017 }
2018
2019 return out.toString();
2020 }
2021
2022 public static String capitalizeFirstLetter(String data) {
2023 char firstLetter = Character.toTitleCase(data.substring(0, 1).charAt(0));
2024
2025 String restLetters = data.substring(1);
2026
2027 return firstLetter + restLetters;
2028 }
2029
2030 public static String lowercaseFirstLetter(String data) {
2031 char firstLetter = Character.toLowerCase(data.substring(0, 1).charAt(0));
2032
2033 String restLetters = data.substring(1);
2034
2035 return firstLetter + restLetters;
2036 }
2037
2038 public static String addAndDeHump(String view) {
2039 StringBuilder sb = new StringBuilder();
2040
2041 for (int i = 0; i < view.length(); i++) {
2042 if ((i != 0) && Character.isUpperCase(view.charAt(i))) {
2043 sb.append('-');
2044 }
2045
2046 sb.append(view.charAt(i));
2047 }
2048
2049 return sb.toString().trim().toLowerCase(Locale.ENGLISH);
2050 }
2051
2052 /**
2053 * <p>
2054 * Quote and escape a String with the given character, handling <code>null</code>.
2055 * </p>
2056 *
2057 * <pre>
2058 * StringUtils.quoteAndEscape(null, *) = null
2059 * StringUtils.quoteAndEscape("", *) = ""
2060 * StringUtils.quoteAndEscape("abc", '"') = abc
2061 * StringUtils.quoteAndEscape("a\"bc", '"') = "a\"bc"
2062 * StringUtils.quoteAndEscape("a\"bc", '\'') = 'a\"bc'
2063 * </pre>
2064 *
2065 * @param source the source String
2066 * @param quoteChar the char used to quote
2067 * @return the String quoted and escaped
2068 * @since 1.5.1
2069 * @see #quoteAndEscape(String, char, char[], char[], char, boolean)
2070 */
2071 public static String quoteAndEscape(String source, char quoteChar) {
2072 return quoteAndEscape(source, quoteChar, new char[] {quoteChar}, new char[] {' '}, '\\', false);
2073 }
2074
2075 /**
2076 * <p>
2077 * Quote and escape a String with the given character, handling <code>null</code>.
2078 * </p>
2079 *
2080 * @param source the source String
2081 * @param quoteChar the char used to quote
2082 * @param quotingTriggers chars generating a quote
2083 * @return the String quoted and escaped
2084 * @since 1.5.1
2085 * @see #quoteAndEscape(String, char, char[], char[], char, boolean)
2086 */
2087 public static String quoteAndEscape(String source, char quoteChar, char[] quotingTriggers) {
2088 return quoteAndEscape(source, quoteChar, new char[] {quoteChar}, quotingTriggers, '\\', false);
2089 }
2090
2091 /**
2092 * @param source the source String
2093 * @param quoteChar the char used to quote
2094 * @param escapedChars chars to escape
2095 * @param escapeChar char used for escaping
2096 * @param force force the quoting
2097 * @return the String quoted and escaped
2098 * @since 1.5.1
2099 * @see #quoteAndEscape(String, char, char[], char[], char, boolean)
2100 */
2101 public static String quoteAndEscape(
2102 String source, char quoteChar, final char[] escapedChars, char escapeChar, boolean force) {
2103 return quoteAndEscape(source, quoteChar, escapedChars, new char[] {' '}, escapeChar, force);
2104 }
2105
2106 /**
2107 * @param source the source String
2108 * @param quoteChar the char used to quote
2109 * @param escapedChars chars to escape
2110 * @param quotingTriggers chars generating a quote
2111 * @param escapeChar char used for escaping
2112 * @param force force the quoting
2113 * @return the String quoted and escaped
2114 * @since 1.5.1
2115 */
2116 public static String quoteAndEscape(
2117 String source,
2118 char quoteChar,
2119 final char[] escapedChars,
2120 final char[] quotingTriggers,
2121 char escapeChar,
2122 boolean force) {
2123 return quoteAndEscape(source, quoteChar, escapedChars, quotingTriggers, escapeChar + "%s", force);
2124 }
2125
2126 /**
2127 * @param source the source String
2128 * @param quoteChar the char used to quote
2129 * @param escapedChars chars to escape
2130 * @param quotingTriggers chars generating a quote
2131 * @param escapePattern pattern used for escaping
2132 * @param force force the quoting
2133 * @return the String quoted and escaped
2134 * @since 3.0.4
2135 */
2136 public static String quoteAndEscape(
2137 String source,
2138 char quoteChar,
2139 final char[] escapedChars,
2140 final char[] quotingTriggers,
2141 String escapePattern,
2142 boolean force) {
2143 if (source == null) {
2144 return null;
2145 }
2146
2147 if (!force
2148 && source.startsWith(Character.toString(quoteChar))
2149 && source.endsWith(Character.toString(quoteChar))) {
2150 return source;
2151 }
2152
2153 String escaped = escape(source, escapedChars, escapePattern);
2154
2155 boolean quote = false;
2156 if (force) {
2157 quote = true;
2158 } else if (!escaped.equals(source)) {
2159 quote = true;
2160 } else {
2161 for (char quotingTrigger : quotingTriggers) {
2162 if (escaped.indexOf(quotingTrigger) > -1) {
2163 quote = true;
2164 break;
2165 }
2166 }
2167 }
2168
2169 if (quote) {
2170 return quoteChar + escaped + quoteChar;
2171 }
2172
2173 return escaped;
2174 }
2175
2176 /**
2177 * @param source the source String
2178 * @param escapedChars chars to escape
2179 * @param escapeChar char used for escaping
2180 * @return the String escaped
2181 * @since 1.5.1
2182 */
2183 public static String escape(String source, final char[] escapedChars, char escapeChar) {
2184 return escape(source, escapedChars, escapeChar + "%s");
2185 }
2186
2187 /**
2188 * @param source the source String
2189 * @param escapedChars chars to escape
2190 * @param escapePattern pattern used for escaping
2191 * @return the String escaped
2192 * @since 3.0.4
2193 */
2194 public static String escape(String source, final char[] escapedChars, String escapePattern) {
2195 if (source == null) {
2196 return null;
2197 }
2198
2199 char[] eqc = new char[escapedChars.length];
2200 System.arraycopy(escapedChars, 0, eqc, 0, escapedChars.length);
2201 Arrays.sort(eqc);
2202
2203 StringBuilder buffer = new StringBuilder(source.length());
2204
2205 for (int i = 0; i < source.length(); i++) {
2206 final char c = source.charAt(i);
2207 int result = Arrays.binarySearch(eqc, c);
2208
2209 if (result > -1) {
2210 buffer.append(String.format(escapePattern, c));
2211 } else {
2212 buffer.append(c);
2213 }
2214 }
2215
2216 return buffer.toString();
2217 }
2218
2219 /**
2220 * Remove all duplicate whitespace characters and line terminators are replaced with a single space.
2221 *
2222 * @param s a not null String
2223 * @return a string with unique whitespace.
2224 * @since 1.5.7
2225 */
2226 public static String removeDuplicateWhitespace(String s) {
2227 StringBuilder result = new StringBuilder();
2228 int length = s.length();
2229 boolean isPreviousWhiteSpace = false;
2230 for (int i = 0; i < length; i++) {
2231 char c = s.charAt(i);
2232 boolean thisCharWhiteSpace = Character.isWhitespace(c);
2233 if (!(isPreviousWhiteSpace && thisCharWhiteSpace)) {
2234 result.append(c);
2235 }
2236 isPreviousWhiteSpace = thisCharWhiteSpace;
2237 }
2238 return result.toString();
2239 }
2240
2241 /**
2242 * Parses the given String and replaces all occurrences of '\n', '\r' and '\r\n' with the system line separator.
2243 *
2244 * @param s a not null String
2245 * @return a String that contains only System line separators.
2246 * @see #unifyLineSeparators(String, String)
2247 * @since 1.5.7
2248 */
2249 public static String unifyLineSeparators(String s) {
2250 return unifyLineSeparators(s, System.getProperty("line.separator"));
2251 }
2252
2253 /**
2254 * Parses the given String and replaces all occurrences of '\n', '\r' and '\r\n' with the system line separator.
2255 *
2256 * @param s a not null String
2257 * @param ls the wanted line separator ("\n" on UNIX), if null using the System line separator.
2258 * @return a String that contains only System line separators.
2259 * @throws IllegalArgumentException if ls is not '\n', '\r' and '\r\n' characters.
2260 * @since 1.5.7
2261 */
2262 public static String unifyLineSeparators(String s, String ls) {
2263 if (s == null) {
2264 return null;
2265 }
2266
2267 if (ls == null) {
2268 ls = System.getProperty("line.separator");
2269 }
2270
2271 if (!(ls.equals("\n") || ls.equals("\r") || ls.equals("\r\n"))) {
2272 throw new IllegalArgumentException("Requested line separator is invalid.");
2273 }
2274
2275 int length = s.length();
2276
2277 StringBuilder buffer = new StringBuilder(length);
2278 for (int i = 0; i < length; i++) {
2279 if (s.charAt(i) == '\r') {
2280 if ((i + 1) < length && s.charAt(i + 1) == '\n') {
2281 i++;
2282 }
2283
2284 buffer.append(ls);
2285 } else if (s.charAt(i) == '\n') {
2286 buffer.append(ls);
2287 } else {
2288 buffer.append(s.charAt(i));
2289 }
2290 }
2291
2292 return buffer.toString();
2293 }
2294
2295 /**
2296 * <p>
2297 * Checks if String contains a search character, handling <code>null</code>. This method uses
2298 * {@link String#indexOf(int)}.
2299 * </p>
2300 * <p>
2301 * A <code>null</code> or empty ("") String will return <code>false</code>.
2302 * </p>
2303 *
2304 * <pre>
2305 * StringUtils.contains(null, *) = false
2306 * StringUtils.contains("", *) = false
2307 * StringUtils.contains("abc", 'a') = true
2308 * StringUtils.contains("abc", 'z') = false
2309 * </pre>
2310 *
2311 * @param str the String to check, may be null
2312 * @param searchChar the character to find
2313 * @return true if the String contains the search character, false if not or <code>null</code> string input
2314 * @since 1.5.7
2315 */
2316 public static boolean contains(String str, char searchChar) {
2317 if (isEmpty(str)) {
2318 return false;
2319 }
2320 return str.indexOf(searchChar) >= 0;
2321 }
2322
2323 /**
2324 * <p>
2325 * Checks if String contains a search String, handling <code>null</code>. This method uses
2326 * {@link String#indexOf(int)}.
2327 * </p>
2328 * <p>
2329 * A <code>null</code> String will return <code>false</code>.
2330 * </p>
2331 *
2332 * <pre>
2333 * StringUtils.contains(null, *) = false
2334 * StringUtils.contains(*, null) = false
2335 * StringUtils.contains("", "") = true
2336 * StringUtils.contains("abc", "") = true
2337 * StringUtils.contains("abc", "a") = true
2338 * StringUtils.contains("abc", "z") = false
2339 * </pre>
2340 *
2341 * @param str the String to check, may be null
2342 * @param searchStr the String to find, may be null
2343 * @return true if the String contains the search String, false if not or <code>null</code> string input
2344 * @since 1.5.7
2345 */
2346 public static boolean contains(String str, String searchStr) {
2347 if (str == null || searchStr == null) {
2348 return false;
2349 }
2350 return str.contains(searchStr);
2351 }
2352 }