Package org.pf.text

Source Code of org.pf.text.StringUtil

// ===========================================================================
// 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 toMapString 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
TOP

Related Classes of org.pf.text.StringUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.