// ===========================================================================
// CONTENT : CLASS StringUtil
// AUTHOR : Manfred Duchrow
// VERSION : 2.0 - 21/03/2003
// HISTORY :
// 10/07/1999 duma CREATED
// 09/12/1999 duma added -> SPACE, repeat()
// moved -> from package com.mdcs.util
// 25/01/2000 duma moved -> from package com.mdcs.text
// 09/02/2000 duma changed -> renamed SPACE to CH_SPACE
// added -> CH_CR, CH_TAB, ..., STR_SPACE, STR_NEWLINE, ...
// 11/01/2002 duma added -> indexOf(), indexOfIgnoreCase(), contains(), containsIgnoreCase()
// 17/05/2002 duma added -> copyFrom()
// 03/07/2002 duma added -> cutHead(), prefix(), suffix()
// 06/07/2002 duma added -> indexOf() and contains() for StringPattern and reverse()
// 15/08/2002 duma added -> upTo(), startingFrom(), asMap()
// 29/09/2002 duma added -> allParts() and allSubstrings() that don't skip empty elements
// 06/03/2003 duma changed -> append() now uses System.arraycopy()
// added -> remove( String[], String[] ), remove( String[], String )
// removeNull( String[] )
// 21/03/2003 duma added -> leftPad(), leftPadCh(), rightPad(), rightPadCh() for int values
//
// Copyright (c) 1999-2003, by Manfred Duchrow. All rights reserved.
// ===========================================================================
package org.pf.text;
// ===========================================================================
// IMPORT
// ===========================================================================
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.ArrayList;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* The sole instance of this class provides several convienience methods
* for string manipulation such as substring replacement or character repetition.
*
* @author Manfred Duchrow
* @version 2.0
*/
public class StringUtil
{
// =========================================================================
// CONSTANTS
// =========================================================================
/** Constant for the space character **/
public static final char CH_SPACE = '\u0020' ;
/** Constant for the new line character **/
public static final char CH_NEWLINE = '\n' ;
/** Constant for the carriage return character **/
public static final char CH_CR = '\r' ;
/** Constant for the tabulator character **/
public static final char CH_TAB = '\t' ;
/** Constant for the String representation of the space character **/
public static final String STR_SPACE = "\u0020" ;
/** Constant for the String representation of the new line character **/
public static final String STR_NEWLINE = "\n" ;
/** Constant for the String representation of the carriage return character **/
public static final String STR_CR = "\r" ;
/** Constant for the String representation of the tabulator character **/
public static final String STR_TAB = "\t" ;
private static final String WORD_DELIM = STR_SPACE + STR_TAB
+ STR_NEWLINE + STR_CR ;
// =========================================================================
// CLASS VARIABLES
// =========================================================================
private static StringUtil singleton = null ;
private static StringUtil getSingleton() { return singleton ; }
private static void setSingleton( StringUtil inst ) { singleton = inst ; }
// =========================================================================
// PUBLIC CLASS METHODS
// =========================================================================
/**
* Returns the one and only instance of this class.
*/
public static StringUtil current()
{
if ( getSingleton() == null )
setSingleton( new StringUtil() ) ;
return getSingleton() ;
} // current()
// =========================================================================
// PUBLIC INSTANCE METHODS
// =========================================================================
/**
* Returns the given string with all found oldSubStr replaced by newSubStr. <br>
*
* Example: StringUtil.current().replaceAll( "Seven of ten", "even", "ix" ) ;<br>
* results in: "Six of ten"
*
* @param sourceStr The string that should be checked for occurrences of oldSubStr
* @param oldSubStr The string that is searched for in sourceStr
* @param newSubStr The new string that is placed everywhere the oldSubStr was found
* @return The original string with all found substrings replaced by new strings
*/
public String replaceAll( String sourceStr, String oldSubStr, String newSubStr )
{
String part = null ;
String result = "" ;
int index = -1 ;
int subLen = 0 ;
subLen = oldSubStr.length() ;
part = sourceStr ;
while ( ( part.length() > 0 ) && ( subLen > 0 ) )
{
index = part.indexOf( oldSubStr ) ;
if ( index >= 0 )
{
result = result + part.substring( 0, index ) + newSubStr ;
part = part.substring( index + subLen ) ;
}
else
{
result = result + part ;
part = "" ;
}
} // while
return result ;
} // replaceAll()
// -------------------------------------------------------------------------
/**
* Returns a string with size of count and all characters initialized with ch. <br>
*
* @param ch the character to be repeated in the result string.
* @param count the number of times the given character should occur in the result string.
* @return A string containing <i>count</i> characters <i>ch</i>.
*/
public String repeat( char ch, int count )
{
StringBuffer buffer = null ;
buffer = new StringBuffer( count ) ;
for ( int i = 1 ; i <= count ; i++ )
{
buffer.append( ch ) ;
}
return ( buffer.toString() ) ;
} // repeat()
// -------------------------------------------------------------------------
/**
* Returns an array of substrings of the given text. <br>
* The delimiters between the substrings are the whitespace characters
* SPACE, NEWLINE, CR and TAB.
*
* @see #parts(String, String)
* @param text The string that should be splitted into whitespace separated words
* @return An array of substrings of the given text
*/
public String[] words( String text )
{
return this.parts( text, WORD_DELIM ) ;
} // words()
// -------------------------------------------------------------------------
/**
* Returns an array of substrings of the given text. <br>
* The separators between the substrings are the given delimiters.
* Each character in the delimiter string is treated as a separator.
* <br>
* All consecutive delimiters are treated as one delimiter, that is there
* will be no empty strings in the result.
*
* @see #allParts(String, String)
* @see #substrings(String, String)
* @see #allSubstrings(String, String)
* @param text The string that should be splitted into substrings
* @param delimiters All characters that should be recognized as a separator or substrings
* @return An array of substrings of the given text
*/
public String[] parts( String text, String delimiters )
{
return this.parts( text, delimiters, false ) ;
} // parts()
// -------------------------------------------------------------------------
/**
* Returns an array of substrings of the given text. <br>
* The separators between the substrings are the given delimiters.
* Each character in the delimiter string is treated as a separator.
* <br>
* For each delimiter that is followed immediately by another delimiter an
* empty string will be added to the result. There are no empty strings added
* to the result for a delimiter at the very beginning of at the very end.
* <p>
* Examples:
* <p>
* allParts( "/A/B//", "/" ) --> { "A", "B", "" } <br>
* allParts( "/A,B/C;D", ",;/" ) --> { "A", "B", "C", "D" } <br>
* allParts( "A/B,C/D", "," ) --> { "A/B", "C/D" } <br>
*
* @see #parts(String, String)
* @see #substrings(String, String)
* @see #allSubstrings(String, String)
* @param text The string that should be splitted into substrings
* @param delimiters All characters that should be recognized as a separator or substrings
* @return An array of substrings of the given text
*/
public String[] allParts( String text, String delimiters )
{
return this.parts( text, delimiters, true ) ;
} // allParts()
// -------------------------------------------------------------------------
/**
* Returns the given text split up into an array of strings, at
* the occurrances of the separator string.
*
* In contrary to method parts() the separator is a one or many
* character sequence delimiter. That is, only the exact sequence
* of the characters in separator identifies the end of a substring.
* Subsequent occurences of separator will be skipped. Therefore
* no empty strings ("") will be in the result array.
*
* @see #allSubstrings(String, String)
* @see #parts(String, String)
* @see #allParts(String, String)
* @param text The text to be split up
* @param separator The string that separates the substrings
* @return An array of substrings not containing any separator anymore
*/
public String[] substrings( String text, String separator )
{
return this.substrings( text, separator, false ) ;
} // substrings()
// -------------------------------------------------------------------------
/**
* Returns the given text split up into an array of strings, at
* the occurrances of the separator string.
*
* In contrary to method allParts() the separator is a one or many
* character sequence delimiter. That is, only the exact sequence
* of the characters in separator identifies the end of a substring.
* Subsequent occurences of separator are not skipped. They are added
* as empty strings to the result.
*
* @see #substrings(String, String)
* @see #parts(String, String)
* @see #allParts(String, String)
* @param text The text to be split up
* @param separator The string that separates the substrings
* @return An array of substrings not containing any separator anymore
*/
public String[] allSubstrings( String text, String separator )
{
return this.substrings( text, separator, true ) ;
} // allSubstrings()
// -------------------------------------------------------------------------
/**
* Returns the first substring that is enclosed by the specified delimiters.
* <br>
* The delimiters are not included in the return string.
* <p>
* Example:<br>
* getDelimitedSubstring( "This {placeholder} belongs to me", "{", "}" )
* --> returns "placeholder"
*
* @param text The input string that contains the delimited part
* @param startDelimiter The start delimiter of the substring
* @param endDelimiter The end delimiter of the substring
* @return The substring or an empty string, if no delimiters are found.
*/
public String getDelimitedSubstring( String text, String startDelimiter,
String endDelimiter )
{
int start ;
int stop ;
String subStr = "" ;
if ( ( text != null ) && ( startDelimiter != null )
&& ( endDelimiter != null ) )
{
start = text.indexOf( startDelimiter ) ;
if ( start >= 0 )
{
stop = text.indexOf( endDelimiter, start + 1 ) ;
if ( stop > start )
subStr = text.substring( start + 1, stop ) ;
}
}
return subStr ;
} // getDelimitedSubstring()
// -------------------------------------------------------------------------
/**
* Returns the first substring that is enclosed by the specified delimiter. <br>
* The delimiters are not included in the return string.
* <p>
* Example:<br>
* getDelimitedSubstring( "File 'text.txt' not found.", "'", "'" )
* --> returns "text.txt"
*
* @param text The input string that contains the delimited part
* @param delimiter The start and end delimiter of the substring
* @return The substring or an empty string, if no delimiters are found.
*/
public String getDelimitedSubstring( String text, String delimiter )
{
return this.getDelimitedSubstring( text, delimiter, delimiter ) ;
} // getDelimitedSubstring()
// -------------------------------------------------------------------------
/**
* Prints the stack trace of the specified throwable to a
* string and returns it.
*/
public String stackTrace( Throwable throwable )
{
StringWriter sw = new StringWriter() ;
PrintWriter pw = new PrintWriter( sw ) ;
throwable.printStackTrace( pw ) ;
pw.close() ;
return sw.toString() ;
} // stackTrace()
// -------------------------------------------------------------------------
/**
* Returns the given string filled (on the left) up to the specified
* length with the given character. <br>
* Example: leftPadCh( "12", 6, '0' ) --> "000012"
*/
public String leftPadCh( String str, int len, char ch )
{
return this.padCh( str, len, ch, true ) ;
} // leftPadCh()
// -------------------------------------------------------------------------
/**
* Returns the given string filled (on the left) up to the specified
* length with spaces. <br>
* Example: leftPad( "XX", 4 ) --> " XX"
*
* @param str The string that has to be filled up to the specified length
* @param len The length of the result string
*/
public String leftPad( String str, int len )
{
return this.leftPadCh( str, len, CH_SPACE ) ;
} // leftPad()
// -------------------------------------------------------------------------
/**
* Returns the given integer as string filled (on the left) up to the
* specified length with the given fill character. <br>
* Example: leftPad( 24, 5, '*' ) --> "***24"
*/
public String leftPadCh( int value, int len, char fillChar )
{
return this.leftPadCh( Integer.toString(value), len, fillChar ) ;
} // leftPadCh()
// -------------------------------------------------------------------------
/**
* Returns the given integer as string filled (on the left) up to the
* specified length with zeroes. <br>
* Example: leftPad( 12, 4 ) --> "0012"
*/
public String leftPad( int value, int len )
{
return this.leftPadCh( value, len, '0' ) ;
} // leftPad()
// -------------------------------------------------------------------------
/**
* Returns the given string filled (on the right) up to the specified
* length with the given character. <br>
* Example: rightPadCh( "34", 5, 'X' ) --> "34XXX"
*/
public String rightPadCh( String str, int len, char ch )
{
return this.padCh( str, len, ch, false ) ;
} // rightPadCh()
// -------------------------------------------------------------------------
/**
* Returns the given string filled (on the right) up to the specified
* length with spaces. <br>
* Example: rightPad( "88", 6 ) --> "88 "
*/
public String rightPad( String str, int len )
{
return this.rightPadCh( str, len, CH_SPACE ) ;
} // rightPad()
// -------------------------------------------------------------------------
/**
* Returns the given integer as string filled (on the right) up to the
* specified length with the given character. <br>
* Example: rightPad( "32", 4, '#' ) --> "32##"
*/
public String rightPadCh( int value, int len, char fillChar )
{
return this.rightPadCh( Integer.toString(value), len, fillChar ) ;
} // rightPad()
// -------------------------------------------------------------------------
/**
* Returns the given integer as string filled (on the right) up to the
* specified length with spaces. <br>
* Example: rightPad( "17", 5 ) --> "17 "
*/
public String rightPad( int value, int len )
{
return this.rightPadCh( value, len, CH_SPACE ) ;
} // rightPad()
// -------------------------------------------------------------------------
/**
* Returns the given string filled equally left and right
* up to the specified length with the given character. <br>
* Example: centerCh( "A", 5, '_' ) --> "__A__" <br>
* Example: centerCh( "XX", 7, '+' ) --> "++XX+++"
*/
public String centerCh( String str, int len, char ch )
{
String buffer = null ;
int missing = len - str.length() ;
int half = 0 ;
if ( missing <= 0 )
return str ;
half = missing / 2 ;
buffer = this.rightPadCh( str, len-half, ch ) ;
return this.leftPadCh( buffer, len, ch ) ;
} // centerCh()
// -------------------------------------------------------------------------
/**
* Returns the given string filled (on the right and right)
* up to the specified length with spaces. <br>
* Example: center( "Mike", 10 ) --> " Mike "
*/
public String center( String str, int len )
{
return this.centerCh( str, len, CH_SPACE ) ;
} // center()
// -------------------------------------------------------------------------
/**
* Returns the given string array extended by one element
* that hold the specified string.
*/
public String[] append( String[] strings, String string )
{
String[] appStr = { string } ;
return this.append( strings, appStr ) ;
} // append()
// -------------------------------------------------------------------------
/**
* Returns an array of strings that contains all strings given
* by the first and second string array. The strings from the
* second array will be added at the end of the first array.
*
* @param strings The array of string to which to append
* @param appendStrings The string to be appended to the first array
*/
public String[] append( String[] strings, String[] appendStrings )
{
String[] newStrings = null ;
if ( strings == null )
return appendStrings ;
if ( appendStrings == null )
return strings ;
newStrings = new String[strings.length + appendStrings.length] ;
System.arraycopy( strings, 0, newStrings, 0, strings.length ) ;
System.arraycopy( appendStrings, 0, newStrings, strings.length, appendStrings.length ) ;
return newStrings ;
} // append()
// -------------------------------------------------------------------------
/**
* Returns an array of strings that contains all strings given
* in the first plus the specified string to append, if it is not
* already in the given array.
*/
public String[] appendIfNotThere( String[] strings, String appendString )
{
if ( this.contains( strings, appendString ) )
return strings ;
else
return this.append( strings, appendString ) ;
} // appendIfNotThere()
// -------------------------------------------------------------------------
/**
* Returns an array of strings that contains all strings given
* in the first plus all strings of the second array that are not
* already in the first array.
*/
public String[] appendIfNotThere( String[] strings, String[] appendStrings )
{
String[] newStrings = strings ;
if ( appendStrings == null )
return newStrings ;
for ( int i = 0 ; i < appendStrings.length ; i++ )
{
newStrings = this.appendIfNotThere( newStrings, appendStrings[i] ) ;
}
return newStrings ;
} // appendIfNotThere()
// -------------------------------------------------------------------------
/**
* Removes all string of the second array from the first array.
* Returns a new array of string that contains all remaining strings of the
* original strings array.
*
* @param strings The array from which to remove the strings
* @param removeStrings The strings to be removed
*/
public String[] remove( String[] strings, String[] removeStrings )
{
if ( ( strings == null ) || ( removeStrings == null )
|| ( strings.length == 0 ) || ( removeStrings.length == 0 ) )
{
return strings ;
}
return this.removeFromStringArray( strings, removeStrings ) ;
} // remove()
// -------------------------------------------------------------------------
/**
* Removes the given string from the specified string array.
* Returns a new array of string that contains all remaining strings of the
* original strings array.
*
* @param strings The array from which to remove the string
* @param removeString The string to be removed
*/
public String[] remove( String[] strings, String removeString )
{
String[] removeStrings = { removeString } ;
return this.remove( strings, removeStrings ) ;
} // remove()
// -------------------------------------------------------------------------
/**
* Removes all null values from the given string array.
* Returns a new string array that contains all none null values of the
* input array.
*
* @param strings The array to be cleared of null values
*/
public String[] removeNull( String[] strings )
{
if ( strings == null )
return strings ;
return this.removeFromStringArray( strings, null ) ;
} // removeNull()
// -------------------------------------------------------------------------
/**
* Returns a string that contains all given strings concatenated
* and separated by the specified separator.
*
* @param strings The array of strings that should be concatenated
* @param separator The separator between the strings
* @return One string containing the concatenated strings separated by separator
*/
public String asString ( String[] strings, String separator )
{
StringBuffer buffer = null ;
buffer = new StringBuffer( strings.length * 20 ) ;
if ( strings.length > 0 )
{
buffer.append( strings[0].toString() ) ;
for ( int i = 1 ; i < strings.length ; i++ )
{
buffer.append( separator ) ;
if ( strings[i] != null )
buffer.append( strings[i] ) ;
}
}
return buffer.toString() ;
} // asString()
// -------------------------------------------------------------------------
/**
* Returns a string that contains all given strings concatenated
* and separated by comma.
*
* @param strings The array of strings that should be concatenated
* @return One string containing the concatenated strings separated by comma (",")
*/
public String asString ( String[] strings )
{
return this.asString( strings, "," ) ;
} // asString()
// -------------------------------------------------------------------------
/**
* Returns the index of the first string in the given string array that
* matches the specified string pattern.
* If no string is found in the array the result is -1.
*
* @param strArray An array of string (may contain null elements)
* @param pattern The pattern the searched string must match
* @return The index of the matching string in the array or -1 if not found
*/
public int indexOf( String[] strArray, StringPattern pattern )
{
if ( ( strArray == null ) || ( strArray.length == 0 ) )
return -1 ;
boolean found = false ;
for ( int i = 0 ; i < strArray.length ; i++ )
{
if ( strArray[i] == null )
{
if ( pattern == null )
found = true ;
}
else
{
if ( pattern != null )
found = pattern.matches( strArray[i] ) ;
}
if ( found )
return i ;
}
return -1 ;
} // indexOf()
// -------------------------------------------------------------------------
/**
* Returns the index of the specified string in the given string array.
* It returns the index of the first occurrence of the string.
* If the string is not found in the array the result is -1.
* The comparison of the strings is case-sensitive!
*
* @param strArray An array of string (may contain null elements)
* @param searchStr The string to be looked up in the array (null allowed)
* @return The index of the string in the array or -1 if not found
*/
public int indexOf( String[] strArray, String searchStr )
{
return this.indexOfString( strArray, searchStr, false ) ;
} // indexOf()
// -------------------------------------------------------------------------
/**
* Returns the index of the specified string in the given string array.
* It returns the index of the first occurrence of the string.
* If the string is not found in the array the result is -1.
* The comparison of the strings is case-insensitive!
*
* @param strArray An array of string (may contain null elements)
* @param searchStr The string to be looked up in the array (null allowed)
* @return The index of the string in the array or -1 if not found
*/
public int indexOfIgnoreCase( String[] strArray, String searchStr )
{
return this.indexOfString( strArray, searchStr, true ) ;
} // indexOfIgnoreCase()
// -------------------------------------------------------------------------
/**
* Returns whether or not the specified string can be found
* in the given string array.
*
* @param strArray An array of string (may contain null elements)
* @param searchStr The string to be looked up in the array (null allowed)
* @param ignoreCase Defines whether or not the comparison is case-sensitive.
* @return true, if the specified array contains the given string
*/
public boolean contains( String[] strArray, String searchStr, boolean ignoreCase )
{
if ( ignoreCase )
return this.containsIgnoreCase( strArray, searchStr ) ;
else
return this.contains( strArray, searchStr ) ;
} // contains()
// -------------------------------------------------------------------------
/**
* Returns whether or not a string can be found in the given string array
* that matches the specified string pattern.
*
* @param strArray An array of string (may contain null elements)
* @param pattern The string pattern to match against in the array (null allowed)
* @return true, if the specified array contains a string matching the pattern
*/
public boolean contains( String[] strArray, StringPattern pattern)
{
return ( this.indexOf( strArray, pattern ) >= 0 ) ;
} // contains()
// -------------------------------------------------------------------------
/**
* Returns whether or not the specified string can be found
* in the given string array.
* The comparison of the strings is case-sensitive!
*
* @param strArray An array of string (may contain null elements)
* @param searchStr The string to be looked up in the array (null allowed)
* @return true, if the specified array contains the given string
*/
public boolean contains( String[] strArray, String searchStr )
{
return ( this.indexOf( strArray, searchStr ) >= 0 ) ;
} // contains()
// -------------------------------------------------------------------------
/**
* Returns whether or not the specified string can be found
* in the given string array.
* The comparison of the strings is case-insensitive!
*
* @param strArray An array of string (may contain null elements)
* @param searchStr The string to be looked up in the array (null allowed)
* @return true, if the specified array contains the given string
*/
public boolean containsIgnoreCase( String[] strArray, String searchStr )
{
return ( this.indexOfIgnoreCase( strArray, searchStr ) >= 0 ) ;
} // containsIgnoreCase()
// -------------------------------------------------------------------------
/**
* Returns all elements of string array <i>from</i> in a new array
* from index start up to the end.
* If start index is larger than the array's length, an empty array will be
* returned.
*
* @param from The string array the elements should be copied from
* @param start Index of the first element to copy
*/
public String[] copyFrom( String[] from, int start )
{
if ( from == null )
return null ;
return this.copyFrom( from, start, from.length - 1 ) ;
} // copyFrom()
// -------------------------------------------------------------------------
/**
* Returns all elements of string array <i>from</i> in a new array
* from index start up to index end (inclusive).
* If end is larger than the last valid index, it will be reduced
* to the last index.
* If end index is less than start index, an empty array will be
* returned.
*
* @param from The string array the elements should be copied from
* @param start Index of the first element to copy
* @param end Index of last element to be copied
*/
public String[] copyFrom( String[] from, int start, int end )
{
String[] result ;
int count ;
int stop = end ;
if ( from == null )
return null ;
if ( stop > ( from.length - 1 ) )
stop = from.length - 1 ;
count = stop - start + 1 ;
if ( count < 1 )
return new String[0] ;
result = new String[count] ;
System.arraycopy( from, start, result, 0, count ) ;
return result ;
} // copyFrom()
// -------------------------------------------------------------------------
/**
* Returns the portion of the given string that comes before the last
* occurance of the specified separator. <br>
* If the separator could not be found in the given string, then the
* string is returned unchanged.
* <p>
* Examples:
* <p>
* cutTail( "A/B/C", "/" ) ; // returns "A/B"
* <br>
* cutTail( "A/B/C", "," ) ; // returns "A/B/C"
* <p>
* @see #prefix( String, String )
* @see #suffix( String, String )
* @see #cutHead( String, String )
* @see #startingFrom( String, String )
* @see #upTo( String, String )
* @param text The string from which to cut off the tail
* @param separator The separator from where to cut off
* @return the string without the separator and without the characters after the separator
*/
public String cutTail( String text, String separator )
{
int index ;
if ( ( text == null ) || ( separator == null ) )
return text ;
index = text.lastIndexOf( separator ) ;
if ( index < 0 )
return text ;
return text.substring( 0, index ) ;
} // cutTail()
// ------------------------------------------------------------------------
/**
* Returns the portion of the given string that stands after the last
* occurance of the specified separator. <br>
* If the separator could not be found in the given string, then the
* string is returned unchanged.
* <p>
* Examples:
* <p>
* cutHead( "A/B/C", "/" ) ; // returns "C"
* <br>
* cutHead( "A/B/C", "," ) ; // returns "A/B/C"
* <p>
* @see #prefix( String, String )
* @see #cutTail( String, String )
* @see #suffix( String, String )
* @see #startingFrom( String, String )
* @see #upTo( String, String )
* @param text The string from which to cut off the head
* @param separator The separator up to which to cut off
* @return the string without the separator and without the characters before the separator
*/
public String cutHead( String text, String separator )
{
int index ;
if ( ( text == null ) || ( separator == null ) )
return text ;
index = text.lastIndexOf( separator ) ;
if ( index < 0 )
return text ;
return text.substring( index + 1 ) ;
} // cutHead()
// ------------------------------------------------------------------------
/**
* Returns a string array with two elements where the first is the attribute
* name and the second is the attribute value.
* Splits the given string at the first occurance of separator and returns
* the piece before the separator in element 0 and the piece after the
* separator in the returned array.
* If the separator is not found, the first element contains the full
* string and the second an empty string.
*
* @param str The string that contains the name-value pair
* @param separator The separator between name and value
*/
public String[] splitNameValue( String str, String separator )
{
String[] result = { "", "" } ;
int index ;
if ( str != null )
{
index = str.indexOf( separator ) ;
if ( index > 0 )
{
result[0] = str.substring( 0, index ) ;
result[1] = str.substring( index + separator.length() ) ;
}
else
{
result[0] = str ;
}
}
return result ;
} // splitNameValue()
// -------------------------------------------------------------------------
/**
* Returns the substring of the given string that comes before the
* first occurance of the specified separator.
* If the string starts with a separator, the result will be an empty string.
* If the string doesn't contain the separator the method returns null.
* <p>
* Examples:
* <p>
* prefix( "A/B/C", "/" ) ; // returns "A"
* <br>
* prefix( "A/B/C", "," ) ; // returns null
* <p>
* @see #suffix( String, String )
* @see #cutTail( String, String )
* @see #cutHead( String, String )
* @see #startingFrom( String, String )
* @see #upTo( String, String )
* @param str The string of which the prefix is desired
* @param separator Separates the prefix from the rest of the string
*/
public String prefix( String str, String separator )
{
return this.prefix( str, separator, true ) ;
} // prefix()
// -------------------------------------------------------------------------
/**
* Returns the substring of the given string that comes after the
* first occurance of the specified separator.
* If the string ends with a separator, the result will be an empty string.
* If the string doesn't contain the separator the method returns null.
* <p>
* Examples:
* <p>
* suffix( "A/B/C", "/" ) ; // returns "B/C"
* <br>
* suffix( "A/B/C", "," ) ; // returns null
* <p>
* @see #prefix( String, String )
* @see #cutTail( String, String )
* @see #cutHead( String, String )
* @see #startingFrom( String, String )
* @see #upTo( String, String )
* @param str The string of which the suffix is desired
* @param separator Separates the suffix from the rest of the string
*/
public String suffix( String str, String separator )
{
return this.suffix( str, separator, true ) ;
} // suffix()
// -------------------------------------------------------------------------
/**
* Returns the substring of the given string that comes before the
* first occurance of the specified separator.
* If the string starts with a separator, the result will be an empty string.
* If the string doesn't contain the separator the method returns the
* whole string unchanged.
* <p>
* Examples:
* <p>
* upTo( "A/B/C", "/" ) ; // returns "A"
* <br>
* upTo( "A/B/C", "," ) ; // returns "A/B/C"
* <br>
* upTo( "/A/B/C", "/" ) ; // returns ""
* <p>
* @see #prefix( String, String )
* @see #cutTail( String, String )
* @see #cutHead( String, String )
* @see #startingFrom( String, String )
* @see #suffix( String, String )
* @param str The string of which the prefix is desired
* @param separator Separates the prefix from the rest of the string
*/
public String upTo( String str, String separator )
{
return this.prefix( str, separator, false ) ;
} // upTo()
// -------------------------------------------------------------------------
/**
* Returns the substring of the given string that comes after the
* first occurance of the specified separator.
* If the string doesn't contain the separator the method returns the
* whole string unchanged.
* <p>
* Examples:
* <p>
* startingFrom( "A/B/C", "/" ) ; // returns "B/C"
* <br>
* startingFrom( "A/B/C", "," ) ; // returns "A/B/C"
* <p>
* @see #prefix( String, String )
* @see #cutTail( String, String )
* @see #cutHead( String, String )
* @see #suffix( String, String )
* @see #upTo( String, String )
* @param str The string of which the suffix is desired
* @param separator Separates the suffix from the rest of the string
*/
public String startingFrom( String str, String separator )
{
return this.suffix( str, separator, false ) ;
} // startingFrom()
// -------------------------------------------------------------------------
/**
* Returns a string that contains all characters of the given string in
* reverse order.
*/
public String reverse( String str )
{
if ( str == null )
return null ;
char[] newStr = new char[str.length()] ;
StringCharacterIterator iterator = new StringCharacterIterator(str) ;
int i = 0 ;
for(char ch = iterator.last(); ch != CharacterIterator.DONE; ch = iterator.previous())
{
newStr[i] = ch ;
i++ ;
}
return new String( newStr ) ;
} // reverse()
// -------------------------------------------------------------------------
/**
* Returns the given map with new entries from the specified String.
* If the specified map is null a new empty java.util.Hashtable will be
* created.
* <br>
* The string is split up into elements separated by the elementSeparator
* parameter. If this parameter is null the default separator "," is used.
* <br>
* After that each part is split up to a key-value pair separated by the
* keyValueSeparator parameter. If this parameter is null the default "=" is
* used.
* <br>
* Then the key-value pairs are added to the map and the map is returned.
* <p>
* <b>Be aware that all leading and trailing whitespaces of keys and values
* will be removed!</b>
*
* @param str The string that contains the list of key-value pairs
* @param elementSeparator The separator between the elements of the list
* @param keyValueSeparator The separator between the keys and values
* @param map The map to which the key-value pairs are added
*/
public Map toMap( String str, String elementSeparator,
String keyValueSeparator, Map map )
{
Map result ;
String elemSep ;
String kvSep ;
String[] assignments ;
String[] nameValue ;
if ( str == null )
return map ;
result = ( map == null ? new Hashtable() : map ) ;
elemSep = ( elementSeparator == null ) ? "," : elementSeparator ;
kvSep = ( keyValueSeparator == null ) ? "=" : keyValueSeparator ;
assignments = this.parts( str, elemSep ) ;
for ( int i = 0 ; i < assignments.length ; i++ )
{
nameValue = this.splitNameValue( assignments[i], kvSep ) ;
nameValue[0] = nameValue[0].trim() ;
nameValue[1] = nameValue[1].trim() ;
if ( nameValue[0].length() > 0 )
result.put( nameValue[0], nameValue[1] ) ;
}
return result ;
} // asMap()
// -------------------------------------------------------------------------
/**
* Returns a new map object that contains all key-value pairs of the
* specified string.
* <br>
* The separator between the elements is assumed to be ","
* and "=" between key and value.
* <p>
* Example:<br>
* "main=Fred,support1=John,support2=Stella,manager=Oscar"
* <p>
* <b>Be aware that all leading and trailing whitespaces of keys and values
* will be removed!</b>
*
* @param str The string with the list of key-value pairs
*/
public Map asMap( String str )
{
return this.toMap( str, null, null, null ) ;
} // asMap()
// -------------------------------------------------------------------------
/**
* Returns a new map object that contains all key-value pairs of the
* specified string.
* <br>
* The separator between the keys and values is assumed to be "=".
* <p>
* <b>Be aware that all leading and trailing whitespaces of keys and values
* will be removed!</b>
*
* @param str The string that contains the list of key-value pairs
* @param elementSeparator The separator between the elements of the list
*/
public Map asMap( String str, String elementSeparator )
{
return this.toMap( str, elementSeparator, null, null ) ;
} // asMap()
// -------------------------------------------------------------------------
/**
* Returns a new map object that contains all key-value pairs of the
* specified string.
* <p>
* <b>Be aware that all leading and trailing whitespaces of keys and values
* will be removed!</b>
*
* @param str The string that contains the list of key-value pairs
* @param elementSeparator The separator between the elements of the list
* @param keyValueSeparator The separator between the keys and values
*/
public Map asMap( String str, String elementSeparator,
String keyValueSeparator )
{
return this.toMap( str, elementSeparator, keyValueSeparator, null ) ;
} // asMap()
// -------------------------------------------------------------------------
/**
* Returns the given map object with all key-value pairs of the
* specified string added to it.
* <br>
* The separator between the keys and values is assumed to be "=".
* <p>
* <b>Be aware that all leading and trailing whitespaces of keys and values
* will be removed!</b>
*
* @param str The string that contains the list of key-value pairs
* @param elementSeparator The separator between the elements of the list
* @param map The map to which the key-value pairs are added
*/
public Map toMap( String str, String elementSeparator, Map map )
{
return this.toMap( str, elementSeparator, null, map ) ;
} // toMap()
// -------------------------------------------------------------------------
/**
* Adds all key-value pairs of the given string to the specified map.
* <br>
* The separator between the elements is assumed to be ","
* and "=" between key and value.
* <p>
* <b>Be aware that all leading and trailing whitespaces of keys and values
* will be removed!</b>
*
* @param str The string that contains the list of key-value pairs
* @param map The map to which the key-value pairs are added
*/
public Map toMap( String str, Map map )
{
return this.toMap( str, null, null, map ) ;
} // toMap()
// -------------------------------------------------------------------------
/**
* Adds all key-value pairs of the given string to a new properties object.
* <br>
* The separator between the elements is assumed to be ","
* and "=" between key and value.
* <p>
* <b>Be aware that all leading and trailing whitespaces of keys and values
* will be removed!</b>
*
* @param str The string that contains the list of key-value pairs
*/
public Properties asProperties( String str )
{
return this.toProperties( str, null ) ;
} // asProperties()
// -------------------------------------------------------------------------
/**
* Adds all key-value pairs of the given string to the specified properties.
* <br>
* The separator between the elements is assumed to be ","
* and "=" between key and value.
* <p>
* <b>Be aware that all leading and trailing whitespaces of keys and values
* will be removed!</b>
*
* @param str The string that contains the list of key-value pairs
* @param properties The properties where the key-value pairs should be added
*/
public Properties toProperties( String str, Properties properties )
{
Properties props = ( properties == null ) ? new Properties() : properties ;
return (Properties)this.toMap( str, null, null, props ) ;
} // toProperties()
// -------------------------------------------------------------------------
// =========================================================================
// PROTECTED INSTANCE METHODS
// =========================================================================
/**
* Cuts off all leading and trailing occurences of separator in text.
*/
protected String trimSeparator( String text, String separator )
{
int sepLen = separator.length() ;
while ( text.startsWith( separator ) )
text = text.substring( separator.length() ) ;
while ( text.endsWith( separator ) )
text = text.substring( 0, text.length() - sepLen ) ;
return text ;
} // trimSeparator()
// -------------------------------------------------------------------------
/**
* Returns an array of substrings of the given text. <br>
* The separators between the substrings are the given delimiters.
* Each character in the delimiter string is treated as a separator.
*
* @param text The string that should be splitted into substrings
* @param delimiters All characters that should be recognized as a separator or substrings
* @param all If true, empty elements will be returned, otherwise thye are skipped
* @return An array of substrings of the given text
*/
protected String[] parts( String text, String delimiters, boolean all )
{
ArrayList result = null ;
StringTokenizer tokenizer = null ;
if ( text == null )
return null ;
if ( ( delimiters == null ) || ( delimiters.length() == 0 ) )
{
String[] resultArray = { text } ;
return resultArray ;
}
if ( text.length() == 0 )
{
return new String[0] ;
}
else
{
result = new ArrayList() ;
tokenizer = new StringTokenizer( text, delimiters, all ) ;
if ( all )
this.collectParts( result, tokenizer, delimiters ) ;
else
this.collectParts( result, tokenizer ) ;
}
return (String[])result.toArray( new String[0] ) ;
} // parts()
// -------------------------------------------------------------------------
protected void collectParts( List list, StringTokenizer tokenizer )
{
while( tokenizer.hasMoreTokens() )
{
list.add( tokenizer.nextToken() ) ;
}
} // collectParts()
// -------------------------------------------------------------------------
protected void collectParts( List list, StringTokenizer tokenizer, String delimiter )
{
String token ;
boolean lastWasDelimiter = false ;
while( tokenizer.hasMoreTokens() )
{
token = tokenizer.nextToken() ;
if ( delimiter.indexOf( token ) >= 0 )
{
if ( lastWasDelimiter )
list.add( "" ) ;
lastWasDelimiter = true ;
}
else
{
list.add( token ) ;
lastWasDelimiter = false ;
}
}
} // collectParts()
// -------------------------------------------------------------------------
/**
* Returns the given text split up into an array of strings, at
* the occurrances of the separator string.
*
* In contrary to method parts() the separator is a one or many
* character sequence delimiter. That is, only the exact sequence
* of the characters in separator identifies the end of a substring.
* Parameter all defines whether empty strings between consecutive
* separators are added to the result or not.
*
* @see #parts(String, String, boolean)
* @param text The text to be split up
* @param separator The string that separates the substrings
* @param all If true, empty strings are added, otherwise skipped
* @return An array of substrings not containing any separator anymore
*/
protected String[] substrings( String text, String separator, boolean all )
{
int index = 0 ;
int start = 0 ;
int sepLen = 0 ;
int strLen = 0 ;
String str = text ;
ArrayList strings = new ArrayList() ;
if ( text == null )
return new String[0] ;
if ( ( separator == null ) || ( separator.length() == 0 ) )
{
if ( text.length() == 0 )
return new String[0] ;
String[] resultArray = { text } ;
return resultArray ;
}
if ( ! all )
str = this.trimSeparator( text, separator ) ;
strLen = str.length() ;
if ( strLen > 0 )
{
sepLen = separator.length() ;
index = str.indexOf( separator, start ) ;
while ( index >= 0 )
{
if ( all )
{
if ( index > 0 )
{
strings.add( str.substring( start, index ) ) ;
}
}
else
{
if ( index > ( start + sepLen ) )
strings.add( str.substring( start, index ) ) ;
}
start = index + sepLen ;
index = str.indexOf( separator, start ) ;
}
if ( start < strLen )
strings.add( str.substring( start ) ) ;
}
return (String[])strings.toArray( new String[0] ) ;
} // substrings()
// -------------------------------------------------------------------------
protected String padCh( String str, int len, char ch, boolean left )
{
StringBuffer buffer = null ;
int missing = len - str.length() ;
if ( missing <= 0 )
return str ;
buffer = new StringBuffer( len ) ;
if ( ! left )
buffer.append( str ) ;
for ( int i = 1 ; i <= missing ; i++ )
buffer.append( ch ) ;
if ( left )
buffer.append( str ) ;
return buffer.toString() ;
} // padCh()
// -------------------------------------------------------------------------
protected int indexOfString( String[] strArray, String searchStr, boolean ignoreCase )
{
if ( ( strArray == null ) || ( strArray.length == 0 ) )
return -1 ;
boolean found = false ;
for ( int i = 0 ; i < strArray.length ; i++ )
{
if ( strArray[i] == null )
{
if ( searchStr == null )
found = true ;
}
else
{
if ( ignoreCase )
found = strArray[i].equalsIgnoreCase( searchStr ) ;
else
found = strArray[i].equals( searchStr ) ;
}
if ( found )
return i ;
}
return -1 ;
} // indexOfString()
// -------------------------------------------------------------------------
/**
* Returns the substring of the given string that comes before the
* first occurance of the specified separator.
* If the string starts with a separator, the result will be an empty string.
* If the string doesn't contain the separator the method returns null or
* the whole string, depending on the returnNull flag.
*
* @param str The string of which the prefix is desired
* @param separator Separates the prefix from the rest of the string
* @param returnNull Specifies if null will be returned if no separator is found
*/
protected String prefix( String str, String separator, boolean returnNull )
{
if ( str == null )
return null ;
if ( separator == null )
return ( returnNull ? null : str ) ;
int index = str.indexOf( separator ) ;
if ( index >= 0 )
return str.substring( 0, index ) ;
else
return ( returnNull ? null : str ) ;
} // prefix()
// -------------------------------------------------------------------------
/**
* Returns the substring of the given string that comes after the
* first occurance of the specified separator.
* If the string ends with a separator, the result will be an empty string.
* If the string doesn't contain the separator the method returns null or
* the whole string, depending on the returnNull flag.
*
* @param str The string of which the suffix is desired
* @param separator Separates the suffix from the rest of the string
* @param returnNull Specifies if null will be returned if no separator is found
*/
protected String suffix( String str, String separator, boolean returnNull )
{
if ( str == null )
return null ;
if ( separator == null )
return ( returnNull ? null : str ) ;
int index = str.indexOf( separator ) ;
if ( index >= 0 )
return str.substring( index + separator.length() ) ;
else
return ( returnNull ? null : str ) ;
} // suffix()
// -------------------------------------------------------------------------
/**
* Removes the given strings from the array.
* If removeStrings is null it means that all null values are removed from
* the first array.
*/
protected String[] removeFromStringArray( String[] strings, String[] removeStrings )
{
List list ;
boolean remains ;
list = new ArrayList( strings.length ) ;
for (int i = 0; i < strings.length; i++)
{
if ( removeStrings == null )
{
remains = strings[i] != null ;
}
else
{
remains = ! this.contains( removeStrings, strings[i] ) ;
}
if ( remains )
{
list.add( strings[i] ) ;
}
}
return (String[])list.toArray( new String[list.size()] ) ;
} // removeFromStringArray()
// -------------------------------------------------------------------------
} // class StringUtil