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