All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.maven.shared.utils.StringUtils Maven / Gradle / Ivy

There is a newer version: 3.4.2
Show newest version
package org.apache.maven.shared.utils;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */


import java.util.Arrays;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
 * 

Common String manipulation routines.

*

*

Originally from * Turbine, the * GenerationJavaCore library and Velocity. * Later a lots methods from commons-lang StringUtils * got added too. Gradually smaller additions and fixes have been made * over the time by various ASF committers.

* * @author Jon S. Stevens * @author Daniel Rall * @author Greg Coladonato * @author Henri Yandell * @author Ed Korthof * @author Rand McNeely * @author Stephen Colebourne * @author Fredrik Westermarck * @author Holger Krauth * @author Alexander Day Chaffee * @version $Id: StringUtils.java 1402496 2012-10-26 13:00:39Z rfscholte $ * */ @SuppressWarnings( "JavaDoc" ) public class StringUtils { /** *

StringUtils instances should NOT be constructed in * standard programming. Instead, the class should be used as * StringUtils.trim(" foo ");.

*

*

This constructor is public to permit tools that require a JavaBean * manager to operate.

*/ public StringUtils() { } // Empty //-------------------------------------------------------------------------- /** *

Removes control characters, including whitespace, from both * ends of this String, handling null by returning * an empty String.

* * @param str the String to check * @return the trimmed text (never null) * @see java.lang.String#trim() */ public @Nonnull static String clean( String str ) { return ( str == null ? "" : str.trim() ); } /** *

Removes control characters, including whitespace, from both * ends of this String, handling null by returning * null.

* * @param str the String to check * @return the trimmed text (or null) * @see java.lang.String#trim() */ public static String trim( String str ) { return ( str == null ? null : str.trim() ); } /** *

Deletes all whitespaces from a String.

*

*

Whitespace is defined by * {@link Character#isWhitespace(char)}.

* * @param str String target to delete whitespace from * @return the String without whitespaces * @throws NullPointerException */ public @Nonnull static String deleteWhitespace( @Nonnull String str ) { StringBuilder buffer = new StringBuilder(); int sz = str.length(); for ( int i = 0; i < sz; i++ ) { if ( !Character.isWhitespace( str.charAt( i ) ) ) { buffer.append( str.charAt( i ) ); } } return buffer.toString(); } /** *

Checks if a String is non null and is * not empty (length > 0).

* * @param str the String to check * @return true if the String is non-null, and not length zero */ public static boolean isNotEmpty( String str ) { return ( ( str != null ) && ( str.length() > 0 ) ); } /** *

Checks if a (trimmed) String is null or empty.

*

*

Note: In future releases, this method will no longer trim the input string such that it works * complementary to {@link #isNotEmpty(String)}. Code that wants to test for whitespace-only strings should be * migrated to use {@link #isBlank(String)} instead.

* * @param str the String to check * @return true if the String is null, or * length zero once trimmed */ public static boolean isEmpty( @Nullable String str ) { return ( ( str == null ) || ( str.trim().length() == 0 ) ); } /** *

* Checks if a String is whitespace, empty ("") or null. *

*

*

     * StringUtils.isBlank(null)      = true
     * StringUtils.isBlank("")        = true
     * StringUtils.isBlank(" ")       = true
     * StringUtils.isBlank("bob")     = false
     * StringUtils.isBlank("  bob  ") = false
     * 
* * @param str the String to check, may be null * @return true if the String is null, empty or whitespace * */ public static boolean isBlank( @Nullable String str ) { int strLen; if ( str == null || ( strLen = str.length() ) == 0 ) { return true; } for ( int i = 0; i < strLen; i++ ) { if ( !Character.isWhitespace( str.charAt( i ) ) ) { return false; } } return true; } /** *

* Checks if a String is not empty (""), not null and not whitespace only. *

*

*

     * StringUtils.isNotBlank(null)      = false
     * StringUtils.isNotBlank("")        = false
     * StringUtils.isNotBlank(" ")       = false
     * StringUtils.isNotBlank("bob")     = true
     * StringUtils.isNotBlank("  bob  ") = true
     * 
* * @param str the String to check, may be null * @return true if the String is not empty and not null and not whitespace * */ public static boolean isNotBlank( @Nullable String str ) { return !isBlank( str ); } // Equals and IndexOf //-------------------------------------------------------------------------- /** *

Compares two Strings, returning true if they are equal.

*

*

nulls are handled without exceptions. Two null * references are considered to be equal. The comparison is case sensitive.

* * @param str1 the first string * @param str2 the second string * @return true if the Strings are equal, case sensitive, or * both null * @see java.lang.String#equals(Object) */ public static boolean equals( @Nullable String str1, @Nullable String str2 ) { return ( str1 == null ? str2 == null : str1.equals( str2 ) ); } /** *

Compares two Strings, returning true if they are equal ignoring * the case.

*

*

Nulls are handled without exceptions. Two null * references are considered equal. Comparison is case insensitive.

* * @param str1 the first string * @param str2 the second string * @return true if the Strings are equal, case insensitive, or * both null * @see java.lang.String#equalsIgnoreCase(String) */ public static boolean equalsIgnoreCase( String str1, String str2 ) { return ( str1 == null ? str2 == null : str1.equalsIgnoreCase( str2 ) ); } /** *

Find the first index of any of a set of potential substrings.

*

*

null String will return -1.

* * @param str the String to check * @param searchStrs the Strings to search for * @return the first index of any of the searchStrs in str * @throws NullPointerException if any of searchStrs[i] is null */ public static int indexOfAny( String str, String... searchStrs ) { if ( ( str == null ) || ( searchStrs == null ) ) { return -1; } // String's can't have a MAX_VALUEth index. int ret = Integer.MAX_VALUE; int tmp; for ( String searchStr : searchStrs ) { tmp = str.indexOf( searchStr ); if ( tmp == -1 ) { continue; } if ( tmp < ret ) { ret = tmp; } } return ( ret == Integer.MAX_VALUE ) ? -1 : ret; } /** *

Find the latest index of any of a set of potential substrings.

*

*

null string will return -1.

* * @param str the String to check * @param searchStrs the Strings to search for * @return the last index of any of the Strings * @throws NullPointerException if any of searchStrs[i] is null */ public static int lastIndexOfAny( String str, String... searchStrs ) { if ( ( str == null ) || ( searchStrs == null ) ) { return -1; } int ret = -1; int tmp; for ( String searchStr : searchStrs ) { tmp = str.lastIndexOf( searchStr ); if ( tmp > ret ) { ret = tmp; } } return ret; } // Substring //-------------------------------------------------------------------------- /** *

Gets a substring from the specified string avoiding exceptions.

*

*

A negative start position can be used to start n * characters from the end of the String.

* * @param str the String to get the substring from * @param start the position to start from, negative means * count back from the end of the String by this many characters * @return substring from start position */ public static String substring( String str, int start ) { if ( str == null ) { return null; } // handle negatives, which means last n characters if ( start < 0 ) { start = str.length() + start; // remember start is negative } if ( start < 0 ) { start = 0; } if ( start > str.length() ) { return ""; } return str.substring( start ); } /** *

Gets a substring from the specified String avoiding exceptions.

*

*

A negative start position can be used to start/end n * characters from the end of the String.

* * @param str the String to get the substring from * @param start the position to start from, negative means * count back from the end of the string by this many characters * @param end the position to end at (exclusive), negative means * count back from the end of the String by this many characters * @return substring from start position to end positon */ public static String substring( String str, int start, int end ) { if ( str == null ) { return null; } // handle negatives if ( end < 0 ) { end = str.length() + end; // remember end is negative } if ( start < 0 ) { start = str.length() + start; // remember start is negative } // check length next if ( end > str.length() ) { // check this works. end = str.length(); } // if start is greater than end, return "" if ( start > end ) { return ""; } if ( start < 0 ) { start = 0; } if ( end < 0 ) { end = 0; } return str.substring( start, end ); } /** *

Gets the leftmost n characters of a String.

*

*

If n characters are not available, or the * String is null, the String will be returned without * an exception.

* * @param str the String to get the leftmost characters from * @param len the length of the required String * @return the leftmost characters * @throws IllegalArgumentException if len is less than zero */ public static String left( String str, int len ) { if ( len < 0 ) { throw new IllegalArgumentException( "Requested String length " + len + " is less than zero" ); } if ( ( str == null ) || ( str.length() <= len ) ) { return str; } else { return str.substring( 0, len ); } } /** *

Gets the rightmost n characters of a String.

*

*

If n characters are not available, or the String * is null, the String will be returned without an * exception.

* * @param str the String to get the rightmost characters from * @param len the length of the required String * @return the leftmost characters * @throws IllegalArgumentException if len is less than zero */ public static String right( String str, int len ) { if ( len < 0 ) { throw new IllegalArgumentException( "Requested String length " + len + " is less than zero" ); } if ( ( str == null ) || ( str.length() <= len ) ) { return str; } else { return str.substring( str.length() - len ); } } /** *

Gets n characters from the middle of a String.

*

*

If n characters are not available, the remainder * of the String will be returned without an exception. If the * String is null, null will be returned.

* * @param str the String to get the characters from * @param pos the position to start from * @param len the length of the required String * @return the leftmost characters * @throws IndexOutOfBoundsException if pos is out of bounds * @throws IllegalArgumentException if len is less than zero */ public static String mid( String str, int pos, int len ) { if ( ( pos < 0 ) || ( ( str != null ) && ( pos > str.length() ) ) ) { throw new StringIndexOutOfBoundsException( "String index " + pos + " is out of bounds" ); } if ( len < 0 ) { throw new IllegalArgumentException( "Requested String length " + len + " is less than zero" ); } if ( str == null ) { return null; } if ( str.length() <= ( pos + len ) ) { return str.substring( pos ); } else { return str.substring( pos, pos + len ); } } // Splitting //-------------------------------------------------------------------------- /** *

Splits the provided text into a array, using whitespace as the * separator.

*

*

The separator is not included in the returned String array.

* * @param str the String to parse * @return an array of parsed Strings */ public @Nonnull static String[] split( @Nonnull String str ) { return split( str, null, -1 ); } /** * @see #split(String, String, int) */ public @Nonnull static String[] split( @Nonnull String text, String separator ) { return split( text, separator, -1 ); } /** *

Splits the provided text into a array, based on a given separator.

*

*

The separator is not included in the returned String array. The * maximum number of splits to perfom can be controlled. A null * separator will cause parsing to be on whitespace.

*

*

This is useful for quickly splitting a String directly into * an array of tokens, instead of an enumeration of tokens (as * StringTokenizer does).

* * @param str The string to parse. * @param separator Characters used as the delimiters. If * null, splits on whitespace. * @param max The maximum number of elements to include in the * array. A zero or negative value implies no limit. * @return an array of parsed Strings */ public @Nonnull static String[] split( @Nonnull String str, String separator, int max ) { StringTokenizer tok; if ( separator == null ) { // Null separator means we're using StringTokenizer's default // delimiter, which comprises all whitespace characters. tok = new StringTokenizer( str ); } else { tok = new StringTokenizer( str, separator ); } int listSize = tok.countTokens(); if ( ( max > 0 ) && ( listSize > max ) ) { listSize = max; } String[] list = new String[listSize]; int i = 0; int lastTokenBegin; int lastTokenEnd = 0; while ( tok.hasMoreTokens() ) { if ( ( max > 0 ) && ( i == listSize - 1 ) ) { // In the situation where we hit the max yet have // tokens left over in our input, the last list // element gets all remaining text. String endToken = tok.nextToken(); lastTokenBegin = str.indexOf( endToken, lastTokenEnd ); list[i] = str.substring( lastTokenBegin ); break; } else { list[i] = tok.nextToken(); lastTokenBegin = str.indexOf( list[i], lastTokenEnd ); lastTokenEnd = lastTokenBegin + list[i].length(); } i++; } return list; } // Joining //-------------------------------------------------------------------------- /** *

Concatenates elements of an array into a single String.

*

*

The difference from join is that concatenate has no delimiter.

* * @param array the array of values to concatenate. * @return the concatenated string. */ public @Nonnull static String concatenate( @Nonnull Object... array ) { return join( array, "" ); } /** *

Joins the elements of the provided array into a single String * containing the provided list of elements.

*

*

No delimiter is added before or after the list. A * null separator is the same as a blank String.

* * @param array the array of values to join together * @param separator the separator character to use * @return the joined String */ public @Nonnull static String join( @Nonnull Object[] array, String separator ) { if ( separator == null ) { separator = ""; } int arraySize = array.length; int bufSize = ( arraySize == 0 ? 0 : ( array[0].toString().length() + separator.length() ) * arraySize ); StringBuilder buf = new StringBuilder( bufSize ); for ( int i = 0; i < arraySize; i++ ) { if ( i > 0 ) { buf.append( separator ); } buf.append( array[i] ); } return buf.toString(); } /** *

Joins the elements of the provided Iterator into * a single String containing the provided elements.

*

*

No delimiter is added before or after the list. A * null separator is the same as a blank String.

* * @param iterator the Iterator of values to join together * @param separator the separator character to use * @return the joined String */ public @Nonnull static String join( @Nonnull Iterator iterator, String separator ) { if ( separator == null ) { separator = ""; } StringBuilder buf = new StringBuilder( 256 ); // Java default is 16, probably too small while ( iterator.hasNext() ) { buf.append( iterator.next() ); if ( iterator.hasNext() ) { buf.append( separator ); } } return buf.toString(); } // Replacing //-------------------------------------------------------------------------- /** *

Replace a char with another char inside a larger String, once.

*

*

A null reference passed to this method is a no-op.

* * @param text text to search and replace in * @param repl char to search for * @param with char to replace with * @return the text with any replacements processed * @see #replace(String text, char repl, char with, int max) */ public static String replaceOnce( @Nullable String text, char repl, char with ) { return replace( text, repl, with, 1 ); } /** *

Replace all occurances of a char within another char.

*

*

A null reference passed to this method is a no-op.

* * @param text text to search and replace in * @param repl char to search for * @param with char to replace with * @return the text with any replacements processed * @see #replace(String text, char repl, char with, int max) */ public static String replace( @Nullable String text, char repl, char with ) { return replace( text, repl, with, -1 ); } /** *

Replace a char with another char inside a larger String, * for the first max values of the search char.

*

*

A null reference passed to this method is a no-op.

* * @param text text to search and replace in * @param repl char to search for * @param with char to replace with * @param max maximum number of values to replace, or -1 if no maximum * @return the text with any replacements processed */ public static String replace( @Nullable String text, char repl, char with, int max ) { return replace( text, String.valueOf( repl ), String.valueOf( with ), max ); } /** *

Replace a String with another String inside a larger String, once.

*

*

A null reference passed to this method is a no-op.

* * @param text text to search and replace in * @param repl String to search for * @param with String to replace with * @return the text with any replacements processed * @see #replace(String text, String repl, String with, int max) */ public static String replaceOnce( @Nullable String text, @Nullable String repl, @Nullable String with ) { return replace( text, repl, with, 1 ); } /** *

Replace all occurances of a String within another String.

*

*

A null reference passed to this method is a no-op.

* * @param text text to search and replace in * @param repl String to search for * @param with String to replace with * @return the text with any replacements processed * @see #replace(String text, String repl, String with, int max) */ public static String replace( @Nullable String text, @Nullable String repl, @Nullable String with ) { return replace( text, repl, with, -1 ); } /** *

Replace a String with another String inside a larger String, * for the first max values of the search String.

*

*

A null reference passed to this method is a no-op.

* * @param text text to search and replace in * @param repl String to search for * @param with String to replace with * @param max maximum number of values to replace, or -1 if no maximum * @return the text with any replacements processed */ public static String replace( @Nullable String text, @Nullable String repl, @Nullable String with, int max ) { if ( ( text == null ) || ( repl == null ) || ( with == null ) || ( repl.length() == 0 ) ) { return text; } StringBuilder buf = new StringBuilder( text.length() ); int start = 0, end; while ( ( end = text.indexOf( repl, start ) ) != -1 ) { buf.append( text.substring( start, end ) ).append( with ); start = end + repl.length(); if ( --max == 0 ) { break; } } buf.append( text.substring( start ) ); return buf.toString(); } /** *

Overlay a part of a String with another String.

* * @param text String to do overlaying in * @param overlay String to overlay * @param start int to start overlaying at * @param end int to stop overlaying before * @return String with overlayed text * @throws NullPointerException if text or overlay is null */ @SuppressWarnings( "ConstantConditions" ) public @Nonnull static String overlayString( @Nonnull String text, @Nonnull String overlay, int start, int end ) { if ( overlay == null ) { throw new NullPointerException( "overlay is null" ); } return text.substring( 0, start ) + overlay + text.substring( end ); } // Centering //-------------------------------------------------------------------------- /** *

Center a String in a larger String of size n.

*

*

Uses spaces as the value to buffer the String with. * Equivalent to center(str, size, " ").

* * @param str String to center * @param size int size of new String * @return String containing centered String * @throws NullPointerException if str is null */ public @Nonnull static String center( @Nonnull String str, int size ) { return center( str, size, " " ); } /** *

Center a String in a larger String of size n.

*

*

Uses a supplied String as the value to buffer the String with.

* * @param str String to center * @param size int size of new String * @param delim String to buffer the new String with * @return String containing centered String * @throws NullPointerException if str or delim is null * @throws ArithmeticException if delim is the empty String */ public @Nonnull static String center( @Nonnull String str, int size, @Nonnull String delim ) { int sz = str.length(); int p = size - sz; if ( p < 1 ) { return str; } str = leftPad( str, sz + p / 2, delim ); str = rightPad( str, size, delim ); return str; } // Chomping //-------------------------------------------------------------------------- /** *

Remove the last newline, and everything after it from a String.

* * @param str String to chomp the newline from * @return String without chomped newline * @throws NullPointerException if str is null */ public @Nonnull static String chomp( @Nonnull String str ) { return chomp( str, "\n" ); } /** *

Remove the last value of a supplied String, and everything after * it from a String.

* * @param str String to chomp from * @param sep String to chomp * @return String without chomped ending * @throws NullPointerException if str or sep is null */ public @Nonnull static String chomp( @Nonnull String str, @Nonnull String sep ) { int idx = str.lastIndexOf( sep ); if ( idx != -1 ) { return str.substring( 0, idx ); } else { return str; } } /** *

Remove a newline if and only if it is at the end * of the supplied String.

* * @param str String to chomp from * @return String without chomped ending * @throws NullPointerException if str is null */ public @Nonnull static String chompLast( @Nonnull String str ) { return chompLast( str, "\n" ); } /** *

Remove a value if and only if the String ends with that value.

* * @param str String to chomp from * @param sep String to chomp * @return String without chomped ending * @throws NullPointerException if str or sep is null */ public @Nonnull static String chompLast( @Nonnull String str, @Nonnull String sep ) { if ( str.length() == 0 ) { return str; } String sub = str.substring( str.length() - sep.length() ); if ( sep.equals( sub ) ) { return str.substring( 0, str.length() - sep.length() ); } else { return str; } } /** *

Remove everything and return the last value of a supplied String, and * everything after it from a String.

* * @param str String to chomp from * @param sep String to chomp * @return String chomped * @throws NullPointerException if str or sep is null */ public @Nonnull static String getChomp( @Nonnull String str, @Nonnull String sep ) { int idx = str.lastIndexOf( sep ); if ( idx == str.length() - sep.length() ) { return sep; } else if ( idx != -1 ) { return str.substring( idx ); } else { return ""; } } /** *

Remove the first value of a supplied String, and everything before it * from a String.

* * @param str String to chomp from * @param sep String to chomp * @return String without chomped beginning * @throws NullPointerException if str or sep is null */ public @Nonnull static String prechomp( @Nonnull String str, @Nonnull String sep ) { int idx = str.indexOf( sep ); if ( idx != -1 ) { return str.substring( idx + sep.length() ); } else { return str; } } /** *

Remove and return everything before the first value of a * supplied String from another String.

* * @param str String to chomp from * @param sep String to chomp * @return String prechomped * @throws NullPointerException if str or sep is null */ public @Nonnull static String getPrechomp( @Nonnull String str, String sep ) { int idx = str.indexOf( sep ); if ( idx != -1 ) { return str.substring( 0, idx + sep.length() ); } else { return ""; } } // Chopping //-------------------------------------------------------------------------- /** *

Remove the last character from a String.

*

*

If the String ends in \r\n, then remove both * of them.

* * @param str String to chop last character from * @return String without last character * @throws NullPointerException if str is null */ public @Nonnull static String chop( @Nonnull String str ) { if ( "".equals( str ) ) { return ""; } if ( str.length() == 1 ) { return ""; } int lastIdx = str.length() - 1; String ret = str.substring( 0, lastIdx ); char last = str.charAt( lastIdx ); if ( last == '\n' ) { if ( ret.charAt( lastIdx - 1 ) == '\r' ) { return ret.substring( 0, lastIdx - 1 ); } } return ret; } /** *

Remove \n from end of a String if it's there. * If a \r precedes it, then remove that too.

* * @param str String to chop a newline from * @return String without newline * @throws NullPointerException if str is null */ public @Nonnull static String chopNewline( @Nonnull String str ) { int lastIdx = str.length() - 1; char last = str.charAt( lastIdx ); if ( last == '\n' ) { if ( str.charAt( lastIdx - 1 ) == '\r' ) { lastIdx--; } } else { lastIdx++; } return str.substring( 0, lastIdx ); } // Conversion //-------------------------------------------------------------------------- // spec 3.10.6 /** *

Escapes any values it finds into their String form.

*

*

So a tab becomes the characters '\\' and * 't'.

* * @param str String to escape values in * @return String with escaped values * @throws NullPointerException if str is null */ public @Nonnull static String escape( @Nonnull String str ) { // improved with code from [email protected] // unicode from him, and defaul for < 32's. int sz = str.length(); StringBuilder buffer = new StringBuilder( 2 * sz ); for ( int i = 0; i < sz; i++ ) { char ch = str.charAt( i ); // handle unicode if ( ch > 0xfff ) { buffer.append( "\\u" ).append( Integer.toHexString( ch ) ); } else if ( ch > 0xff ) { buffer.append( "\\u0" ).append( Integer.toHexString( ch ) ); } else if ( ch > 0x7f ) { buffer.append( "\\u00" ).append( Integer.toHexString( ch ) ); } else if ( ch < 32 ) { switch ( ch ) { case '\b': buffer.append( '\\' ); buffer.append( 'b' ); break; case '\n': buffer.append( '\\' ); buffer.append( 'n' ); break; case '\t': buffer.append( '\\' ); buffer.append( 't' ); break; case '\f': buffer.append( '\\' ); buffer.append( 'f' ); break; case '\r': buffer.append( '\\' ); buffer.append( 'r' ); break; default: if ( ch > 0xf ) { buffer.append( "\\u00" ).append( Integer.toHexString( ch ) ); } else { buffer.append( "\\u000" ).append( Integer.toHexString( ch ) ); } break; } } else { switch ( ch ) { case '\'': buffer.append( '\\' ); buffer.append( '\'' ); break; case '"': buffer.append( '\\' ); buffer.append( '"' ); break; case '\\': buffer.append( '\\' ); buffer.append( '\\' ); break; default: buffer.append( ch ); break; } } } return buffer.toString(); } // Padding //-------------------------------------------------------------------------- /** *

Repeat a String n times to form a * new string.

* * @param str String to repeat * @param repeat number of times to repeat str * @return String with repeated String * @throws NegativeArraySizeException if repeat < 0 * @throws NullPointerException if str is null */ public @Nonnull static String repeat( @Nonnull String str, int repeat ) { StringBuilder buffer = new StringBuilder( repeat * str.length() ); for ( int i = 0; i < repeat; i++ ) { buffer.append( str ); } return buffer.toString(); } /** *

Right pad a String with spaces.

*

*

The String is padded to the size of n.

* * @param str String to repeat * @param size number of times to repeat str * @return right padded String * @throws NullPointerException if str is null */ public @Nonnull static String rightPad( @Nonnull String str, int size ) { return rightPad( str, size, " " ); } /** *

Right pad a String with a specified string.

*

*

The String is padded to the size of n.

* * @param str String to pad out * @param size size to pad to * @param delim String to pad with * @return right padded String * @throws NullPointerException if str or delim is null * @throws ArithmeticException if delim is the empty String */ public @Nonnull static String rightPad( @Nonnull String str, int size, @Nonnull String delim ) { size = ( size - str.length() ) / delim.length(); if ( size > 0 ) { str += repeat( delim, size ); } return str; } /** *

Left pad a String with spaces.

*

*

The String is padded to the size of n.

* * @param str String to pad out * @param size size to pad to * @return left padded String * @throws NullPointerException if str or delim is null */ public @Nonnull static String leftPad( @Nonnull String str, int size ) { return leftPad( str, size, " " ); } /** * Left pad a String with a specified string. Pad to a size of n. * * @param str String to pad out * @param size size to pad to * @param delim String to pad with * @return left padded String * @throws NullPointerException if str or delim is null * @throws ArithmeticException if delim is the empty string */ public @Nonnull static String leftPad( @Nonnull String str, int size, @Nonnull String delim ) { size = ( size - str.length() ) / delim.length(); if ( size > 0 ) { str = repeat( delim, size ) + str; } return str; } // Stripping //-------------------------------------------------------------------------- /** *

Remove whitespace from the front and back of a String.

* * @param str the String to remove whitespace from * @return the stripped String */ public static String strip( String str ) { return strip( str, null ); } /** *

Remove a specified String from the front and back of a * String.

*

*

If whitespace is wanted to be removed, used the * {@link #strip(java.lang.String)} method.

* * @param str the String to remove a string from * @param delim the String to remove at start and end * @return the stripped String */ public static String strip( String str, @Nullable String delim ) { str = stripStart( str, delim ); return stripEnd( str, delim ); } /** *

Strip whitespace from the front and back of every String * in the array.

* * @param strs the Strings to remove whitespace from * @return the stripped Strings */ public static String[] stripAll( String... strs ) { return stripAll( strs, null ); } /** *

Strip the specified delimiter from the front and back of * every String in the array.

* * @param strs the Strings to remove a String from * @param delimiter the String to remove at start and end * @return the stripped Strings */ public static String[] stripAll( String[] strs, @Nullable String delimiter ) { if ( ( strs == null ) || ( strs.length == 0 ) ) { return strs; } int sz = strs.length; String[] newArr = new String[sz]; for ( int i = 0; i < sz; i++ ) { newArr[i] = strip( strs[i], delimiter ); } return newArr; } /** *

Strip any of a supplied String from the end of a String.

*

*

If the strip String is null, whitespace is * stripped.

* * @param str the String to remove characters from * @param strip the String to remove * @return the stripped String */ public static String stripEnd( String str, @Nullable String strip ) { if ( str == null ) { return null; } int end = str.length(); if ( strip == null ) { while ( ( end != 0 ) && Character.isWhitespace( str.charAt( end - 1 ) ) ) { end--; } } else { while ( ( end != 0 ) && ( strip.indexOf( str.charAt( end - 1 ) ) != -1 ) ) { end--; } } return str.substring( 0, end ); } /** *

Strip any of a supplied String from the start of a String.

*

*

If the strip String is null, whitespace is * stripped.

* * @param str the String to remove characters from * @param strip the String to remove * @return the stripped String */ public static String stripStart( String str, @Nullable String strip ) { if ( str == null ) { return null; } int start = 0; int sz = str.length(); if ( strip == null ) { while ( ( start != sz ) && Character.isWhitespace( str.charAt( start ) ) ) { start++; } } else { while ( ( start != sz ) && ( strip.indexOf( str.charAt( start ) ) != -1 ) ) { start++; } } return str.substring( start ); } // Case conversion //-------------------------------------------------------------------------- /** *

Convert a String to upper case, null String * returns null.

* * @param str the String to uppercase * @return the upper cased String */ public static String upperCase( String str ) { if ( str == null ) { return null; } return str.toUpperCase(); } /** *

Convert a String to lower case, null String * returns null.

* * @param str the string to lowercase * @return the lower cased String */ public static String lowerCase( String str ) { if ( str == null ) { return null; } return str.toLowerCase(); } /** *

Uncapitalise a String.

*

*

That is, convert the first character into lower-case. * null is returned as null.

* * @param str the String to uncapitalise * @return uncapitalised String */ public static String uncapitalise( String str ) { if ( str == null ) { return null; } else if ( str.length() == 0 ) { return ""; } else { return String.valueOf( Character.toLowerCase( str.charAt( 0 ) ) ) + str.substring( 1 ); } } /** *

Capitalise a String.

*

*

That is, convert the first character into title-case. * null is returned as null.

* * @param str the String to capitalise * @return capitalised String */ public static String capitalise( String str ) { if ( str == null ) { return null; } else if ( str.length() == 0 ) { return ""; } else { return String.valueOf( Character.toTitleCase( str.charAt( 0 ) ) ) + str.substring( 1 ); } } /** *

Swaps the case of String.

*

*

Properly looks after making sure the start of words * are Titlecase and not Uppercase.

*

*

null is returned as null.

* * @param str the String to swap the case of * @return the modified String */ public static String swapCase( String str ) { if ( str == null ) { return null; } int sz = str.length(); StringBuilder buffer = new StringBuilder( sz ); boolean whitespace = false; char ch; char tmp; for ( int i = 0; i < sz; i++ ) { ch = str.charAt( i ); if ( Character.isUpperCase( ch ) ) { tmp = Character.toLowerCase( ch ); } else if ( Character.isTitleCase( ch ) ) { tmp = Character.toLowerCase( ch ); } else if ( Character.isLowerCase( ch ) ) { if ( whitespace ) { tmp = Character.toTitleCase( ch ); } else { tmp = Character.toUpperCase( ch ); } } else { tmp = ch; } buffer.append( tmp ); whitespace = Character.isWhitespace( ch ); } return buffer.toString(); } /** *

Capitalise all the words in a String.

*

*

Uses {@link Character#isWhitespace(char)} as a * separator between words.

*

*

null will return null.

* * @param str the String to capitalise * @return capitalised String */ public static String capitaliseAllWords( String str ) { if ( str == null ) { return null; } int sz = str.length(); StringBuilder buffer = new StringBuilder( sz ); boolean space = true; for ( int i = 0; i < sz; i++ ) { char ch = str.charAt( i ); if ( Character.isWhitespace( ch ) ) { buffer.append( ch ); space = true; } else if ( space ) { buffer.append( Character.toTitleCase( ch ) ); space = false; } else { buffer.append( ch ); } } return buffer.toString(); } /** *

Uncapitalise all the words in a string.

*

*

Uses {@link Character#isWhitespace(char)} as a * separator between words.

*

*

null will return null.

* * @param str the string to uncapitalise * @return uncapitalised string */ public static String uncapitaliseAllWords( String str ) { if ( str == null ) { return null; } int sz = str.length(); StringBuilder buffer = new StringBuilder( sz ); boolean space = true; for ( int i = 0; i < sz; i++ ) { char ch = str.charAt( i ); if ( Character.isWhitespace( ch ) ) { buffer.append( ch ); space = true; } else if ( space ) { buffer.append( Character.toLowerCase( ch ) ); space = false; } else { buffer.append( ch ); } } return buffer.toString(); } // Nested extraction //-------------------------------------------------------------------------- /** *

Get the String that is nested in between two instances of the * same String.

*

*

If str is null, will * return null.

* * @param str the String containing nested-string * @param tag the String before and after nested-string * @return the String that was nested, or null * @throws NullPointerException if tag is null */ public static String getNestedString( String str, @Nonnull String tag ) { return getNestedString( str, tag, tag ); } /** *

Get the String that is nested in between two Strings.

* * @param str the String containing nested-string * @param open the String before nested-string * @param close the String after nested-string * @return the String that was nested, or null * @throws NullPointerException if open or close is null */ public static String getNestedString( String str, @Nonnull String open, @Nonnull String close ) { if ( str == null ) { return null; } int start = str.indexOf( open ); if ( start != -1 ) { int end = str.indexOf( close, start + open.length() ); if ( end != -1 ) { return str.substring( start + open.length(), end ); } } return null; } /** *

How many times is the substring in the larger String.

*

*

null returns 0.

* * @param str the String to check * @param sub the substring to count * @return the number of occurances, 0 if the String is null * @throws NullPointerException if sub is null */ public static int countMatches( @Nullable String str, @Nonnull String sub ) { if ( sub.equals( "" ) ) { return 0; } if ( str == null ) { return 0; } int count = 0; int idx = 0; while ( ( idx = str.indexOf( sub, idx ) ) != -1 ) { count++; idx += sub.length(); } return count; } // Character Tests //-------------------------------------------------------------------------- /** *

Checks if the String contains only unicode letters.

*

*

null will return false. * An empty String will return true.

* * @param str the String to check * @return true if only contains letters, and is non-null */ public static boolean isAlpha( String str ) { if ( str == null ) { return false; } int sz = str.length(); for ( int i = 0; i < sz; i++ ) { if ( !Character.isLetter( str.charAt( i ) ) ) { return false; } } return true; } /** *

Checks if the String contains only whitespace.

*

*

null will return false. An * empty String will return true.

* * @param str the String to check * @return true if only contains whitespace, and is non-null */ public static boolean isWhitespace( String str ) { if ( str == null ) { return false; } int sz = str.length(); for ( int i = 0; i < sz; i++ ) { if ( ( !Character.isWhitespace( str.charAt( i ) ) ) ) { return false; } } return true; } /** *

Checks if the String contains only unicode letters and * space (' ').

*

*

null will return false. An * empty String will return true.

* * @param str the String to check * @return true if only contains letters and space, * and is non-null */ public static boolean isAlphaSpace( String str ) { if ( str == null ) { return false; } int sz = str.length(); for ( int i = 0; i < sz; i++ ) { if ( ( !Character.isLetter( str.charAt( i ) ) ) && ( str.charAt( i ) != ' ' ) ) { return false; } } return true; } /** *

Checks if the String contains only unicode letters or digits.

*

*

null will return false. An empty * String will return true.

* * @param str the String to check * @return true if only contains letters or digits, * and is non-null */ public static boolean isAlphanumeric( String str ) { if ( str == null ) { return false; } int sz = str.length(); for ( int i = 0; i < sz; i++ ) { if ( !Character.isLetterOrDigit( str.charAt( i ) ) ) { return false; } } return true; } /** *

Checks if the String contains only unicode letters, digits * or space (' ').

*

*

null will return false. An empty * String will return true.

* * @param str the String to check * @return true if only contains letters, digits or space, * and is non-null */ public static boolean isAlphanumericSpace( String str ) { if ( str == null ) { return false; } int sz = str.length(); for ( int i = 0; i < sz; i++ ) { if ( ( !Character.isLetterOrDigit( str.charAt( i ) ) ) && ( str.charAt( i ) != ' ' ) ) { return false; } } return true; } /** *

Checks if the String contains only unicode digits.

*

*

null will return false. * An empty String will return true.

* * @param str the String to check * @return true if only contains digits, and is non-null */ public static boolean isNumeric( String str ) { if ( str == null ) { return false; } int sz = str.length(); for ( int i = 0; i < sz; i++ ) { if ( !Character.isDigit( str.charAt( i ) ) ) { return false; } } return true; } // Defaults //-------------------------------------------------------------------------- /** *

Returns either the passed in Object as a String, * or, if the Object is null, an empty * String.

* * @param obj the Object to check * @return the passed in Object's toString, or blank if it was * null */ public @Nonnull static String defaultString( Object obj ) { return defaultString( obj, "" ); } /** *

Returns either the passed in Object as a String, * or, if the Object is null, a passed * in default String.

* * @param obj the Object to check * @param defaultString the default String to return if str is * null * @return the passed in string, or the default if it was * null */ public @Nonnull static String defaultString( Object obj, @Nonnull String defaultString ) { return ( obj == null ) ? defaultString : obj.toString(); } // Reversing //-------------------------------------------------------------------------- /** *

Reverse a String.

*

*

null String returns null.

* * @param str the String to reverse * @return the reversed String */ public static String reverse( String str ) { if ( str == null ) { return null; } return new StringBuffer( str ).reverse().toString(); } /** *

Reverses a String that is delimited by a specific character.

*

*

The Strings between the delimiters are not reversed. * Thus java.lang.String becomes String.lang.java (if the delimiter * is '.').

* * @param str the String to reverse * @param delimiter the delimiter to use * @return the reversed String */ public @Nonnull static String reverseDelimitedString( @Nonnull String str, String delimiter ) { // could implement manually, but simple way is to reuse other, // probably slower, methods. String[] strs = split( str, delimiter ); reverseArray( strs ); return join( strs, delimiter ); } /** *

Reverses an array.

*

*

TAKEN FROM CollectionsUtils.

* * @param array the array to reverse */ private static void reverseArray( @Nonnull String... array ) { int i = 0; int j = array.length - 1; String tmp; while ( j > i ) { tmp = array[j]; array[j] = array[i]; array[i] = tmp; j--; i++; } } // Abbreviating //-------------------------------------------------------------------------- /** * Turn "Now is the time for all good men" into "Now is the time for..." *

* Specifically: *

* If str is less than max characters long, return it. * Else abbreviate it to (substring(str, 0, max-3) + "..."). * If maxWidth is less than 3, throw an IllegalArgumentException. * In no case will it return a string of length greater than maxWidth. * * @param maxWidth maximum length of result string */ public @Nonnull static String abbreviate( @Nonnull String s, int maxWidth ) { return abbreviate( s, 0, maxWidth ); } /** * Turn "Now is the time for all good men" into "...is the time for..." *

* Works like abbreviate(String, int), but allows you to specify a "left edge" * offset. Note that this left edge is not necessarily going to be the leftmost * character in the result, or the first * character following the ellipses, but it will appear somewhere in the result. * In no case will it return a string of length greater than maxWidth. * * @param offset left edge of source string * @param maxWidth maximum length of result string */ public @Nonnull static String abbreviate( @Nonnull String s, int offset, int maxWidth ) { if ( maxWidth < 4 ) { throw new IllegalArgumentException( "Minimum abbreviation width is 4" ); } if ( s.length() <= maxWidth ) { return s; } if ( offset > s.length() ) { offset = s.length(); } if ( ( s.length() - offset ) < ( maxWidth - 3 ) ) { offset = s.length() - ( maxWidth - 3 ); } if ( offset <= 4 ) { return s.substring( 0, maxWidth - 3 ) + "..."; } if ( maxWidth < 7 ) { throw new IllegalArgumentException( "Minimum abbreviation width with offset is 7" ); } if ( ( offset + ( maxWidth - 3 ) ) < s.length() ) { return "..." + abbreviate( s.substring( offset ), maxWidth - 3 ); } return "..." + s.substring( s.length() - ( maxWidth - 3 ) ); } // Difference //-------------------------------------------------------------------------- /** * Compare two strings, and return the portion where they differ. * (More precisely, return the remainder of the second string, * starting from where it's different from the first.) *

* E.g. strdiff("i am a machine", "i am a robot") -> "robot" * * @return the portion of s2 where it differs from s1; returns the empty string ("") if they are equal */ public static String difference( @Nonnull String s1, @Nonnull String s2 ) { int at = differenceAt( s1, s2 ); if ( at == -1 ) { return ""; } return s2.substring( at ); } /** * Compare two strings, and return the index at which the strings begin to differ. *

* E.g. strdiff("i am a machine", "i am a robot") -> 7 *

* * @return the index where s2 and s1 begin to differ; -1 if they are equal */ public static int differenceAt( @Nonnull String s1, @Nonnull String s2 ) { int i; for ( i = 0; ( i < s1.length() ) && ( i < s2.length() ); ++i ) { if ( s1.charAt( i ) != s2.charAt( i ) ) { break; } } if ( ( i < s2.length() ) || ( i < s1.length() ) ) { return i; } return -1; } /** * Fill all 'variables' in the given text with the values from the map. * Any text looking like '${key}' will get replaced by the value stored * in the namespace map under the 'key'. * * @param text * @param namespace * @return the interpolated text. */ public static String interpolate( String text, @Nonnull Map namespace ) { for ( Map.Entry entry : namespace.entrySet() ) { String key = entry.getKey().toString(); Object obj = entry.getValue(); if ( obj == null ) { throw new NullPointerException( "The value of the key '" + key + "' is null." ); } String value = obj.toString(); text = replace( text, "${" + key + "}", value ); if ( !key.contains( " " ) ) { text = replace( text, "$" + key, value ); } } return text; } /** * This is basically the inverse of {@link #addAndDeHump(String)}. * It will remove the 'replaceThis' parameter and uppercase the next * character afterwards. *
     * removeAndHump( "this-is-it", %quot;-" );
     * 
* will become 'ThisIsIt'. * * @param data * @param replaceThis * @return humped String */ public @Nonnull static String removeAndHump( @Nonnull String data, @Nonnull String replaceThis ) { String temp; StringBuilder out = new StringBuilder(); temp = data; StringTokenizer st = new StringTokenizer( temp, replaceThis ); while ( st.hasMoreTokens() ) { String element = st.nextToken(); out.append( capitalizeFirstLetter( element ) ); } return out.toString(); } /** * Convert the first character of the given String to uppercase. * This method will not trim of spaces! *

*

* Attention: this method will currently throw a * IndexOutOfBoundsException for empty strings! *

* * @param data the String to get capitalized * @return data string with the first character transformed to uppercase * @throws NullPointerException if data is null */ public @Nonnull static String capitalizeFirstLetter( @Nonnull String data ) { char firstLetter = Character.toTitleCase( data.substring( 0, 1 ).charAt( 0 ) ); String restLetters = data.substring( 1 ); return firstLetter + restLetters; } /** * Convert the first character of the given String to lowercase. * This method will not trim of spaces! *

*

* Attention: this method will currently throw a * IndexOutOfBoundsException for empty strings! *

* * @param data the String to get it's first character lower-cased. * @return data string with the first character transformed to lowercase * @throws NullPointerException if data is null */ public @Nonnull static String lowercaseFirstLetter( @Nonnull String data ) { char firstLetter = Character.toLowerCase( data.substring( 0, 1 ).charAt( 0 ) ); String restLetters = data.substring( 1 ); return firstLetter + restLetters; } /** * Take the input string and un-camel-case it. *

* 'ThisIsIt' will become 'this-is-it'. * * @param view * @return deHumped String */ public @Nonnull static String addAndDeHump( @Nonnull String view ) { StringBuilder sb = new StringBuilder(); for ( int i = 0; i < view.length(); i++ ) { if ( ( i != 0 ) && Character.isUpperCase( view.charAt( i ) ) ) { sb.append( '-' ); } sb.append( view.charAt( i ) ); } return sb.toString().trim().toLowerCase( Locale.ENGLISH ); } /** *

Quote and escape a String with the given character, handling null.

*

*

     * StringUtils.quoteAndEscape(null, *)    = null
     * StringUtils.quoteAndEscape("", *)      = ""
     * StringUtils.quoteAndEscape("abc", '"') = abc
     * StringUtils.quoteAndEscape("a\"bc", '"') = "a\"bc"
     * StringUtils.quoteAndEscape("a\"bc", '\'') = 'a\"bc'
     * 
* * @param source * @param quoteChar * @return the String quoted and escaped * @see #quoteAndEscape(String, char, char[], char[], char, boolean) * @see #quoteAndEscape(String, char, char[], char[], char, boolean) * */ public static String quoteAndEscape( @Nullable String source, char quoteChar ) { return quoteAndEscape( source, quoteChar, new char[]{ quoteChar }, new char[]{ ' ' }, '\\', false ); } /** *

Quote and escape a String with the given character, handling null.

* * @param source * @param quoteChar * @param quotingTriggers * @return the String quoted and escaped * @see #quoteAndEscape(String, char, char[], char[], char, boolean) * */ public static String quoteAndEscape( @Nullable String source, char quoteChar, @Nonnull char[] quotingTriggers ) { return quoteAndEscape( source, quoteChar, new char[]{ quoteChar }, quotingTriggers, '\\', false ); } /** * @param source * @param quoteChar * @param escapedChars * @param escapeChar * @param force * @return the String quoted and escaped * @see #quoteAndEscape(String, char, char[], char[], char, boolean) * */ public static String quoteAndEscape( @Nullable String source, char quoteChar, @Nonnull final char[] escapedChars, char escapeChar, boolean force ) { return quoteAndEscape( source, quoteChar, escapedChars, new char[]{ ' ' }, escapeChar, force ); } /** * @param source * @param quoteChar * @param escapedChars * @param quotingTriggers * @param escapeChar * @param force * @return the String quoted and escaped * */ public static String quoteAndEscape( @Nullable String source, char quoteChar, @Nonnull final char[] escapedChars, @Nonnull final char[] quotingTriggers, char escapeChar, boolean force ) { if ( source == null ) { return null; } if ( !force && source.startsWith( Character.toString( quoteChar ) ) && source.endsWith( Character.toString( quoteChar ) ) ) { return source; } String escaped = escape( source, escapedChars, escapeChar ); boolean quote = false; if ( force ) { quote = true; } else if ( !escaped.equals( source ) ) { quote = true; } else { for ( char quotingTrigger : quotingTriggers ) { if ( escaped.indexOf( quotingTrigger ) > -1 ) { quote = true; break; } } } if ( quote ) { return quoteChar + escaped + quoteChar; } return escaped; } /** * @param source * @param escapedChars * @param escapeChar * @return the String escaped * */ public static String escape( @Nullable String source, @Nonnull final char[] escapedChars, char escapeChar ) { if ( source == null ) { return null; } char[] eqc = new char[escapedChars.length]; System.arraycopy( escapedChars, 0, eqc, 0, escapedChars.length ); Arrays.sort( eqc ); StringBuilder buffer = new StringBuilder( source.length() ); for ( int i = 0; i < source.length(); i++ ) { final char c = source.charAt( i ); int result = Arrays.binarySearch( eqc, c ); if ( result > -1 ) { buffer.append( escapeChar ); } buffer.append( c ); } return buffer.toString(); } /** * Remove all duplicate whitespace characters and line terminators are replaced with a single * space. * * @param s a not null String * @return a string with unique whitespace. * */ public @Nonnull static String removeDuplicateWhitespace( @Nonnull String s ) { StringBuilder result = new StringBuilder(); int length = s.length(); boolean isPreviousWhiteSpace = false; for ( int i = 0; i < length; i++ ) { char c = s.charAt( i ); boolean thisCharWhiteSpace = Character.isWhitespace( c ); if ( !( isPreviousWhiteSpace && thisCharWhiteSpace ) ) { result.append( c ); } isPreviousWhiteSpace = thisCharWhiteSpace; } return result.toString(); } /** * Parses the given String and replaces all occurrences of * '\n', '\r' and '\r\n' with the system line separator. * * @param s a not null String * @return a String that contains only System line separators. * @see #unifyLineSeparators(String, String) * */ public static String unifyLineSeparators( @Nullable String s ) { return unifyLineSeparators( s, System.getProperty( "line.separator" ) ); } /** * Parses the given String and replaces all occurrences of * '\n', '\r' and '\r\n' with the system line separator. * * @param s a not null String * @param ls the wanted line separator ("\n" on UNIX), if null using the System line separator. * @return a String that contains only System line separators. * @throws IllegalArgumentException if ls is not '\n', '\r' and '\r\n' characters. * */ public static String unifyLineSeparators( @Nullable String s, @Nullable String ls ) { if ( s == null ) { return null; } if ( ls == null ) { ls = System.getProperty( "line.separator" ); } if ( !( ls.equals( "\n" ) || ls.equals( "\r" ) || ls.equals( "\r\n" ) ) ) { throw new IllegalArgumentException( "Requested line separator is invalid." ); } int length = s.length(); StringBuilder buffer = new StringBuilder( length ); for ( int i = 0; i < length; i++ ) { if ( s.charAt( i ) == '\r' ) { if ( ( i + 1 ) < length && s.charAt( i + 1 ) == '\n' ) { i++; } buffer.append( ls ); } else if ( s.charAt( i ) == '\n' ) { buffer.append( ls ); } else { buffer.append( s.charAt( i ) ); } } return buffer.toString(); } /** *

Checks if String contains a search character, handling null. * This method uses {@link String#indexOf(int)}.

*

*

A null or empty ("") String will return false.

*

*

     * StringUtils.contains(null, *)    = false
     * StringUtils.contains("", *)      = false
     * StringUtils.contains("abc", 'a') = true
     * StringUtils.contains("abc", 'z') = false
     * 
* * @param str the String to check, may be null * @param searchChar the character to find * @return true if the String contains the search character, * false if not or null string input * */ @SuppressWarnings( "ConstantConditions" ) public static boolean contains( @Nullable String str, char searchChar ) { return !isEmpty( str ) && str.indexOf( searchChar ) >= 0; } /** *

Checks if String contains a search String, handling null. * This method uses {@link String#indexOf(int)}.

*

*

A null String will return false.

*

*

     * StringUtils.contains(null, *)     = false
     * StringUtils.contains(*, null)     = false
     * StringUtils.contains("", "")      = true
     * StringUtils.contains("abc", "")   = true
     * StringUtils.contains("abc", "a")  = true
     * StringUtils.contains("abc", "z")  = false
     * 
* * @param str the String to check, may be null * @param searchStr the String to find, may be null * @return true if the String contains the search String, * false if not or null string input * */ public static boolean contains( @Nullable String str, @Nullable String searchStr ) { return !( str == null || searchStr == null ) && str.contains( searchStr ); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy