forked from geodmms/xdgnjobs

?? ?
2008-06-09 bd210ee7438fd203c19d3e8080ea12b79fe56159
xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/util/StringUtils.java
@@ -1,2806 +1,2770 @@
package com.ximple.eofms.util;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Collection;
import java.util.Locale;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.net.URLEncoder;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CharacterCodingException;
import java.nio.CharBuffer;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.lang.reflect.Array;
import java.text.BreakIterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public abstract class StringUtils
{
   public static String ENCODING_US_ASCII = "US-ASCII";
   public static String ENCODING_ISO_8859_1 = "ISO-8859-1";
   public static String ENCODING_ISO_8859_2 = "ISO-8859-2";
   public static String ENCODING_ISO_8859_5 = "ISO-8859-5";
   public static String ENCODING_UTF_8 = "UTF-8";
   public static String ENCODING_UTF_16BE = "UTF-16BE";
   public static String ENCODING_UTF_16LE = "UTF-16LE";
   public static String ENCODING_UTF_16 = "UTF-16";
    public static String ENCODING_US_ASCII = "US-ASCII";
    public static String ENCODING_ISO_8859_1 = "ISO-8859-1";
    public static String ENCODING_ISO_8859_2 = "ISO-8859-2";
    public static String ENCODING_ISO_8859_5 = "ISO-8859-5";
    public static String ENCODING_UTF_8 = "UTF-8";
    public static String ENCODING_UTF_16BE = "UTF-16BE";
    public static String ENCODING_UTF_16LE = "UTF-16LE";
    public static String ENCODING_UTF_16 = "UTF-16";
   public static Charset CHARSET_US_ASCII = Charset.forName(StringUtils.ENCODING_US_ASCII);
    public static Charset CHARSET_US_ASCII = Charset.forName(StringUtils.ENCODING_US_ASCII);
   public static final Pattern BBCODE_COLOR = Pattern.compile("\\[color\\s*=\\s*([#\\w]*)\\s*\\]", Pattern.CASE_INSENSITIVE);
   public static final Pattern BBCODE_SIZE = Pattern.compile("\\[size\\s*=\\s*([+\\-]?[0-9]*)\\s*\\]", Pattern.CASE_INSENSITIVE);
   public static final Pattern BBCODE_URL_SHORT = Pattern.compile("\\[url\\]\\s*([^\\s]*)\\s*\\[\\/url\\]", Pattern.CASE_INSENSITIVE);
   public static final Pattern BBCODE_URL_LONG = Pattern.compile("\\[url=([^\\[]*)\\]([^\\[]*)\\[/url\\]", Pattern.CASE_INSENSITIVE);
   public static final Pattern BBCODE_IMG = Pattern.compile("\\[img\\]\\s*([^\\s]*)\\s*\\[\\/img\\]", Pattern.CASE_INSENSITIVE);
   public static final Pattern BBCODE_QUOTE_LONG = Pattern.compile("\\[quote=([^\\]]+\\]*)\\]", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
   public static final Pattern BBCODE_BAREURL = Pattern.compile("(?:[^\"'=>\\]]|^)((?:http|ftp)s?://(?:%[\\p{Digit}A-Fa-f][\\p{Digit}A-Fa-f]|[\\-_\\.!~*';\\|/?:@#&=\\+$,\\p{Alnum}])+)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    public static final Pattern BBCODE_COLOR = Pattern.compile("\\[color\\s*=\\s*([#\\w]*)\\s*\\]", Pattern.CASE_INSENSITIVE);
    public static final Pattern BBCODE_SIZE = Pattern.compile("\\[size\\s*=\\s*([+\\-]?[0-9]*)\\s*\\]", Pattern.CASE_INSENSITIVE);
    public static final Pattern BBCODE_URL_SHORT = Pattern.compile("\\[url\\]\\s*([^\\s]*)\\s*\\[\\/url\\]", Pattern.CASE_INSENSITIVE);
    public static final Pattern BBCODE_URL_LONG = Pattern.compile("\\[url=([^\\[]*)\\]([^\\[]*)\\[/url\\]", Pattern.CASE_INSENSITIVE);
    public static final Pattern BBCODE_IMG = Pattern.compile("\\[img\\]\\s*([^\\s]*)\\s*\\[\\/img\\]", Pattern.CASE_INSENSITIVE);
    public static final Pattern BBCODE_QUOTE_LONG = Pattern.compile("\\[quote=([^\\]]+\\]*)\\]", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
    public static final Pattern BBCODE_BAREURL = Pattern.compile("(?:[^\"'=>\\]]|^)((?:http|ftp)s?://(?:%[\\p{Digit}A-Fa-f][\\p{Digit}A-Fa-f]|[\\-_\\.!~*';\\|/?:@#&=\\+$,\\p{Alnum}])+)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
   private static final Map<Character, String> AGGRESSIVE_HTML_ENCODE_MAP = new HashMap<Character, String>();
   private static final Map<Character, String> DEFENSIVE_HTML_ENCODE_MAP = new HashMap<Character, String>();
   private static final Map<Character, String> XML_ENCODE_MAP = new HashMap<Character, String>();
   private static final Map<Character, String> STRING_ENCODE_MAP = new HashMap<Character, String>();
   private static final Map<Character, String> SQL_ENCODE_MAP = new HashMap<Character, String>();
   private static final Map<Character, String> LATEX_ENCODE_MAP = new HashMap<Character, String>();
    private static final Map<Character, String> AGGRESSIVE_HTML_ENCODE_MAP = new HashMap<Character, String>();
    private static final Map<Character, String> DEFENSIVE_HTML_ENCODE_MAP = new HashMap<Character, String>();
    private static final Map<Character, String> XML_ENCODE_MAP = new HashMap<Character, String>();
    private static final Map<Character, String> STRING_ENCODE_MAP = new HashMap<Character, String>();
    private static final Map<Character, String> SQL_ENCODE_MAP = new HashMap<Character, String>();
    private static final Map<Character, String> LATEX_ENCODE_MAP = new HashMap<Character, String>();
   private static final Map<String, Character>      HTML_DECODE_MAP = new HashMap<String, Character>();
    private static final Map<String, Character> HTML_DECODE_MAP = new HashMap<String, Character>();
   private static final HtmlEncoderFallbackHandler HTML_ENCODER_FALLBACK = new HtmlEncoderFallbackHandler();
    private static final HtmlEncoderFallbackHandler HTML_ENCODER_FALLBACK = new HtmlEncoderFallbackHandler();
   static
   {
      // Html encoding mapping according to the HTML 4.0 spec
      // http://www.w3.org/TR/REC-html40/sgml/entities.html
    static
    {
        // Html encoding mapping according to the HTML 4.0 spec
        // http://www.w3.org/TR/REC-html40/sgml/entities.html
      // Special characters for HTML
      AGGRESSIVE_HTML_ENCODE_MAP.put('\u0026',"&amp;");
      AGGRESSIVE_HTML_ENCODE_MAP.put('\u003C',"&lt;");
      AGGRESSIVE_HTML_ENCODE_MAP.put('\u003E',"&gt;");
      AGGRESSIVE_HTML_ENCODE_MAP.put('\u0022',"&quot;");
        // Special characters for HTML
        AGGRESSIVE_HTML_ENCODE_MAP.put('\u0026', "&amp;");
        AGGRESSIVE_HTML_ENCODE_MAP.put('\u003C', "&lt;");
        AGGRESSIVE_HTML_ENCODE_MAP.put('\u003E', "&gt;");
        AGGRESSIVE_HTML_ENCODE_MAP.put('\u0022', "&quot;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u0152',"&OElig;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u0153',"&oelig;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u0160',"&Scaron;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u0161',"&scaron;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u0178',"&Yuml;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u02C6',"&circ;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u02DC',"&tilde;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2002',"&ensp;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2003',"&emsp;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2009',"&thinsp;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u200C',"&zwnj;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u200D',"&zwj;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u200E',"&lrm;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u200F',"&rlm;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2013',"&ndash;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2014',"&mdash;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2018',"&lsquo;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2019',"&rsquo;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u201A',"&sbquo;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u201C',"&ldquo;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u201D',"&rdquo;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u201E',"&bdquo;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2020',"&dagger;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2021',"&Dagger;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2030',"&permil;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2039',"&lsaquo;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u203A',"&rsaquo;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u20AC',"&euro;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u0152', "&OElig;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u0153', "&oelig;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u0160', "&Scaron;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u0161', "&scaron;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u0178', "&Yuml;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u02C6', "&circ;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u02DC', "&tilde;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2002', "&ensp;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2003', "&emsp;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2009', "&thinsp;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u200C', "&zwnj;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u200D', "&zwj;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u200E', "&lrm;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u200F', "&rlm;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2013', "&ndash;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2014', "&mdash;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2018', "&lsquo;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2019', "&rsquo;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u201A', "&sbquo;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u201C', "&ldquo;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u201D', "&rdquo;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u201E', "&bdquo;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2020', "&dagger;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2021', "&Dagger;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2030', "&permil;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2039', "&lsaquo;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u203A', "&rsaquo;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u20AC', "&euro;");
      // Character entity references for ISO 8859-1 characters
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00A0',"&nbsp;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00A1',"&iexcl;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00A2',"&cent;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00A3',"&pound;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00A4',"&curren;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00A5',"&yen;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00A6',"&brvbar;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00A7',"&sect;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00A8',"&uml;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00A9',"&copy;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00AA',"&ordf;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00AB',"&laquo;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00AC',"&not;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00AD',"&shy;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00AE',"&reg;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00AF',"&macr;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00B0',"&deg;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00B1',"&plusmn;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00B2',"&sup2;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00B3',"&sup3;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00B4',"&acute;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00B5',"&micro;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00B6',"&para;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00B7',"&middot;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00B8',"&cedil;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00B9',"&sup1;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00BA',"&ordm;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00BB',"&raquo;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00BC',"&frac14;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00BD',"&frac12;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00BE',"&frac34;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00BF',"&iquest;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00C0',"&Agrave;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00C1',"&Aacute;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00C2',"&Acirc;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00C3',"&Atilde;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00C4',"&Auml;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00C5',"&Aring;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00C6',"&AElig;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00C7',"&Ccedil;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00C8',"&Egrave;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00C9',"&Eacute;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00CA',"&Ecirc;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00CB',"&Euml;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00CC',"&Igrave;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00CD',"&Iacute;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00CE',"&Icirc;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00CF',"&Iuml;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00D0',"&ETH;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00D1',"&Ntilde;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00D2',"&Ograve;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00D3',"&Oacute;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00D4',"&Ocirc;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00D5',"&Otilde;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00D6',"&Ouml;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00D7',"&times;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00D8',"&Oslash;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00D9',"&Ugrave;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00DA',"&Uacute;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00DB',"&Ucirc;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00DC',"&Uuml;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00DD',"&Yacute;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00DE',"&THORN;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00DF',"&szlig;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00E0',"&agrave;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00E1',"&aacute;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00E2',"&acirc;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00E3',"&atilde;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00E4',"&auml;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00E5',"&aring;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00E6',"&aelig;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00E7',"&ccedil;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00E8',"&egrave;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00E9',"&eacute;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00EA',"&ecirc;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00EB',"&euml;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00EC',"&igrave;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00ED',"&iacute;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00EE',"&icirc;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00EF',"&iuml;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00F0',"&eth;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00F1',"&ntilde;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00F2',"&ograve;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00F3',"&oacute;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00F4',"&ocirc;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00F5',"&otilde;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00F6',"&ouml;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00F7',"&divide;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00F8',"&oslash;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00F9',"&ugrave;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00FA',"&uacute;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00FB',"&ucirc;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00FC',"&uuml;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00FD',"&yacute;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00FE',"&thorn;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u00FF',"&yuml;");
        // Character entity references for ISO 8859-1 characters
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00A0', "&nbsp;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00A1', "&iexcl;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00A2', "&cent;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00A3', "&pound;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00A4', "&curren;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00A5', "&yen;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00A6', "&brvbar;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00A7', "&sect;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00A8', "&uml;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00A9', "&copy;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00AA', "&ordf;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00AB', "&laquo;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00AC', "&not;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00AD', "&shy;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00AE', "&reg;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00AF', "&macr;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00B0', "&deg;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00B1', "&plusmn;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00B2', "&sup2;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00B3', "&sup3;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00B4', "&acute;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00B5', "&micro;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00B6', "&para;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00B7', "&middot;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00B8', "&cedil;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00B9', "&sup1;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00BA', "&ordm;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00BB', "&raquo;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00BC', "&frac14;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00BD', "&frac12;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00BE', "&frac34;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00BF', "&iquest;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00C0', "&Agrave;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00C1', "&Aacute;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00C2', "&Acirc;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00C3', "&Atilde;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00C4', "&Auml;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00C5', "&Aring;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00C6', "&AElig;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00C7', "&Ccedil;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00C8', "&Egrave;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00C9', "&Eacute;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00CA', "&Ecirc;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00CB', "&Euml;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00CC', "&Igrave;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00CD', "&Iacute;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00CE', "&Icirc;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00CF', "&Iuml;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00D0', "&ETH;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00D1', "&Ntilde;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00D2', "&Ograve;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00D3', "&Oacute;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00D4', "&Ocirc;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00D5', "&Otilde;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00D6', "&Ouml;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00D7', "&times;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00D8', "&Oslash;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00D9', "&Ugrave;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00DA', "&Uacute;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00DB', "&Ucirc;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00DC', "&Uuml;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00DD', "&Yacute;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00DE', "&THORN;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00DF', "&szlig;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00E0', "&agrave;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00E1', "&aacute;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00E2', "&acirc;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00E3', "&atilde;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00E4', "&auml;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00E5', "&aring;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00E6', "&aelig;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00E7', "&ccedil;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00E8', "&egrave;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00E9', "&eacute;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00EA', "&ecirc;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00EB', "&euml;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00EC', "&igrave;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00ED', "&iacute;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00EE', "&icirc;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00EF', "&iuml;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00F0', "&eth;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00F1', "&ntilde;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00F2', "&ograve;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00F3', "&oacute;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00F4', "&ocirc;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00F5', "&otilde;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00F6', "&ouml;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00F7', "&divide;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00F8', "&oslash;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00F9', "&ugrave;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00FA', "&uacute;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00FB', "&ucirc;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00FC', "&uuml;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00FD', "&yacute;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00FE', "&thorn;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u00FF', "&yuml;");
      // Mathematical, Greek and Symbolic characters for HTML
      DEFENSIVE_HTML_ENCODE_MAP.put('\u0192',"&fnof;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u0391',"&Alpha;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u0392',"&Beta;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u0393',"&Gamma;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u0394',"&Delta;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u0395',"&Epsilon;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u0396',"&Zeta;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u0397',"&Eta;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u0398',"&Theta;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u0399',"&Iota;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u039A',"&Kappa;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u039B',"&Lambda;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u039C',"&Mu;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u039D',"&Nu;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u039E',"&Xi;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u039F',"&Omicron;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03A0',"&Pi;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03A1',"&Rho;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03A3',"&Sigma;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03A4',"&Tau;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03A5',"&Upsilon;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03A6',"&Phi;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03A7',"&Chi;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03A8',"&Psi;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03A9',"&Omega;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03B1',"&alpha;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03B2',"&beta;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03B3',"&gamma;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03B4',"&delta;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03B5',"&epsilon;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03B6',"&zeta;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03B7',"&eta;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03B8',"&theta;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03B9',"&iota;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03BA',"&kappa;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03BB',"&lambda;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03BC',"&mu;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03BD',"&nu;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03BE',"&xi;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03BF',"&omicron;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03C0',"&pi;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03C1',"&rho;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03C2',"&sigmaf;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03C3',"&sigma;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03C4',"&tau;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03C5',"&upsilon;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03C6',"&phi;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03C7',"&chi;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03C8',"&psi;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03C9',"&omega;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03D1',"&thetasym;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03D2',"&upsih;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u03D6',"&piv;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2022',"&bull;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2026',"&hellip;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2032',"&prime;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2033',"&Prime;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u203E',"&oline;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2044',"&frasl;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2118',"&weierp;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2111',"&image;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u211C',"&real;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2122',"&trade;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2135',"&alefsym;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2190',"&larr;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2191',"&uarr;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2192',"&rarr;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2193',"&darr;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2194',"&harr;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u21B5',"&crarr;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u21D0',"&lArr;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u21D1',"&uArr;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u21D2',"&rArr;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u21D3',"&dArr;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u21D4',"&hArr;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2200',"&forall;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2202',"&part;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2203',"&exist;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2205',"&empty;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2207',"&nabla;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2208',"&isin;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2209',"&notin;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u220B',"&ni;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u220F',"&prod;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2211',"&sum;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2212',"&minus;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2217',"&lowast;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u221A',"&radic;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u221D',"&prop;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u221E',"&infin;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2220',"&ang;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2227',"&and;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2228',"&or;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2229',"&cap;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u222A',"&cup;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u222B',"&int;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2234',"&there4;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u223C',"&sim;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2245',"&cong;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2248',"&asymp;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2260',"&ne;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2261',"&equiv;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2264',"&le;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2265',"&ge;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2282',"&sub;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2283',"&sup;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2284',"&nsub;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2286',"&sube;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2287',"&supe;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2295',"&oplus;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2297',"&otimes;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u22A5',"&perp;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u22C5',"&sdot;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2308',"&lceil;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2309',"&rceil;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u230A',"&lfloor;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u230B',"&rfloor;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2329',"&lang;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u232A',"&rang;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u25CA',"&loz;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2660',"&spades;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2663',"&clubs;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2665',"&hearts;");
      DEFENSIVE_HTML_ENCODE_MAP.put('\u2666',"&diams;");
        // Mathematical, Greek and Symbolic characters for HTML
        DEFENSIVE_HTML_ENCODE_MAP.put('\u0192', "&fnof;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u0391', "&Alpha;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u0392', "&Beta;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u0393', "&Gamma;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u0394', "&Delta;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u0395', "&Epsilon;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u0396', "&Zeta;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u0397', "&Eta;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u0398', "&Theta;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u0399', "&Iota;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u039A', "&Kappa;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u039B', "&Lambda;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u039C', "&Mu;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u039D', "&Nu;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u039E', "&Xi;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u039F', "&Omicron;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03A0', "&Pi;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03A1', "&Rho;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03A3', "&Sigma;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03A4', "&Tau;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03A5', "&Upsilon;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03A6', "&Phi;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03A7', "&Chi;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03A8', "&Psi;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03A9', "&Omega;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03B1', "&alpha;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03B2', "&beta;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03B3', "&gamma;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03B4', "&delta;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03B5', "&epsilon;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03B6', "&zeta;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03B7', "&eta;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03B8', "&theta;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03B9', "&iota;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03BA', "&kappa;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03BB', "&lambda;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03BC', "&mu;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03BD', "&nu;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03BE', "&xi;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03BF', "&omicron;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03C0', "&pi;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03C1', "&rho;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03C2', "&sigmaf;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03C3', "&sigma;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03C4', "&tau;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03C5', "&upsilon;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03C6', "&phi;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03C7', "&chi;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03C8', "&psi;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03C9', "&omega;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03D1', "&thetasym;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03D2', "&upsih;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u03D6', "&piv;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2022', "&bull;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2026', "&hellip;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2032', "&prime;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2033', "&Prime;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u203E', "&oline;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2044', "&frasl;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2118', "&weierp;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2111', "&image;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u211C', "&real;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2122', "&trade;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2135', "&alefsym;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2190', "&larr;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2191', "&uarr;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2192', "&rarr;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2193', "&darr;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2194', "&harr;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u21B5', "&crarr;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u21D0', "&lArr;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u21D1', "&uArr;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u21D2', "&rArr;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u21D3', "&dArr;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u21D4', "&hArr;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2200', "&forall;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2202', "&part;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2203', "&exist;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2205', "&empty;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2207', "&nabla;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2208', "&isin;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2209', "&notin;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u220B', "&ni;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u220F', "&prod;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2211', "&sum;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2212', "&minus;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2217', "&lowast;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u221A', "&radic;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u221D', "&prop;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u221E', "&infin;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2220', "&ang;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2227', "&and;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2228', "&or;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2229', "&cap;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u222A', "&cup;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u222B', "&int;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2234', "&there4;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u223C', "&sim;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2245', "&cong;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2248', "&asymp;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2260', "&ne;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2261', "&equiv;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2264', "&le;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2265', "&ge;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2282', "&sub;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2283', "&sup;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2284', "&nsub;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2286', "&sube;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2287', "&supe;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2295', "&oplus;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2297', "&otimes;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u22A5', "&perp;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u22C5', "&sdot;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2308', "&lceil;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2309', "&rceil;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u230A', "&lfloor;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u230B', "&rfloor;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2329', "&lang;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u232A', "&rang;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u25CA', "&loz;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2660', "&spades;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2663', "&clubs;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2665', "&hearts;");
        DEFENSIVE_HTML_ENCODE_MAP.put('\u2666', "&diams;");
      Set<Map.Entry<Character, String>> aggresive_entries = AGGRESSIVE_HTML_ENCODE_MAP.entrySet();
      for (Map.Entry<Character, String> entry : aggresive_entries)
      {
         HTML_DECODE_MAP.put(entry.getValue(), entry.getKey());
      }
        Set<Map.Entry<Character, String>> aggresive_entries = AGGRESSIVE_HTML_ENCODE_MAP.entrySet();
        for (Map.Entry<Character, String> entry : aggresive_entries)
        {
            HTML_DECODE_MAP.put(entry.getValue(), entry.getKey());
        }
      Set<Map.Entry<Character, String>> defensive_entries = DEFENSIVE_HTML_ENCODE_MAP.entrySet();
      for (Map.Entry<Character, String> entry : defensive_entries)
      {
         HTML_DECODE_MAP.put(entry.getValue(), entry.getKey());
      }
        Set<Map.Entry<Character, String>> defensive_entries = DEFENSIVE_HTML_ENCODE_MAP.entrySet();
        for (Map.Entry<Character, String> entry : defensive_entries)
        {
            HTML_DECODE_MAP.put(entry.getValue(), entry.getKey());
        }
      XML_ENCODE_MAP.put('\u0026',"&amp;");
      XML_ENCODE_MAP.put('\'',"&apos;");
      XML_ENCODE_MAP.put('\u0022',"&quot;");
      XML_ENCODE_MAP.put('\u003C',"&lt;");
      XML_ENCODE_MAP.put('\u003E',"&gt;");
        XML_ENCODE_MAP.put('\u0026', "&amp;");
        XML_ENCODE_MAP.put('\'', "&apos;");
        XML_ENCODE_MAP.put('\u0022', "&quot;");
        XML_ENCODE_MAP.put('\u003C', "&lt;");
        XML_ENCODE_MAP.put('\u003E', "&gt;");
      SQL_ENCODE_MAP.put('\'',"''");
        SQL_ENCODE_MAP.put('\'', "''");
      STRING_ENCODE_MAP.put('\\',"\\\\");
      STRING_ENCODE_MAP.put('\n',"\\n");
      STRING_ENCODE_MAP.put('\r',"\\r");
      STRING_ENCODE_MAP.put('\t',"\\t");
      STRING_ENCODE_MAP.put('"',"\\\"");
        STRING_ENCODE_MAP.put('\\', "\\\\");
        STRING_ENCODE_MAP.put('\n', "\\n");
        STRING_ENCODE_MAP.put('\r', "\\r");
        STRING_ENCODE_MAP.put('\t', "\\t");
        STRING_ENCODE_MAP.put('"', "\\\"");
      LATEX_ENCODE_MAP.put('\\',"\\\\");
      LATEX_ENCODE_MAP.put('#',"\\#");
      LATEX_ENCODE_MAP.put('$',"\\$");
      LATEX_ENCODE_MAP.put('%',"\\%");
      LATEX_ENCODE_MAP.put('&',"\\&");
      LATEX_ENCODE_MAP.put('~',"\\~");
      LATEX_ENCODE_MAP.put('_',"\\_");
      LATEX_ENCODE_MAP.put('^',"\\^");
      LATEX_ENCODE_MAP.put('{',"\\{");
      LATEX_ENCODE_MAP.put('}',"\\}");
      LATEX_ENCODE_MAP.put('\u00A1',"!'");
      LATEX_ENCODE_MAP.put('\u00BF',"?'");
      LATEX_ENCODE_MAP.put('\u00C0',"\\`{A}");
      LATEX_ENCODE_MAP.put('\u00C1',"\\'{A}");
      LATEX_ENCODE_MAP.put('\u00C2',"\\^{A}");
      LATEX_ENCODE_MAP.put('\u00C3',"\\H{A}");
      LATEX_ENCODE_MAP.put('\u00C4',"\\\"{A}");
      LATEX_ENCODE_MAP.put('\u00C5',"\\AA");
      LATEX_ENCODE_MAP.put('\u00C6',"\\AE");
      LATEX_ENCODE_MAP.put('\u00C7',"\\c{C}");
      LATEX_ENCODE_MAP.put('\u00C8',"\\`{E}");
      LATEX_ENCODE_MAP.put('\u00C9',"\\'{E}");
      LATEX_ENCODE_MAP.put('\u00CA',"\\^{E}");
      LATEX_ENCODE_MAP.put('\u00CB',"\\\"{E}");
      LATEX_ENCODE_MAP.put('\u00CC',"\\`{I}");
      LATEX_ENCODE_MAP.put('\u00CD',"\\'{I}");
      LATEX_ENCODE_MAP.put('\u00CE',"\\^{I}");
      LATEX_ENCODE_MAP.put('\u00CF',"\\\"{I}");
        LATEX_ENCODE_MAP.put('\\', "\\\\");
        LATEX_ENCODE_MAP.put('#', "\\#");
        LATEX_ENCODE_MAP.put('$', "\\$");
        LATEX_ENCODE_MAP.put('%', "\\%");
        LATEX_ENCODE_MAP.put('&', "\\&");
        LATEX_ENCODE_MAP.put('~', "\\~");
        LATEX_ENCODE_MAP.put('_', "\\_");
        LATEX_ENCODE_MAP.put('^', "\\^");
        LATEX_ENCODE_MAP.put('{', "\\{");
        LATEX_ENCODE_MAP.put('}', "\\}");
        LATEX_ENCODE_MAP.put('\u00A1', "!'");
        LATEX_ENCODE_MAP.put('\u00BF', "?'");
        LATEX_ENCODE_MAP.put('\u00C0', "\\`{A}");
        LATEX_ENCODE_MAP.put('\u00C1', "\\'{A}");
        LATEX_ENCODE_MAP.put('\u00C2', "\\^{A}");
        LATEX_ENCODE_MAP.put('\u00C3', "\\H{A}");
        LATEX_ENCODE_MAP.put('\u00C4', "\\\"{A}");
        LATEX_ENCODE_MAP.put('\u00C5', "\\AA");
        LATEX_ENCODE_MAP.put('\u00C6', "\\AE");
        LATEX_ENCODE_MAP.put('\u00C7', "\\c{C}");
        LATEX_ENCODE_MAP.put('\u00C8', "\\`{E}");
        LATEX_ENCODE_MAP.put('\u00C9', "\\'{E}");
        LATEX_ENCODE_MAP.put('\u00CA', "\\^{E}");
        LATEX_ENCODE_MAP.put('\u00CB', "\\\"{E}");
        LATEX_ENCODE_MAP.put('\u00CC', "\\`{I}");
        LATEX_ENCODE_MAP.put('\u00CD', "\\'{I}");
        LATEX_ENCODE_MAP.put('\u00CE', "\\^{I}");
        LATEX_ENCODE_MAP.put('\u00CF', "\\\"{I}");
// todo \u00D0
      LATEX_ENCODE_MAP.put('\u00D1',"\\H{N}");
      LATEX_ENCODE_MAP.put('\u00D2',"\\`{O}");
      LATEX_ENCODE_MAP.put('\u00D3',"\\'{O}");
      LATEX_ENCODE_MAP.put('\u00D4',"\\^{O}");
      LATEX_ENCODE_MAP.put('\u00D5',"\\H{O}");
      LATEX_ENCODE_MAP.put('\u00D6',"\\\"{O}");
        LATEX_ENCODE_MAP.put('\u00D1', "\\H{N}");
        LATEX_ENCODE_MAP.put('\u00D2', "\\`{O}");
        LATEX_ENCODE_MAP.put('\u00D3', "\\'{O}");
        LATEX_ENCODE_MAP.put('\u00D4', "\\^{O}");
        LATEX_ENCODE_MAP.put('\u00D5', "\\H{O}");
        LATEX_ENCODE_MAP.put('\u00D6', "\\\"{O}");
// todo \u00D7
      LATEX_ENCODE_MAP.put('\u00D8',"\\O");
      LATEX_ENCODE_MAP.put('\u00D9',"\\`{U}");
      LATEX_ENCODE_MAP.put('\u00DA',"\\'{U}");
      LATEX_ENCODE_MAP.put('\u00DB',"\\^{U}");
      LATEX_ENCODE_MAP.put('\u00DC',"\\\"{U}");
      LATEX_ENCODE_MAP.put('\u00DD',"\\'{Y}");
        LATEX_ENCODE_MAP.put('\u00D8', "\\O");
        LATEX_ENCODE_MAP.put('\u00D9', "\\`{U}");
        LATEX_ENCODE_MAP.put('\u00DA', "\\'{U}");
        LATEX_ENCODE_MAP.put('\u00DB', "\\^{U}");
        LATEX_ENCODE_MAP.put('\u00DC', "\\\"{U}");
        LATEX_ENCODE_MAP.put('\u00DD', "\\'{Y}");
// todo \u00DE
      LATEX_ENCODE_MAP.put('\u00DF',"\\ss");
      LATEX_ENCODE_MAP.put('\u00E0',"\\`{a}");
      LATEX_ENCODE_MAP.put('\u00E1',"\\'{a}");
      LATEX_ENCODE_MAP.put('\u00E2',"\\^{a}");
      LATEX_ENCODE_MAP.put('\u00E3',"\\H{a}");
      LATEX_ENCODE_MAP.put('\u00E4',"\\\"{a}");
      LATEX_ENCODE_MAP.put('\u00E5',"\\aa");
      LATEX_ENCODE_MAP.put('\u00E6',"\\ae");
      LATEX_ENCODE_MAP.put('\u00E7',"\\c{c}");
      LATEX_ENCODE_MAP.put('\u00E8',"\\`{e}");
      LATEX_ENCODE_MAP.put('\u00E9',"\\'{e}");
      LATEX_ENCODE_MAP.put('\u00EA',"\\^{e}");
      LATEX_ENCODE_MAP.put('\u00EB',"\\\"{e}");
      LATEX_ENCODE_MAP.put('\u00EC',"\\`{i}");
      LATEX_ENCODE_MAP.put('\u00ED',"\\'{i}");
      LATEX_ENCODE_MAP.put('\u00EE',"\\^{i}");
      LATEX_ENCODE_MAP.put('\u00EF',"\\\"{i}");
        LATEX_ENCODE_MAP.put('\u00DF', "\\ss");
        LATEX_ENCODE_MAP.put('\u00E0', "\\`{a}");
        LATEX_ENCODE_MAP.put('\u00E1', "\\'{a}");
        LATEX_ENCODE_MAP.put('\u00E2', "\\^{a}");
        LATEX_ENCODE_MAP.put('\u00E3', "\\H{a}");
        LATEX_ENCODE_MAP.put('\u00E4', "\\\"{a}");
        LATEX_ENCODE_MAP.put('\u00E5', "\\aa");
        LATEX_ENCODE_MAP.put('\u00E6', "\\ae");
        LATEX_ENCODE_MAP.put('\u00E7', "\\c{c}");
        LATEX_ENCODE_MAP.put('\u00E8', "\\`{e}");
        LATEX_ENCODE_MAP.put('\u00E9', "\\'{e}");
        LATEX_ENCODE_MAP.put('\u00EA', "\\^{e}");
        LATEX_ENCODE_MAP.put('\u00EB', "\\\"{e}");
        LATEX_ENCODE_MAP.put('\u00EC', "\\`{i}");
        LATEX_ENCODE_MAP.put('\u00ED', "\\'{i}");
        LATEX_ENCODE_MAP.put('\u00EE', "\\^{i}");
        LATEX_ENCODE_MAP.put('\u00EF', "\\\"{i}");
// todo \u00F0
      LATEX_ENCODE_MAP.put('\u00F1',"\\H{n}");
      LATEX_ENCODE_MAP.put('\u00F2',"\\`{o}");
      LATEX_ENCODE_MAP.put('\u00F3',"\\'{o}");
      LATEX_ENCODE_MAP.put('\u00F4',"\\^{o}");
      LATEX_ENCODE_MAP.put('\u00F5',"\\H{o}");
      LATEX_ENCODE_MAP.put('\u00F6',"\\\"{o}");
        LATEX_ENCODE_MAP.put('\u00F1', "\\H{n}");
        LATEX_ENCODE_MAP.put('\u00F2', "\\`{o}");
        LATEX_ENCODE_MAP.put('\u00F3', "\\'{o}");
        LATEX_ENCODE_MAP.put('\u00F4', "\\^{o}");
        LATEX_ENCODE_MAP.put('\u00F5', "\\H{o}");
        LATEX_ENCODE_MAP.put('\u00F6', "\\\"{o}");
// todo \u00F7
      LATEX_ENCODE_MAP.put('\u00F8',"\\o");
      LATEX_ENCODE_MAP.put('\u00F9',"\\`{u}");
      LATEX_ENCODE_MAP.put('\u00FA',"\\'{u}");
      LATEX_ENCODE_MAP.put('\u00FB',"\\^{u}");
      LATEX_ENCODE_MAP.put('\u00FC',"\\\"{u}");
      LATEX_ENCODE_MAP.put('\u00FD',"\\'{y}");
        LATEX_ENCODE_MAP.put('\u00F8', "\\o");
        LATEX_ENCODE_MAP.put('\u00F9', "\\`{u}");
        LATEX_ENCODE_MAP.put('\u00FA', "\\'{u}");
        LATEX_ENCODE_MAP.put('\u00FB', "\\^{u}");
        LATEX_ENCODE_MAP.put('\u00FC', "\\\"{u}");
        LATEX_ENCODE_MAP.put('\u00FD', "\\'{y}");
// todo \u00FE
      LATEX_ENCODE_MAP.put('\u00FF',"\\\"{y}");
   }
   /**
    * Transforms a provided <code>String</code> object into a new string,
    * containing only valid characters for a java class name.
    *
    * @param name The string that has to be transformed into a valid class
    * name.
    * @return The encoded <code>String</code> object.
    * @see #encodeUrl(String)
    * @see #encodeHtml(String)
    * @see #encodeXml(String)
    * @see #encodeSql(String)
    * @see #encodeLatex(String)
    * @see #encodeRegexp(String)
    * @since 1.0
    */
   public static String encodeClassname(String name)
   {
      if (null == name)
      {
         return null;
      }
      Pattern pattern = Pattern.compile("[^\\w]");
      Matcher matcher = pattern.matcher(name);
      return matcher.replaceAll("_");
   }
   private static boolean needsUrlEncoding(String source)
   {
      if (null == source)
      {
         return false;
      }
      // check if the string needs encoding first since
      // the URLEncoder always allocates a StringBuffer, even when the
      // string is returned as-is
      boolean encode = false;
      char ch;
      for (int i = 0; i < source.length(); i++)
      {
         ch = source.charAt(i);
         if (ch >= 'a' && ch <= 'z' ||
            ch >= 'A' && ch <= 'Z' ||
            ch >= '0' && ch <= '9' ||
            ch == '-' || ch == '_' || ch == '.' || ch == '*')
         {
            continue;
         }
         encode = true;
         break;
      }
      return encode;
   }
   /**
    * Transforms a provided <code>String</code> object into a new string,
    * containing only valid URL characters.
    *
    * @param source The string that has to be transformed into a valid URL
    * string.
    * @return The encoded <code>String</code> object.
    * @see #encodeClassname(String)
    * @see #encodeUrlValue(String)
    * @see #encodeHtml(String)
    * @see #encodeXml(String)
    * @see #encodeSql(String)
    * @see #encodeLatex(String)
    * @see #encodeRegexp(String)
    * @since 1.0
    */
   public static String encodeUrl(String source)
   {
      if (!needsUrlEncoding(source))
      {
         return source;
      }
      try
      {
         return URLEncoder.encode(source, ENCODING_ISO_8859_1);
      }
      ///CLOVER:OFF
      catch (UnsupportedEncodingException e)
      {
         // this should never happen, ISO-8859-1 is a standard encoding
         throw new RuntimeException(e);
      }
      ///CLOVER:ON
   }
   /**
    * Transforms a provided <code>String</code> object into a new string,
    * only pure US Ascii strings are preserved and URL encoded in a regular
    * way. Strings with characters from other encodings will be encoded in a
    * RIFE-specific manner to allow international data to passed along the
    * query string.
    *
    * @param source The string that has to be transformed into a valid URL
    * parameter string.
    * @return The encoded <code>String</code> object.
    * @see #decodeUrlValue(String)
    * @see #encodeClassname(String)
    * @see #encodeUrl(String)
    * @see #encodeHtml(String)
    * @see #encodeXml(String)
    * @see #encodeSql(String)
    * @see #encodeLatex(String)
    * @see #encodeRegexp(String)
    * @since 1.0
    */
   public static String encodeUrlValue(String source)
   {
      if (!needsUrlEncoding(source))
      {
         return source;
      }
      // check if the string is valid US-ASCII encoding
      boolean         valid = true;
      CharsetEncoder encoder = CHARSET_US_ASCII.newEncoder();
      try
      {
         encoder.encode(CharBuffer.wrap(source));
      }
      catch (CharacterCodingException e)
      {
         valid = false;
      }
      try
      {
         // if it is valid US-ASCII, use the regular URL encoding method
         if (valid)
         {
               return URLEncoder.encode(source, ENCODING_US_ASCII);
         }
         // otherwise, base-64 encode the UTF-8 bytes and mark the string
         // as being encoded in a special way
         else
         {
            StringBuilder encoded = new StringBuilder("%02%02");
            String base64 = Base64.encodeToString(source.getBytes(ENCODING_UTF_8), false);
            String base64_urlsafe = replace(base64, "=", "%3D");
            encoded.append(base64_urlsafe);
            return encoded.toString();
         }
      }
      ///CLOVER:OFF
      catch (UnsupportedEncodingException e)
      {
         // this should never happen, ISO-8859-1 is a standard encoding
         throw new RuntimeException(e);
      }
      ///CLOVER:ON
   }
   /**
    * Decodes a <code>String</code> that has been encoded in a RIFE-specific
    * manner for URL usage.. Before calling this method, you should first
    * verify if the value needs decoding by using the
    * <code>doesUrlValueNeedDecoding(String)</code> method.
    *
    * @param source the value that has been encoded for URL usage in a
    * RIFE-specific way
    * @return The decoded <code>String</code> object.
    * @see #encodeUrlValue(String)
    * @see #doesUrlValueNeedDecoding(String)
    * @since 1.0
    */
   public static String decodeUrlValue(String source)
   {
      try
      {
         byte[] decoded = Base64.decode(source.substring(2));
         if (null == decoded)
         {
            return null;
         }
         else
         {
            return new String(decoded, StringUtils.ENCODING_UTF_8);
         }
      }
      ///CLOVER:OFF
      catch (UnsupportedEncodingException e)
      {
         // this should never happen, UTF-8 is a standard encoding
         throw new RuntimeException(e);
      }
      ///CLOVER:ON
   }
   /**
    * Checks if a <code>String</code> is encoded in a RIFE-specific manner
    * for URL usage.
    *
    * @param source the value that might have been encoded for URL usage in a
    * RIFE-specific way
    * @return <code>true</code> if the value is encoded in the RIFE-specific
    * format; and
    * <p><code>false</code> otherwise
    * @see #encodeUrlValue(String)
    * @see #decodeUrlValue(String)
    * @since 1.0
    */
   public static boolean doesUrlValueNeedDecoding(String source)
   {
      if (source != null &&
         source.length() > 2 &&
         source.startsWith("\u0002\u0002"))
      {
         return true;
      }
      return false;
   }
   private static boolean needsHtmlEncoding(String source, boolean defensive)
   {
      if (null == source)
      {
         return false;
      }
      boolean encode = false;
      char ch;
      for (int i = 0; i < source.length(); i++)
      {
         ch = source.charAt(i);
         if ((defensive || (ch != '\u0022' && ch != '\u0026' && ch != '\u003C' && ch != '\u003E')) &&
            ch < '\u00A0')
         {
            continue;
         }
         encode = true;
         break;
      }
      return encode;
   }
   /**
    *
    * @since 1.6
    */
   public static String decodeHtml(String source)
   {
      if (null == source ||
         0 == source.length())
      {
         return source;
      }
      int      current_index = 0;
      int      delimiter_start_index = 0;
      int      delimiter_end_index = 0;
      StringBuilder result = null;
      while (current_index <= source.length())
      {
         delimiter_start_index = source.indexOf('&', current_index);
         if (delimiter_start_index != -1)
         {
            delimiter_end_index = source.indexOf(';', delimiter_start_index + 1);
            if (delimiter_end_index != -1)
            {
               // ensure that the string builder is setup correctly
               if (null == result)
               {
                  result = new StringBuilder();
               }
               // add the text that leads up to this match
               if (delimiter_start_index > current_index)
               {
                  result.append(source.substring(current_index, delimiter_start_index));
               }
               // add the decoded entity
               String entity = source.substring(delimiter_start_index, delimiter_end_index + 1);
               current_index = delimiter_end_index + 1;
               // try to decoded numeric entities
               if (entity.charAt(1) == '#')
               {
                  int start = 2;
                  int radix = 10;
                  // check if the number is hexadecimal
                  if (entity.charAt(2) == 'X' || entity.charAt(2) == 'x')
                  {
                     start++;
                     radix = 16;
                  }
                  try
                  {
                     Character c = new Character((char)Integer.parseInt(entity.substring(start, entity.length() - 1), radix));
                     result.append(c);
                  }
                  // when the number of the entity can't be parsed, add the entity as-is
                  catch (NumberFormatException e)
                  {
                     result.append(entity);
                  }
               }
               else
               {
                  // try to decode the entity as a literal
                  Character decoded = HTML_DECODE_MAP.get(entity);
                  if (decoded != null)
                  {
                     result.append(decoded);
                  }
                  // if there was no match, add the entity as-is
                  else
                  {
                     result.append(entity);
                  }
               }
            }
            else
            {
               break;
            }
         }
         else
         {
            break;
         }
      }
      if (null == result)
      {
         return source;
      }
      else if (current_index < source.length())
      {
         result.append(source.substring(current_index));
      }
      return result.toString();
   }
   /**
    * Transforms a provided <code>String</code> object into a new string,
    * containing only valid Html characters.
    *
    * @param source The string that has to be transformed into a valid Html
    * string.
    * @return The encoded <code>String</code> object.
    * @see #encodeClassname(String)
    * @see #encodeUrl(String)
    * @see #encodeUrlValue(String)
    * @see #encodeXml(String)
    * @see #encodeSql(String)
    * @see #encodeString(String)
    * @see #encodeLatex(String)
    * @see #encodeRegexp(String)
    * @since 1.0
    */
   public static String encodeHtml(String source)
   {
      if (needsHtmlEncoding(source, false))
      {
         return encode(source, HTML_ENCODER_FALLBACK, AGGRESSIVE_HTML_ENCODE_MAP, DEFENSIVE_HTML_ENCODE_MAP);
      }
      return source;
   }
   /**
    * Transforms a provided <code>String</code> object into a new string,
    * containing as much as possible Html characters. It is safe to already
    * feed existing Html to this method since &amp;, &lt; and &gt; will not
    * be encoded.
    *
    * @param source The string that has to be transformed into a valid Html
    * string.
    * @return The encoded <code>String</code> object.
    * @see #encodeClassname(String)
    * @see #encodeUrl(String)
    * @see #encodeUrlValue(String)
    * @see #encodeXml(String)
    * @see #encodeSql(String)
    * @see #encodeString(String)
    * @see #encodeLatex(String)
    * @see #encodeRegexp(String)
    * @since 1.0
    */
   public static String encodeHtmlDefensive(String source)
   {
      if (needsHtmlEncoding(source, true))
      {
         return encode(source, null, DEFENSIVE_HTML_ENCODE_MAP);
      }
      return source;
   }
   /**
    * Transforms a provided <code>String</code> object into a new string,
    * containing only valid XML characters.
    *
    * @param source The string that has to be transformed into a valid XML
    * string.
    * @return The encoded <code>String</code> object.
    * @see #encodeClassname(String)
    * @see #encodeUrl(String)
    * @see #encodeUrlValue(String)
    * @see #encodeHtml(String)
    * @see #encodeSql(String)
    * @see #encodeString(String)
    * @see #encodeLatex(String)
    * @see #encodeRegexp(String)
    * @since 1.0
    */
   public static String encodeXml(String source)
   {
      return encode(source, null, XML_ENCODE_MAP);
   }
   /**
    * Transforms a provided <code>String</code> object into a new string,
    * containing only valid <code>String</code> characters.
    *
    * @param source The string that has to be transformed into a valid
    * sequence of <code>String</code> characters.
    * @return The encoded <code>String</code> object.
    * @see #encodeClassname(String)
    * @see #encodeUrl(String)
    * @see #encodeUrlValue(String)
    * @see #encodeHtml(String)
    * @see #encodeXml(String)
    * @see #encodeSql(String)
    * @see #encodeLatex(String)
    * @see #encodeRegexp(String)
    * @since 1.0
    */
   public static String encodeString(String source)
   {
      return encode(source, null, STRING_ENCODE_MAP);
   }
   /**
    * Transforms a provided <code>String</code> object into a series of
    * unicode escape codes.
    *
    * @param source The string that has to be transformed into a valid
    * sequence of unicode escape codes
    * @return The encoded <code>String</code> object.
    * @see #encodeClassname(String)
    * @see #encodeUrl(String)
    * @see #encodeUrlValue(String)
    * @see #encodeHtml(String)
    * @see #encodeXml(String)
    * @see #encodeSql(String)
    * @see #encodeLatex(String)
    * @see #encodeRegexp(String)
    * @since 1.0
    */
   public static String encodeUnicode(String source)
   {
      if (null == source)
      {
         return null;
      }
      StringBuilder   encoded = new StringBuilder();
      String         hexstring = null;
      for (int i = 0; i < source.length(); i++)
      {
         hexstring = Integer.toHexString((int)source.charAt(i)).toUpperCase();
         encoded.append("\\u");
         // fill with zeros
         for (int j = hexstring.length(); j < 4; j++)
         {
            encoded.append("0");
         }
         encoded.append(hexstring);
      }
      return encoded.toString();
   }
   /**
    * Transforms a provided <code>String</code> object into a new string,
    * containing only valid Sql characters.
    *
    * @param source The string that has to be transformed into a valid Sql
    * string.
    * @return The encoded <code>String</code> object.
    * @see #encodeClassname(String)
    * @see #encodeUrl(String)
    * @see #encodeUrlValue(String)
    * @see #encodeHtml(String)
    * @see #encodeXml(String)
    * @see #encodeString(String)
    * @see #encodeLatex(String)
    * @see #encodeRegexp(String)
    * @since 1.0
    */
   public static String encodeSql(String source)
   {
      return encode(source, null, SQL_ENCODE_MAP);
   }
   /**
    * Transforms a provided <code>String</code> object into a new string,
    * containing only valid LaTeX characters.
    *
    * @param source The string that has to be transformed into a valid LaTeX
    * string.
    * @return The encoded <code>String</code> object.
    * @see #encodeClassname(String)
    * @see #encodeUrl(String)
    * @see #encodeUrlValue(String)
    * @see #encodeHtml(String)
    * @see #encodeXml(String)
    * @see #encodeSql(String)
    * @see #encodeString(String)
    * @see #encodeRegexp(String)
    * @since 1.0
    */
   public static String encodeLatex(String source)
   {
      if (null == source)
      {
         return null;
      }
      source = encode(source, null, LATEX_ENCODE_MAP);
      source = StringUtils.replace(source, "latex", "\\LaTeX", false);
      return source;
   }
   /**
    * Transforms a provided <code>String</code> object into a new string,
    * using the mapping that are provided through the supplied encoding
    * table.
    *
    * @param source The string that has to be transformed into a valid
    * string, using the mappings that are provided through the supplied
    * encoding table.
    * @param encodingTables A <code>Map</code> object containing the mappings
    * to transform characters into valid entities. The keys of this map
    * should be <code>Character</code> objects and the values
    * <code>String</code> objects.
    * @return The encoded <code>String</code> object.
    * @since 1.0
    */
   private static String encode(String source, EncoderFallbackHandler fallbackHandler, Map<Character, String>... encodingTables)
   {
      if (null == source)
      {
         return null;
      }
      if (null == encodingTables ||
         0 == encodingTables.length)
      {
         return source;
      }
      StringBuilder   encoded_string = null;
      char[]         string_to_encode_array = source.toCharArray();
      int            last_match = -1;
      for (int i = 0; i < string_to_encode_array.length; i++)
      {
         char char_to_encode = string_to_encode_array[i];
         for (Map<Character, String> encoding_table : encodingTables)
         {
            if (encoding_table.containsKey(char_to_encode))
            {
               encoded_string = prepareEncodedString(source, encoded_string, i, last_match, string_to_encode_array);
               encoded_string.append(encoding_table.get(char_to_encode));
               last_match = i;
            }
         }
         if (fallbackHandler != null &&
            last_match < i &&
            fallbackHandler.hasFallback(char_to_encode))
         {
            encoded_string = prepareEncodedString(source, encoded_string, i, last_match, string_to_encode_array);
            fallbackHandler.appendFallback(encoded_string, char_to_encode);
            last_match = i;
         }
      }
      if (null == encoded_string)
      {
         return source;
      }
      else
      {
         int difference = string_to_encode_array.length-(last_match+1);
         if (difference > 0)
         {
            encoded_string.append(string_to_encode_array, last_match+1, difference);
         }
         return encoded_string.toString();
      }
   }
   private static StringBuilder prepareEncodedString(String source, StringBuilder encodedString, int i, int lastMatch, char[] stringToEncodeArray)
   {
      if (null == encodedString)
      {
         encodedString = new StringBuilder(source.length());
      }
      int difference = i - (lastMatch + 1);
      if (difference > 0)
      {
         encodedString.append(stringToEncodeArray, lastMatch + 1, difference);
      }
      return encodedString;
   }
   private static interface EncoderFallbackHandler
   {
      abstract boolean hasFallback(char character);
      abstract void appendFallback(StringBuilder encodedBuffer, char character);
   }
   private static class HtmlEncoderFallbackHandler implements EncoderFallbackHandler
   {
      private final static String PREFIX = "&#";
      private final static String SUFFIX = ";";
      public boolean hasFallback(char character)
      {
         if (character < '\u00A0')
         {
            return false;
         }
         return true;
      }
      public void appendFallback(StringBuilder encodedBuffer, char character)
      {
         encodedBuffer.append(PREFIX);
         encodedBuffer.append((int)character);
         encodedBuffer.append(SUFFIX);
      }
   }
   /**
    * Transforms a provided <code>String</code> object into a literal that can
    * be included into a regular expression {@link Pattern} as-is. None of the
    * regular expression escapes in the string will be functional anymore.
    *
    * @param source The string that has to be escaped as a literal
    * @return The encoded <code>String</code> object.
    * @see #encodeClassname(String)
    * @see #encodeUrl(String)
    * @see #encodeUrlValue(String)
    * @see #encodeHtml(String)
    * @see #encodeXml(String)
    * @see #encodeSql(String)
    * @see #encodeString(String)
    * @see #encodeLatex(String)
    * @since 1.3
    */
    public static String encodeRegexp(String source)
   {
        int regexp_quote_start = source.indexOf("\\E");
        if (-1 == regexp_quote_start)
      {
         return "\\Q" + source + "\\E";
      }
        StringBuilder buffer = new StringBuilder(source.length() * 2);
      buffer.append("\\Q");
      regexp_quote_start = 0;
      int current = 0;
      while (-1 == (regexp_quote_start = source.indexOf("\\E", current)))
      {
         buffer.append(source.substring(current, regexp_quote_start));
         current = regexp_quote_start + 2;
         buffer.append("\\E\\\\E\\Q");
      }
      buffer.append(source.substring(current, source.length()));
      buffer.append("\\E");
      return buffer.toString();
        LATEX_ENCODE_MAP.put('\u00FF', "\\\"{y}");
    }
   /**
    * Counts the number of times a substring occures in a provided string in
    * a case-sensitive manner.
    *
    * @param source The <code>String</code> object that will be searched in.
    * @param substring The string whose occurances will we counted.
    * @return An <code>int</code> value containing the number of occurances
    * of the substring.
    * @since 1.0
    */
   public static int count(String source, String substring)
   {
      return count(source, substring, true);
   }
    /**
     * Transforms a provided <code>String</code> object into a new string,
     * containing only valid characters for a java class name.
     *
     * @param name The string that has to be transformed into a valid class
     *             name.
     * @return The encoded <code>String</code> object.
     * @see #encodeUrl(String)
     * @see #encodeHtml(String)
     * @see #encodeXml(String)
     * @see #encodeSql(String)
     * @see #encodeLatex(String)
     * @see #encodeRegexp(String)
     * @since 1.0
     */
    public static String encodeClassname(String name)
    {
        if (null == name)
        {
            return null;
        }
   /**
    * Counts the number of times a substring occures in a provided string.
    *
    * @param source The <code>String</code> object that will be searched in.
    * @param substring The string whose occurances will we counted.
    * @param matchCase A <code>boolean</code> indicating if the match is
    * going to be performed in a case-sensitive manner or not.
    * @return An <code>int</code> value containing the number of occurances
    * of the substring.
    * @since 1.0
    */
   public static int count(String source, String substring, boolean matchCase)
   {
      if (null == source)
      {
         return 0;
      }
        Pattern pattern = Pattern.compile("[^\\w]");
        Matcher matcher = pattern.matcher(name);
      if (null == substring)
      {
         return 0;
      }
        return matcher.replaceAll("_");
    }
      int current_index = 0;
      int substring_index = 0;
      int count = 0;
    private static boolean needsUrlEncoding(String source)
    {
        if (null == source)
        {
            return false;
        }
      if (!matchCase)
      {
         source = source.toLowerCase();
         substring = substring.toLowerCase();
      }
        // check if the string needs encoding first since
        // the URLEncoder always allocates a StringBuffer, even when the
        // string is returned as-is
        boolean encode = false;
        char ch;
        for (int i = 0; i < source.length(); i++)
        {
            ch = source.charAt(i);
      while (current_index < source.length()-1)
      {
         substring_index = source.indexOf(substring, current_index);
            if (ch >= 'a' && ch <= 'z' ||
                    ch >= 'A' && ch <= 'Z' ||
                    ch >= '0' && ch <= '9' ||
                    ch == '-' || ch == '_' || ch == '.' || ch == '*')
            {
                continue;
            }
         if (-1 == substring_index)
         {
            break;
         }
         else
         {
            current_index = substring_index + substring.length();
            count++;
         }
      }
            encode = true;
            break;
        }
      return count;
   }
        return encode;
    }
   /**
    * Splits a string into different parts, using a seperator string to
    * detect the seperation boundaries in a case-sensitive manner. The
    * seperator will not be included in the list of parts.
    *
    * @param source The string that will be split into parts.
    * @param seperator The seperator string that will be used to determine
    * the parts.
    * @return An <code>ArrayList</code> containing the parts as
    * <code>String</code> objects.
    * @since 1.0
    */
   public static ArrayList<String> split(String source, String seperator)
   {
      return split(source, seperator, true);
   }
    /**
     * Transforms a provided <code>String</code> object into a new string,
     * containing only valid URL characters.
     *
     * @param source The string that has to be transformed into a valid URL
     *               string.
     * @return The encoded <code>String</code> object.
     * @see #encodeClassname(String)
     * @see #encodeUrlValue(String)
     * @see #encodeHtml(String)
     * @see #encodeXml(String)
     * @see #encodeSql(String)
     * @see #encodeLatex(String)
     * @see #encodeRegexp(String)
     * @since 1.0
     */
    public static String encodeUrl(String source)
    {
        if (!needsUrlEncoding(source))
        {
            return source;
        }
   /**
    * Splits a string into different parts, using a seperator string to
    * detect the seperation boundaries. The seperator will not be included in
    * the list of parts.
    *
    * @param source The string that will be split into parts.
    * @param seperator The seperator string that will be used to determine
    * the parts.
    * @param matchCase A <code>boolean</code> indicating if the match is
    * going to be performed in a case-sensitive manner or not.
    * @return An <code>ArrayList</code> containing the parts as
    * <code>String</code> objects.
    * @since 1.0
    */
   public static ArrayList<String> split(String source, String seperator, boolean matchCase)
   {
      ArrayList<String>   substrings = new ArrayList<String>();
        try
        {
            return URLEncoder.encode(source, ENCODING_ISO_8859_1);
        }
        ///CLOVER:OFF
        catch (UnsupportedEncodingException e)
        {
            // this should never happen, ISO-8859-1 is a standard encoding
            throw new RuntimeException(e);
        }
        ///CLOVER:ON
    }
      if (null == source)
      {
         return substrings;
      }
    /**
     * Transforms a provided <code>String</code> object into a new string,
     * only pure US Ascii strings are preserved and URL encoded in a regular
     * way. Strings with characters from other encodings will be encoded in a
     * RIFE-specific manner to allow international data to passed along the
     * query string.
     *
     * @param source The string that has to be transformed into a valid URL
     *               parameter string.
     * @return The encoded <code>String</code> object.
     * @see #decodeUrlValue(String)
     * @see #encodeClassname(String)
     * @see #encodeUrl(String)
     * @see #encodeHtml(String)
     * @see #encodeXml(String)
     * @see #encodeSql(String)
     * @see #encodeLatex(String)
     * @see #encodeRegexp(String)
     * @since 1.0
     */
    public static String encodeUrlValue(String source)
    {
        if (!needsUrlEncoding(source))
        {
            return source;
        }
      if (null == seperator)
      {
         substrings.add(source);
         return substrings;
      }
        // check if the string is valid US-ASCII encoding
        boolean valid = true;
        CharsetEncoder encoder = CHARSET_US_ASCII.newEncoder();
        try
        {
            encoder.encode(CharBuffer.wrap(source));
        }
        catch (CharacterCodingException e)
        {
            valid = false;
        }
      int      current_index = 0;
      int      delimiter_index = 0;
      String   element = null;
        try
        {
            // if it is valid US-ASCII, use the regular URL encoding method
            if (valid)
            {
                return URLEncoder.encode(source, ENCODING_US_ASCII);
            }
            // otherwise, base-64 encode the UTF-8 bytes and mark the string
            // as being encoded in a special way
            else
            {
                StringBuilder encoded = new StringBuilder("%02%02");
                String base64 = Base64.encodeToString(source.getBytes(ENCODING_UTF_8), false);
                String base64_urlsafe = replace(base64, "=", "%3D");
                encoded.append(base64_urlsafe);
      String  source_lookup_reference = null;
      if (!matchCase)
      {
         source_lookup_reference = source.toLowerCase();
         seperator = seperator.toLowerCase();
      }
      else
      {
         source_lookup_reference = source;
      }
                return encoded.toString();
            }
        }
        ///CLOVER:OFF
        catch (UnsupportedEncodingException e)
        {
            // this should never happen, ISO-8859-1 is a standard encoding
            throw new RuntimeException(e);
        }
        ///CLOVER:ON
    }
      while (current_index <= source_lookup_reference.length())
      {
         delimiter_index = source_lookup_reference.indexOf(seperator, current_index);
    /**
     * Decodes a <code>String</code> that has been encoded in a RIFE-specific
     * manner for URL usage.. Before calling this method, you should first
     * verify if the value needs decoding by using the
     * <code>doesUrlValueNeedDecoding(String)</code> method.
     *
     * @param source the value that has been encoded for URL usage in a
     *               RIFE-specific way
     * @return The decoded <code>String</code> object.
     * @see #encodeUrlValue(String)
     * @see #doesUrlValueNeedDecoding(String)
     * @since 1.0
     */
    public static String decodeUrlValue(String source)
    {
        try
        {
            byte[] decoded = Base64.decode(source.substring(2));
            if (null == decoded)
            {
                return null;
            } else
            {
                return new String(decoded, StringUtils.ENCODING_UTF_8);
            }
        }
        ///CLOVER:OFF
        catch (UnsupportedEncodingException e)
        {
            // this should never happen, UTF-8 is a standard encoding
            throw new RuntimeException(e);
        }
        ///CLOVER:ON
    }
         if (-1 == delimiter_index)
         {
            element = new String(source.substring(current_index, source.length()));
            substrings.add(element);
            current_index = source.length() + 1;
         }
         else
         {
            element = new String(source.substring(current_index, delimiter_index));
            substrings.add(element);
            current_index = delimiter_index + seperator.length();
         }
      }
    /**
     * Checks if a <code>String</code> is encoded in a RIFE-specific manner
     * for URL usage.
     *
     * @param source the value that might have been encoded for URL usage in a
     *               RIFE-specific way
     * @return <code>true</code> if the value is encoded in the RIFE-specific
     *         format; and
     *         <p><code>false</code> otherwise
     * @see #encodeUrlValue(String)
     * @see #decodeUrlValue(String)
     * @since 1.0
     */
    public static boolean doesUrlValueNeedDecoding(String source)
    {
        if (source != null &&
                source.length() > 2 &&
                source.startsWith("\u0002\u0002"))
        {
            return true;
        }
      return substrings;
   }
        return false;
    }
   /**
    * Splits a string into different parts, using a seperator string to
    * detect the seperation boundaries in a case-sensitive manner. The
    * seperator will not be included in the parts array.
    *
    * @param source The string that will be split into parts.
    * @param seperator The seperator string that will be used to determine
    * the parts.
    * @return A <code>String[]</code> array containing the seperated parts.
    * @since 1.0
    */
   public static String[] splitToArray(String source, String seperator)
   {
      return splitToArray(source, seperator, true);
   }
    private static boolean needsHtmlEncoding(String source, boolean defensive)
    {
        if (null == source)
        {
            return false;
        }
   /**
    * Splits a string into different parts, using a seperator string to
    * detect the seperation boundaries. The seperator will not be included in
    * the parts array.
    *
    * @param source The string that will be split into parts.
    * @param seperator The seperator string that will be used to determine
    * the parts.
    * @param matchCase A <code>boolean</code> indicating if the match is
    * going to be performed in a case-sensitive manner or not.
    * @return A <code>String[]</code> array containing the seperated parts.
    * @since 1.0
    */
   public static String[] splitToArray(String source, String seperator, boolean matchCase)
   {
      ArrayList<String>   substrings = split(source, seperator, matchCase);
      String[]            substrings_array = new String[substrings.size()];
      substrings_array = substrings.toArray(substrings_array);
        boolean encode = false;
        char ch;
        for (int i = 0; i < source.length(); i++)
        {
            ch = source.charAt(i);
      return substrings_array;
   }
            if ((defensive || (ch != '\u0022' && ch != '\u0026' && ch != '\u003C' && ch != '\u003E')) &&
                    ch < '\u00A0')
            {
                continue;
            }
   /**
    * Splits a string into integers, using a seperator string to detect the
    * seperation boundaries in a case-sensitive manner. If a part couldn't be
    * converted to an integer, it will be omitted from the resulting array.
    *
    * @param source The string that will be split into integers.
    * @param seperator The seperator string that will be used to determine
    * the parts.
    * @return An <code>int[]</code> array containing the seperated parts.
    * @since 1.0
    */
   public static int[] splitToIntArray(String source, String seperator)
   {
      return splitToIntArray(source, seperator, true);
   }
            encode = true;
            break;
        }
   /**
    * Splits a string into integers, using a seperator string to detect the
    * seperation boundaries. If a part couldn't be converted to an integer,
    * it will be omitted from the resulting array.
    *
    * @param source The string that will be split into integers.
    * @param seperator The seperator string that will be used to determine
    * the parts.
    * @param matchCase A <code>boolean</code> indicating if the match is
    * going to be performed in a case-sensitive manner or not.
    * @return An <code>int[]</code> array containing the seperated parts.
    * @since 1.0
    */
   public static int[] splitToIntArray(String source, String seperator, boolean matchCase)
   {
      ArrayList<String>   string_parts = split(source, seperator, matchCase);
      int                 number_of_valid_parts = 0;
        return encode;
    }
      for (String string_part : string_parts)
      {
         try
         {
            Integer.parseInt(string_part);
            number_of_valid_parts++;
         }
         catch (NumberFormatException e)
         {
            // just continue
         }
      }
    /**
     * @since 1.6
     */
    public static String decodeHtml(String source)
    {
        if (null == source ||
                0 == source.length())
        {
            return source;
        }
      int[]   string_parts_int = (int[]) Array.newInstance(int.class, number_of_valid_parts);
      int     added_parts = 0;
        int current_index = 0;
        int delimiter_start_index = 0;
        int delimiter_end_index = 0;
      for (String string_part : string_parts)
      {
         try
         {
            string_parts_int[added_parts] = Integer.parseInt(string_part);
            added_parts++;
         }
         catch (NumberFormatException e)
         {
            // just continue
         }
      }
        StringBuilder result = null;
      return string_parts_int;
   }
        while (current_index <= source.length())
        {
            delimiter_start_index = source.indexOf('&', current_index);
            if (delimiter_start_index != -1)
            {
                delimiter_end_index = source.indexOf(';', delimiter_start_index + 1);
                if (delimiter_end_index != -1)
                {
                    // ensure that the string builder is setup correctly
                    if (null == result)
                    {
                        result = new StringBuilder();
                    }
   /**
    * Splits a string into bytes, using a seperator string to detect the
    * seperation boundaries in a case-sensitive manner. If a part couldn't be
    * converted to a <code>byte</code>, it will be omitted from the resulting
    * array.
    *
    * @param source The string that will be split into bytes.
    * @param seperator The seperator string that will be used to determine
    * the parts.
    * @return A <code>byte[]</code> array containing the bytes.
    * @since 1.0
    */
   public static byte[] splitToByteArray(String source, String seperator)
   {
      return splitToByteArray(source, seperator, true);
   }
                    // add the text that leads up to this match
                    if (delimiter_start_index > current_index)
                    {
                        result.append(source.substring(current_index, delimiter_start_index));
                    }
   /**
    * Splits a string into bytes, using a seperator string to detect the
    * seperation boundaries. If a part couldn't be converted to a
    * <code>byte</code>, it will be omitted from the resulting array.
    *
    * @param source The string that will be split into bytes.
    * @param seperator The seperator string that will be used to determine
    * the parts.
    * @param matchCase A <code>boolean</code> indicating if the match is
    * going to be performed in a case-sensitive manner or not.
    * @return A <code>byte[]</code> array containing the bytes.
    * @since 1.0
    */
   public static byte[] splitToByteArray(String source, String seperator, boolean matchCase)
   {
      ArrayList<String>   string_parts = split(source, seperator, matchCase);
      int                 number_of_valid_parts = 0;
      for (String string_part : string_parts)
      {
         try
         {
            Byte.parseByte(string_part);
            number_of_valid_parts++;
         }
         catch (NumberFormatException e)
         {
            // just continue
         }
      }
                    // add the decoded entity
                    String entity = source.substring(delimiter_start_index, delimiter_end_index + 1);
      byte[]  string_parts_byte = (byte[])Array.newInstance(byte.class, number_of_valid_parts);
      int     added_parts = 0;
      for (String string_part : string_parts)
      {
         try
         {
            string_parts_byte[added_parts] = Byte.parseByte(string_part);
            added_parts++;
         }
         catch (NumberFormatException e)
         {
            // just continue
         }
      }
                    current_index = delimiter_end_index + 1;
      return string_parts_byte;
   }
                    // try to decoded numeric entities
                    if (entity.charAt(1) == '#')
                    {
                        int start = 2;
                        int radix = 10;
                        // check if the number is hexadecimal
                        if (entity.charAt(2) == 'X' || entity.charAt(2) == 'x')
                        {
                            start++;
                            radix = 16;
                        }
                        try
                        {
                            Character c = new Character((char) Integer.parseInt(entity.substring(start, entity.length() - 1), radix));
                            result.append(c);
                        }
                        // when the number of the entity can't be parsed, add the entity as-is
                        catch (NumberFormatException e)
                        {
                            result.append(entity);
                        }
                    } else
                    {
                        // try to decode the entity as a literal
                        Character decoded = HTML_DECODE_MAP.get(entity);
                        if (decoded != null)
                        {
                            result.append(decoded);
                        }
                        // if there was no match, add the entity as-is
                        else
                        {
                            result.append(entity);
                        }
                    }
                } else
                {
                    break;
                }
            } else
            {
                break;
            }
        }
   /**
    * Removes all occurances of a string from the front of another string in
    * a case-sensitive manner.
    *
    * @param source The string in which the matching will be done.
    * @param stringToStrip The string that will be stripped from the front.
    * @return A new <code>String</code> containing the stripped result.
    * @since 1.0
    */
   public static String stripFromFront(String source, String stringToStrip)
   {
      return stripFromFront(source, stringToStrip, true);
   }
        if (null == result)
        {
            return source;
        } else if (current_index < source.length())
        {
            result.append(source.substring(current_index));
        }
   /**
    * Removes all occurances of a string from the front of another string.
    *
    * @param source The string in which the matching will be done.
    * @param stringToStrip The string that will be stripped from the front.
    * @param matchCase A <code>boolean</code> indicating if the match is
    * going to be performed in a case-sensitive manner or not.
    * @return A new <code>String</code> containing the stripping result.
    * @since 1.0
    */
   public static String stripFromFront(String source, String stringToStrip, boolean matchCase)
   {
      if (null == source)
      {
         return null;
      }
        return result.toString();
    }
      if (null == stringToStrip)
      {
         return source;
      }
    /**
     * Transforms a provided <code>String</code> object into a new string,
     * containing only valid Html characters.
     *
     * @param source The string that has to be transformed into a valid Html
     *               string.
     * @return The encoded <code>String</code> object.
     * @see #encodeClassname(String)
     * @see #encodeUrl(String)
     * @see #encodeUrlValue(String)
     * @see #encodeXml(String)
     * @see #encodeSql(String)
     * @see #encodeString(String)
     * @see #encodeLatex(String)
     * @see #encodeRegexp(String)
     * @since 1.0
     */
    public static String encodeHtml(String source)
    {
        if (needsHtmlEncoding(source, false))
        {
            return encode(source, HTML_ENCODER_FALLBACK, AGGRESSIVE_HTML_ENCODE_MAP, DEFENSIVE_HTML_ENCODE_MAP);
        }
        return source;
    }
      int strip_length = stringToStrip.length();
      int new_index = 0;
      int last_index = 0;
    /**
     * Transforms a provided <code>String</code> object into a new string,
     * containing as much as possible Html characters. It is safe to already
     * feed existing Html to this method since &amp;, &lt; and &gt; will not
     * be encoded.
     *
     * @param source The string that has to be transformed into a valid Html
     *               string.
     * @return The encoded <code>String</code> object.
     * @see #encodeClassname(String)
     * @see #encodeUrl(String)
     * @see #encodeUrlValue(String)
     * @see #encodeXml(String)
     * @see #encodeSql(String)
     * @see #encodeString(String)
     * @see #encodeLatex(String)
     * @see #encodeRegexp(String)
     * @since 1.0
     */
    public static String encodeHtmlDefensive(String source)
    {
        if (needsHtmlEncoding(source, true))
        {
            return encode(source, null, DEFENSIVE_HTML_ENCODE_MAP);
        }
        return source;
    }
      String  source_lookup_reference = null;
      if (!matchCase)
      {
         source_lookup_reference = source.toLowerCase();
         stringToStrip = stringToStrip.toLowerCase();
      }
      else
      {
         source_lookup_reference = source;
      }
    /**
     * Transforms a provided <code>String</code> object into a new string,
     * containing only valid XML characters.
     *
     * @param source The string that has to be transformed into a valid XML
     *               string.
     * @return The encoded <code>String</code> object.
     * @see #encodeClassname(String)
     * @see #encodeUrl(String)
     * @see #encodeUrlValue(String)
     * @see #encodeHtml(String)
     * @see #encodeSql(String)
     * @see #encodeString(String)
     * @see #encodeLatex(String)
     * @see #encodeRegexp(String)
     * @since 1.0
     */
    public static String encodeXml(String source)
    {
        return encode(source, null, XML_ENCODE_MAP);
    }
      new_index = source_lookup_reference.indexOf(stringToStrip);
      if (0 == new_index)
      {
         do
         {
            last_index = new_index;
            new_index = source_lookup_reference.indexOf(stringToStrip, new_index+strip_length);
         }
         while (new_index != -1 &&
               new_index == last_index+strip_length);
    /**
     * Transforms a provided <code>String</code> object into a new string,
     * containing only valid <code>String</code> characters.
     *
     * @param source The string that has to be transformed into a valid
     *               sequence of <code>String</code> characters.
     * @return The encoded <code>String</code> object.
     * @see #encodeClassname(String)
     * @see #encodeUrl(String)
     * @see #encodeUrlValue(String)
     * @see #encodeHtml(String)
     * @see #encodeXml(String)
     * @see #encodeSql(String)
     * @see #encodeLatex(String)
     * @see #encodeRegexp(String)
     * @since 1.0
     */
    public static String encodeString(String source)
    {
        return encode(source, null, STRING_ENCODE_MAP);
    }
         return source.substring(last_index+strip_length);
      }
      else
      {
         return source;
      }
   }
    /**
     * Transforms a provided <code>String</code> object into a series of
     * unicode escape codes.
     *
     * @param source The string that has to be transformed into a valid
     *               sequence of unicode escape codes
     * @return The encoded <code>String</code> object.
     * @see #encodeClassname(String)
     * @see #encodeUrl(String)
     * @see #encodeUrlValue(String)
     * @see #encodeHtml(String)
     * @see #encodeXml(String)
     * @see #encodeSql(String)
     * @see #encodeLatex(String)
     * @see #encodeRegexp(String)
     * @since 1.0
     */
    public static String encodeUnicode(String source)
    {
        if (null == source)
        {
            return null;
        }
   /**
    * Removes all occurances of a string from the end of another string in a
    * case-sensitive manner.
    *
    * @param source The string in which the matching will be done.
    * @param stringToStrip The string that will be stripped from the end.
    * @return A new <code>String</code> containing the stripped result.
    * @since 1.0
    */
   public static String stripFromEnd(String source, String stringToStrip)
   {
      return stripFromEnd(source, stringToStrip, true);
   }
        StringBuilder encoded = new StringBuilder();
        String hexstring = null;
        for (int i = 0; i < source.length(); i++)
        {
            hexstring = Integer.toHexString((int) source.charAt(i)).toUpperCase();
            encoded.append("\\u");
            // fill with zeros
            for (int j = hexstring.length(); j < 4; j++)
            {
                encoded.append("0");
            }
            encoded.append(hexstring);
        }
   /**
    * Removes all occurances of a string from the end of another string.
    *
    * @param source The string in which the matching will be done.
    * @param stringToStrip The string that will be stripped from the end.
    * @param matchCase A <code>boolean</code> indicating if the match is
    * going to be performed in a case-sensitive manner or not.
    * @return A new <code>String</code> containing the stripped result.
    * @since 1.0
    */
   public static String stripFromEnd(String source, String stringToStrip, boolean matchCase)
   {
      if (null == source)
      {
         return null;
      }
        return encoded.toString();
    }
      if (null == stringToStrip)
      {
         return source;
      }
    /**
     * Transforms a provided <code>String</code> object into a new string,
     * containing only valid Sql characters.
     *
     * @param source The string that has to be transformed into a valid Sql
     *               string.
     * @return The encoded <code>String</code> object.
     * @see #encodeClassname(String)
     * @see #encodeUrl(String)
     * @see #encodeUrlValue(String)
     * @see #encodeHtml(String)
     * @see #encodeXml(String)
     * @see #encodeString(String)
     * @see #encodeLatex(String)
     * @see #encodeRegexp(String)
     * @since 1.0
     */
    public static String encodeSql(String source)
    {
        return encode(source, null, SQL_ENCODE_MAP);
    }
      int strip_length = stringToStrip.length();
      int new_index = 0;
      int last_index = 0;
    /**
     * Transforms a provided <code>String</code> object into a new string,
     * containing only valid LaTeX characters.
     *
     * @param source The string that has to be transformed into a valid LaTeX
     *               string.
     * @return The encoded <code>String</code> object.
     * @see #encodeClassname(String)
     * @see #encodeUrl(String)
     * @see #encodeUrlValue(String)
     * @see #encodeHtml(String)
     * @see #encodeXml(String)
     * @see #encodeSql(String)
     * @see #encodeString(String)
     * @see #encodeRegexp(String)
     * @since 1.0
     */
    public static String encodeLatex(String source)
    {
        if (null == source)
        {
            return null;
        }
      String  source_lookup_reference = null;
      if (!matchCase)
      {
         source_lookup_reference = source.toLowerCase();
         stringToStrip = stringToStrip.toLowerCase();
      }
      else
      {
         source_lookup_reference = source;
      }
        source = encode(source, null, LATEX_ENCODE_MAP);
        source = StringUtils.replace(source, "latex", "\\LaTeX", false);
      new_index = source_lookup_reference.lastIndexOf(stringToStrip);
      if (new_index != -1 &&
         source.length() == new_index+strip_length)
      {
         do
         {
            last_index = new_index;
            new_index = source_lookup_reference.lastIndexOf(stringToStrip, last_index-1);
         }
         while (new_index != -1 &&
               new_index == last_index-strip_length);
        return source;
    }
         return source.substring(0, last_index);
      }
      else
      {
         return source;
      }
   }
    /**
     * Transforms a provided <code>String</code> object into a new string,
     * using the mapping that are provided through the supplied encoding
     * table.
     *
     * @param source         The string that has to be transformed into a valid
     *                       string, using the mappings that are provided through the supplied
     *                       encoding table.
     * @param encodingTables A <code>Map</code> object containing the mappings
     *                       to transform characters into valid entities. The keys of this map
     *                       should be <code>Character</code> objects and the values
     *                       <code>String</code> objects.
     * @return The encoded <code>String</code> object.
     * @since 1.0
     */
    private static String encode(String source, EncoderFallbackHandler fallbackHandler, Map<Character, String>... encodingTables)
    {
        if (null == source)
        {
            return null;
        }
   /**
    * Searches for a string within a specified string in a case-sensitive
    * manner and replaces every match with another string.
    *
    * @param source The string in which the matching parts will be replaced.
    * @param stringToReplace The string that will be searched for.
    * @param replacementString The string that will replace each matching
    * part.
    * @return A new <code>String</code> object containing the replacement
    * result.
    * @since 1.0
    */
   public static String replace(String source, String stringToReplace, String replacementString)
   {
      return replace(source, stringToReplace, replacementString, true);
   }
        if (null == encodingTables ||
                0 == encodingTables.length)
        {
            return source;
        }
   /**
    * Searches for a string within a specified string and replaces every
    * match with another string.
    *
    * @param source The string in which the matching parts will be replaced.
    * @param stringToReplace The string that will be searched for.
    * @param replacementString The string that will replace each matching
    * part.
    * @param matchCase A <code>boolean</code> indicating if the match is
    * going to be performed in a case-sensitive manner or not.
    * @return A new <code>String</code> object containing the replacement
    * result.
    * @since 1.0
    */
   public static String replace(String source, String stringToReplace, String replacementString, boolean matchCase)
   {
      if (null == source)
      {
         return null;
      }
        StringBuilder encoded_string = null;
        char[] string_to_encode_array = source.toCharArray();
        int last_match = -1;
      if (null == stringToReplace)
      {
         return source;
      }
        for (int i = 0; i < string_to_encode_array.length; i++)
        {
            char char_to_encode = string_to_encode_array[i];
            for (Map<Character, String> encoding_table : encodingTables)
            {
                if (encoding_table.containsKey(char_to_encode))
                {
                    encoded_string = prepareEncodedString(source, encoded_string, i, last_match, string_to_encode_array);
      if (null == replacementString)
      {
         return source;
      }
                    encoded_string.append(encoding_table.get(char_to_encode));
                    last_match = i;
                }
            }
      Iterator<String> string_parts = split(source, stringToReplace, matchCase).iterator();
      StringBuilder      new_string = new StringBuilder();
            if (fallbackHandler != null &&
                    last_match < i &&
                    fallbackHandler.hasFallback(char_to_encode))
            {
                encoded_string = prepareEncodedString(source, encoded_string, i, last_match, string_to_encode_array);
      while (string_parts.hasNext())
      {
         String string_part = string_parts.next();
         new_string.append(string_part);
         if (string_parts.hasNext())
         {
            new_string.append(replacementString);
         }
      }
                fallbackHandler.appendFallback(encoded_string, char_to_encode);
                last_match = i;
            }
        }
      return new_string.toString();
   }
        if (null == encoded_string)
        {
            return source;
        } else
        {
            int difference = string_to_encode_array.length - (last_match + 1);
            if (difference > 0)
            {
                encoded_string.append(string_to_encode_array, last_match + 1, difference);
            }
            return encoded_string.toString();
        }
    }
   /**
    * Creates a new string that contains the provided string a number of
    * times.
    *
    * @param source The string that will be repeated.
    * @param count The number of times that the string will be repeated.
    * @return A new <code>String</code> object containing the repeated
    * concatenation result.
    * @since 1.0
    */
   public static String repeat(String source, int count)
   {
      if (null == source)
      {
         return null;
      }
    private static StringBuilder prepareEncodedString(String source, StringBuilder encodedString, int i, int lastMatch, char[] stringToEncodeArray)
    {
        if (null == encodedString)
        {
            encodedString = new StringBuilder(source.length());
        }
      StringBuilder new_string = new StringBuilder();
      while (count > 0)
      {
         new_string.append(source);
         count --;
      }
        int difference = i - (lastMatch + 1);
        if (difference > 0)
        {
            encodedString.append(stringToEncodeArray, lastMatch + 1, difference);
        }
      return new_string.toString();
   }
        return encodedString;
    }
   /**
    * Creates a new array of <code>String</code> objects, containing the
    * elements of a supplied <code>Iterator</code>.
    *
    * @param iterator The iterator containing the elements to create the
    * array with.
    * @return The new <code>String</code> array.
    * @since 1.0
    */
   public static String[] toStringArray(Iterator<String> iterator)
   {
      if (null == iterator)
      {
         return new String[0];
      }
    private static interface EncoderFallbackHandler
    {
        abstract boolean hasFallback(char character);
      ArrayList<String>   strings = new ArrayList<String>();
        abstract void appendFallback(StringBuilder encodedBuffer, char character);
    }
      while (iterator.hasNext())
      {
         strings.add(iterator.next());
      }
    private static class HtmlEncoderFallbackHandler implements EncoderFallbackHandler
    {
        private final static String PREFIX = "&#";
        private final static String SUFFIX = ";";
      String[] string_array = new String[strings.size()];
      strings.toArray(string_array);
        public boolean hasFallback(char character)
        {
            if (character < '\u00A0')
            {
                return false;
            }
      return string_array;
   }
            return true;
        }
   /**
    * Creates a new <code>ArrayList</code>, containing the elements of a
    * supplied array of <code>String</code> objects.
    *
    * @param stringArray The array of <code>String</code> objects that have
    * to be converted.
    * @return The new <code>ArrayList</code> with the elements of the
    * <code>String</code> array.
    * @since 1.0
    */
   public static ArrayList<String> toArrayList(String[] stringArray)
   {
      ArrayList<String> strings = new ArrayList<String>();
        public void appendFallback(StringBuilder encodedBuffer, char character)
        {
            encodedBuffer.append(PREFIX);
            encodedBuffer.append((int) character);
            encodedBuffer.append(SUFFIX);
        }
    }
      if (null == stringArray)
      {
         return strings;
      }
    /**
     * Transforms a provided <code>String</code> object into a literal that can
     * be included into a regular expression {@link Pattern} as-is. None of the
     * regular expression escapes in the string will be functional anymore.
     *
     * @param source The string that has to be escaped as a literal
     * @return The encoded <code>String</code> object.
     * @see #encodeClassname(String)
     * @see #encodeUrl(String)
     * @see #encodeUrlValue(String)
     * @see #encodeHtml(String)
     * @see #encodeXml(String)
     * @see #encodeSql(String)
     * @see #encodeString(String)
     * @see #encodeLatex(String)
     * @since 1.3
     */
    public static String encodeRegexp(String source)
    {
        int regexp_quote_start = source.indexOf("\\E");
        if (-1 == regexp_quote_start)
        {
            return "\\Q" + source + "\\E";
        }
      for (String element : stringArray)
      {
         strings.add(element);
      }
        StringBuilder buffer = new StringBuilder(source.length() * 2);
        buffer.append("\\Q");
      return strings;
   }
        regexp_quote_start = 0;
   /**
    * Creates a new <code>String</code> object, containing the elements of a
    * supplied <code>Collection</code> of <code>String</code> objects joined
    * by a given seperator.
    *
    * @param collection The <code>Collection</code> containing the elements
    * to join.
    * @param seperator The seperator used to join the string elements.
    * @return A new <code>String</code> with the join result.
    * @since 1.0
    */
   public static String join(Collection collection, String seperator)
   {
      if (null == collection)
      {
         return null;
      }
        int current = 0;
        while (-1 == (regexp_quote_start = source.indexOf("\\E", current)))
        {
            buffer.append(source.substring(current, regexp_quote_start));
            current = regexp_quote_start + 2;
            buffer.append("\\E\\\\E\\Q");
        }
      if (null == seperator)
      {
         seperator = "";
      }
        buffer.append(source.substring(current, source.length()));
        buffer.append("\\E");
      if (0 == collection.size())
      {
         return "";
      }
      else
      {
         StringBuilder result = new StringBuilder();
         for (Object element : collection)
         {
            result.append(String.valueOf(element));
            result.append(seperator);
         }
        return buffer.toString();
    }
    /**
     * Counts the number of times a substring occures in a provided string in
     * a case-sensitive manner.
     *
     * @param source    The <code>String</code> object that will be searched in.
     * @param substring The string whose occurances will we counted.
     * @return An <code>int</code> value containing the number of occurances
     *         of the substring.
     * @since 1.0
     */
    public static int count(String source, String substring)
    {
        return count(source, substring, true);
    }
    /**
     * Counts the number of times a substring occures in a provided string.
     *
     * @param source    The <code>String</code> object that will be searched in.
     * @param substring The string whose occurances will we counted.
     * @param matchCase A <code>boolean</code> indicating if the match is
     *                  going to be performed in a case-sensitive manner or not.
     * @return An <code>int</code> value containing the number of occurances
     *         of the substring.
     * @since 1.0
     */
    public static int count(String source, String substring, boolean matchCase)
    {
        if (null == source)
        {
            return 0;
        }
        if (null == substring)
        {
            return 0;
        }
        int current_index = 0;
        int substring_index = 0;
        int count = 0;
        if (!matchCase)
        {
            source = source.toLowerCase();
            substring = substring.toLowerCase();
        }
        while (current_index < source.length() - 1)
        {
            substring_index = source.indexOf(substring, current_index);
            if (-1 == substring_index)
            {
                break;
            } else
            {
                current_index = substring_index + substring.length();
                count++;
            }
        }
        return count;
    }
    /**
     * Splits a string into different parts, using a seperator string to
     * detect the seperation boundaries in a case-sensitive manner. The
     * seperator will not be included in the list of parts.
     *
     * @param source    The string that will be split into parts.
     * @param seperator The seperator string that will be used to determine
     *                  the parts.
     * @return An <code>ArrayList</code> containing the parts as
     *         <code>String</code> objects.
     * @since 1.0
     */
    public static ArrayList<String> split(String source, String seperator)
    {
        return split(source, seperator, true);
    }
    /**
     * Splits a string into different parts, using a seperator string to
     * detect the seperation boundaries. The seperator will not be included in
     * the list of parts.
     *
     * @param source    The string that will be split into parts.
     * @param seperator The seperator string that will be used to determine
     *                  the parts.
     * @param matchCase A <code>boolean</code> indicating if the match is
     *                  going to be performed in a case-sensitive manner or not.
     * @return An <code>ArrayList</code> containing the parts as
     *         <code>String</code> objects.
     * @since 1.0
     */
    public static ArrayList<String> split(String source, String seperator, boolean matchCase)
    {
        ArrayList<String> substrings = new ArrayList<String>();
        if (null == source)
        {
            return substrings;
        }
        if (null == seperator)
        {
            substrings.add(source);
            return substrings;
        }
        int current_index = 0;
        int delimiter_index = 0;
        String element = null;
        String source_lookup_reference = null;
        if (!matchCase)
        {
            source_lookup_reference = source.toLowerCase();
            seperator = seperator.toLowerCase();
        } else
        {
            source_lookup_reference = source;
        }
        while (current_index <= source_lookup_reference.length())
        {
            delimiter_index = source_lookup_reference.indexOf(seperator, current_index);
            if (-1 == delimiter_index)
            {
                element = new String(source.substring(current_index, source.length()));
                substrings.add(element);
                current_index = source.length() + 1;
            } else
            {
                element = new String(source.substring(current_index, delimiter_index));
                substrings.add(element);
                current_index = delimiter_index + seperator.length();
            }
        }
        return substrings;
    }
    /**
     * Splits a string into different parts, using a seperator string to
     * detect the seperation boundaries in a case-sensitive manner. The
     * seperator will not be included in the parts array.
     *
     * @param source    The string that will be split into parts.
     * @param seperator The seperator string that will be used to determine
     *                  the parts.
     * @return A <code>String[]</code> array containing the seperated parts.
     * @since 1.0
     */
    public static String[] splitToArray(String source, String seperator)
    {
        return splitToArray(source, seperator, true);
    }
    /**
     * Splits a string into different parts, using a seperator string to
     * detect the seperation boundaries. The seperator will not be included in
     * the parts array.
     *
     * @param source    The string that will be split into parts.
     * @param seperator The seperator string that will be used to determine
     *                  the parts.
     * @param matchCase A <code>boolean</code> indicating if the match is
     *                  going to be performed in a case-sensitive manner or not.
     * @return A <code>String[]</code> array containing the seperated parts.
     * @since 1.0
     */
    public static String[] splitToArray(String source, String seperator, boolean matchCase)
    {
        ArrayList<String> substrings = split(source, seperator, matchCase);
        String[] substrings_array = new String[substrings.size()];
        substrings_array = substrings.toArray(substrings_array);
        return substrings_array;
    }
    /**
     * Splits a string into integers, using a seperator string to detect the
     * seperation boundaries in a case-sensitive manner. If a part couldn't be
     * converted to an integer, it will be omitted from the resulting array.
     *
     * @param source    The string that will be split into integers.
     * @param seperator The seperator string that will be used to determine
     *                  the parts.
     * @return An <code>int[]</code> array containing the seperated parts.
     * @since 1.0
     */
    public static int[] splitToIntArray(String source, String seperator)
    {
        return splitToIntArray(source, seperator, true);
    }
    /**
     * Splits a string into integers, using a seperator string to detect the
     * seperation boundaries. If a part couldn't be converted to an integer,
     * it will be omitted from the resulting array.
     *
     * @param source    The string that will be split into integers.
     * @param seperator The seperator string that will be used to determine
     *                  the parts.
     * @param matchCase A <code>boolean</code> indicating if the match is
     *                  going to be performed in a case-sensitive manner or not.
     * @return An <code>int[]</code> array containing the seperated parts.
     * @since 1.0
     */
    public static int[] splitToIntArray(String source, String seperator, boolean matchCase)
    {
        ArrayList<String> string_parts = split(source, seperator, matchCase);
        int number_of_valid_parts = 0;
        for (String string_part : string_parts)
        {
            try
            {
                Integer.parseInt(string_part);
                number_of_valid_parts++;
            }
            catch (NumberFormatException e)
            {
                // just continue
            }
        }
        int[] string_parts_int = (int[]) Array.newInstance(int.class, number_of_valid_parts);
        int added_parts = 0;
        for (String string_part : string_parts)
        {
            try
            {
                string_parts_int[added_parts] = Integer.parseInt(string_part);
                added_parts++;
            }
            catch (NumberFormatException e)
            {
                // just continue
            }
        }
        return string_parts_int;
    }
    /**
     * Splits a string into bytes, using a seperator string to detect the
     * seperation boundaries in a case-sensitive manner. If a part couldn't be
     * converted to a <code>byte</code>, it will be omitted from the resulting
     * array.
     *
     * @param source    The string that will be split into bytes.
     * @param seperator The seperator string that will be used to determine
     *                  the parts.
     * @return A <code>byte[]</code> array containing the bytes.
     * @since 1.0
     */
    public static byte[] splitToByteArray(String source, String seperator)
    {
        return splitToByteArray(source, seperator, true);
    }
    /**
     * Splits a string into bytes, using a seperator string to detect the
     * seperation boundaries. If a part couldn't be converted to a
     * <code>byte</code>, it will be omitted from the resulting array.
     *
     * @param source    The string that will be split into bytes.
     * @param seperator The seperator string that will be used to determine
     *                  the parts.
     * @param matchCase A <code>boolean</code> indicating if the match is
     *                  going to be performed in a case-sensitive manner or not.
     * @return A <code>byte[]</code> array containing the bytes.
     * @since 1.0
     */
    public static byte[] splitToByteArray(String source, String seperator, boolean matchCase)
    {
        ArrayList<String> string_parts = split(source, seperator, matchCase);
        int number_of_valid_parts = 0;
        for (String string_part : string_parts)
        {
            try
            {
                Byte.parseByte(string_part);
                number_of_valid_parts++;
            }
            catch (NumberFormatException e)
            {
                // just continue
            }
        }
        byte[] string_parts_byte = (byte[]) Array.newInstance(byte.class, number_of_valid_parts);
        int added_parts = 0;
        for (String string_part : string_parts)
        {
            try
            {
                string_parts_byte[added_parts] = Byte.parseByte(string_part);
                added_parts++;
            }
            catch (NumberFormatException e)
            {
                // just continue
            }
        }
        return string_parts_byte;
    }
    /**
     * Removes all occurances of a string from the front of another string in
     * a case-sensitive manner.
     *
     * @param source        The string in which the matching will be done.
     * @param stringToStrip The string that will be stripped from the front.
     * @return A new <code>String</code> containing the stripped result.
     * @since 1.0
     */
    public static String stripFromFront(String source, String stringToStrip)
    {
        return stripFromFront(source, stringToStrip, true);
    }
    /**
     * Removes all occurances of a string from the front of another string.
     *
     * @param source        The string in which the matching will be done.
     * @param stringToStrip The string that will be stripped from the front.
     * @param matchCase     A <code>boolean</code> indicating if the match is
     *                      going to be performed in a case-sensitive manner or not.
     * @return A new <code>String</code> containing the stripping result.
     * @since 1.0
     */
    public static String stripFromFront(String source, String stringToStrip, boolean matchCase)
    {
        if (null == source)
        {
            return null;
        }
        if (null == stringToStrip)
        {
            return source;
        }
        int strip_length = stringToStrip.length();
        int new_index = 0;
        int last_index = 0;
        String source_lookup_reference = null;
        if (!matchCase)
        {
            source_lookup_reference = source.toLowerCase();
            stringToStrip = stringToStrip.toLowerCase();
        } else
        {
            source_lookup_reference = source;
        }
        new_index = source_lookup_reference.indexOf(stringToStrip);
        if (0 == new_index)
        {
            do
            {
                last_index = new_index;
                new_index = source_lookup_reference.indexOf(stringToStrip, new_index + strip_length);
            }
            while (new_index != -1 &&
                    new_index == last_index + strip_length);
            return source.substring(last_index + strip_length);
        } else
        {
            return source;
        }
    }
    /**
     * Removes all occurances of a string from the end of another string in a
     * case-sensitive manner.
     *
     * @param source        The string in which the matching will be done.
     * @param stringToStrip The string that will be stripped from the end.
     * @return A new <code>String</code> containing the stripped result.
     * @since 1.0
     */
    public static String stripFromEnd(String source, String stringToStrip)
    {
        return stripFromEnd(source, stringToStrip, true);
    }
    /**
     * Removes all occurances of a string from the end of another string.
     *
     * @param source        The string in which the matching will be done.
     * @param stringToStrip The string that will be stripped from the end.
     * @param matchCase     A <code>boolean</code> indicating if the match is
     *                      going to be performed in a case-sensitive manner or not.
     * @return A new <code>String</code> containing the stripped result.
     * @since 1.0
     */
    public static String stripFromEnd(String source, String stringToStrip, boolean matchCase)
    {
        if (null == source)
        {
            return null;
        }
        if (null == stringToStrip)
        {
            return source;
        }
        int strip_length = stringToStrip.length();
        int new_index = 0;
        int last_index = 0;
        String source_lookup_reference = null;
        if (!matchCase)
        {
            source_lookup_reference = source.toLowerCase();
            stringToStrip = stringToStrip.toLowerCase();
        } else
        {
            source_lookup_reference = source;
        }
        new_index = source_lookup_reference.lastIndexOf(stringToStrip);
        if (new_index != -1 &&
                source.length() == new_index + strip_length)
        {
            do
            {
                last_index = new_index;
                new_index = source_lookup_reference.lastIndexOf(stringToStrip, last_index - 1);
            }
            while (new_index != -1 &&
                    new_index == last_index - strip_length);
            return source.substring(0, last_index);
        } else
        {
            return source;
        }
    }
    /**
     * Searches for a string within a specified string in a case-sensitive
     * manner and replaces every match with another string.
     *
     * @param source            The string in which the matching parts will be replaced.
     * @param stringToReplace   The string that will be searched for.
     * @param replacementString The string that will replace each matching
     *                          part.
     * @return A new <code>String</code> object containing the replacement
     *         result.
     * @since 1.0
     */
    public static String replace(String source, String stringToReplace, String replacementString)
    {
        return replace(source, stringToReplace, replacementString, true);
    }
    /**
     * Searches for a string within a specified string and replaces every
     * match with another string.
     *
     * @param source            The string in which the matching parts will be replaced.
     * @param stringToReplace   The string that will be searched for.
     * @param replacementString The string that will replace each matching
     *                          part.
     * @param matchCase         A <code>boolean</code> indicating if the match is
     *                          going to be performed in a case-sensitive manner or not.
     * @return A new <code>String</code> object containing the replacement
     *         result.
     * @since 1.0
     */
    public static String replace(String source, String stringToReplace, String replacementString, boolean matchCase)
    {
        if (null == source)
        {
            return null;
        }
        if (null == stringToReplace)
        {
            return source;
        }
        if (null == replacementString)
        {
            return source;
        }
        Iterator<String> string_parts = split(source, stringToReplace, matchCase).iterator();
        StringBuilder new_string = new StringBuilder();
        while (string_parts.hasNext())
        {
            String string_part = string_parts.next();
            new_string.append(string_part);
            if (string_parts.hasNext())
            {
                new_string.append(replacementString);
            }
        }
        return new_string.toString();
    }
    /**
     * Creates a new string that contains the provided string a number of
     * times.
     *
     * @param source The string that will be repeated.
     * @param count  The number of times that the string will be repeated.
     * @return A new <code>String</code> object containing the repeated
     *         concatenation result.
     * @since 1.0
     */
    public static String repeat(String source, int count)
    {
        if (null == source)
        {
            return null;
        }
        StringBuilder new_string = new StringBuilder();
        while (count > 0)
        {
            new_string.append(source);
            count--;
        }
        return new_string.toString();
    }
    /**
     * Creates a new array of <code>String</code> objects, containing the
     * elements of a supplied <code>Iterator</code>.
     *
     * @param iterator The iterator containing the elements to create the
     *                 array with.
     * @return The new <code>String</code> array.
     * @since 1.0
     */
    public static String[] toStringArray(Iterator<String> iterator)
    {
        if (null == iterator)
        {
            return new String[0];
        }
        ArrayList<String> strings = new ArrayList<String>();
        while (iterator.hasNext())
        {
            strings.add(iterator.next());
        }
        String[] string_array = new String[strings.size()];
        strings.toArray(string_array);
        return string_array;
    }
    /**
     * Creates a new <code>ArrayList</code>, containing the elements of a
     * supplied array of <code>String</code> objects.
     *
     * @param stringArray The array of <code>String</code> objects that have
     *                    to be converted.
     * @return The new <code>ArrayList</code> with the elements of the
     *         <code>String</code> array.
     * @since 1.0
     */
    public static ArrayList<String> toArrayList(String[] stringArray)
    {
        ArrayList<String> strings = new ArrayList<String>();
        if (null == stringArray)
        {
            return strings;
        }
        for (String element : stringArray)
        {
            strings.add(element);
        }
        return strings;
    }
    /**
     * Creates a new <code>String</code> object, containing the elements of a
     * supplied <code>Collection</code> of <code>String</code> objects joined
     * by a given seperator.
     *
     * @param collection The <code>Collection</code> containing the elements
     *                   to join.
     * @param seperator  The seperator used to join the string elements.
     * @return A new <code>String</code> with the join result.
     * @since 1.0
     */
    public static String join(Collection collection, String seperator)
    {
        if (null == collection)
        {
            return null;
        }
        if (null == seperator)
        {
            seperator = "";
        }
        if (0 == collection.size())
        {
            return "";
        } else
        {
            StringBuilder result = new StringBuilder();
            for (Object element : collection)
            {
                result.append(String.valueOf(element));
                result.append(seperator);
            }
         result.setLength(result.length()-seperator.length());
         return result.toString();
      }
   }
            result.setLength(result.length() - seperator.length());
            return result.toString();
        }
    }
   /**
    * Creates a new <code>String</code> object, containing the elements of a
    * supplied array, joined by a given seperator.
    *
    * @param array The object array containing the elements to join.
    * @param seperator The seperator used to join the string elements.
    * @return A new <code>String</code> with the join result.
    * @since 1.0
    */
   public static String join(Object[] array, String seperator)
   {
      return join(array, seperator, null, false);
   }
    /**
     * Creates a new <code>String</code> object, containing the elements of a
     * supplied array, joined by a given seperator.
     *
     * @param array     The object array containing the elements to join.
     * @param seperator The seperator used to join the string elements.
     * @return A new <code>String</code> with the join result.
     * @since 1.0
     */
    public static String join(Object[] array, String seperator)
    {
        return join(array, seperator, null, false);
    }
   /**
    * Creates a new <code>String</code> object, containing the elements of a
    * supplied array, joined by a given seperator.
    *
    * @param array The object array containing the elements to join.
    * @param seperator The seperator used to join the string elements.
    * @param delimiter The delimiter used to surround the string elements.
    * @return A new <code>String</code> with the join result.
    * @since 1.0
    */
   public static String join(Object[] array, String seperator, String delimiter)
   {
      return join(array, seperator, delimiter, false);
   }
    /**
     * Creates a new <code>String</code> object, containing the elements of a
     * supplied array, joined by a given seperator.
     *
     * @param array     The object array containing the elements to join.
     * @param seperator The seperator used to join the string elements.
     * @param delimiter The delimiter used to surround the string elements.
     * @return A new <code>String</code> with the join result.
     * @since 1.0
     */
    public static String join(Object[] array, String seperator, String delimiter)
    {
        return join(array, seperator, delimiter, false);
    }
   /**
    * Creates a new <code>String</code> object, containing the elements of a
    * supplied array, joined by a given seperator.
    *
    * @param array The object array containing the elements to join.
    * @param seperator The seperator used to join the string elements.
    * @param delimiter The delimiter used to surround the string elements.
    * @param encodeStrings Indicates whether the characters of the string
    * representation of the Array values should be encoded.
    * @return A new <code>String</code> with the join result.
    * @since 1.0
    */
   public static String join(Object[] array, String seperator, String delimiter, boolean encodeStrings)
   {
      if (null == array)
      {
         return null;
      }
    /**
     * Creates a new <code>String</code> object, containing the elements of a
     * supplied array, joined by a given seperator.
     *
     * @param array         The object array containing the elements to join.
     * @param seperator     The seperator used to join the string elements.
     * @param delimiter     The delimiter used to surround the string elements.
     * @param encodeStrings Indicates whether the characters of the string
     *                      representation of the Array values should be encoded.
     * @return A new <code>String</code> with the join result.
     * @since 1.0
     */
    public static String join(Object[] array, String seperator, String delimiter, boolean encodeStrings)
    {
        if (null == array)
        {
            return null;
        }
      if (null == seperator)
      {
         seperator = "";
      }
        if (null == seperator)
        {
            seperator = "";
        }
      if (null == delimiter)
      {
         delimiter = "";
      }
        if (null == delimiter)
        {
            delimiter = "";
        }
      if (0 == array.length)
      {
         return "";
      }
      else
      {
         int            current_index = 0;
         String         array_value = null;
         StringBuilder   result = new StringBuilder();
         while (current_index < array.length - 1)
         {
            if (null == array[current_index])
            {
               result.append("null");
            }
            else
            {
               array_value = String.valueOf(array[current_index]);
               if (encodeStrings)
               {
                  array_value = encodeString(array_value);
               }
               result.append(delimiter);
               result.append(array_value);
               result.append(delimiter);
            }
            result.append(seperator);
            current_index++;
         }
        if (0 == array.length)
        {
            return "";
        } else
        {
            int current_index = 0;
            String array_value = null;
            StringBuilder result = new StringBuilder();
            while (current_index < array.length - 1)
            {
                if (null == array[current_index])
                {
                    result.append("null");
                } else
                {
                    array_value = String.valueOf(array[current_index]);
                    if (encodeStrings)
                    {
                        array_value = encodeString(array_value);
                    }
                    result.append(delimiter);
                    result.append(array_value);
                    result.append(delimiter);
                }
                result.append(seperator);
                current_index++;
            }
         if (null == array[current_index])
         {
            result.append("null");
         }
         else
         {
            array_value = String.valueOf(array[current_index]);
            if (encodeStrings)
            {
               array_value = encodeString(array_value);
            }
            result.append(delimiter);
            result.append(array_value);
            result.append(delimiter);
         }
         return result.toString();
      }
   }
            if (null == array[current_index])
            {
                result.append("null");
            } else
            {
                array_value = String.valueOf(array[current_index]);
                if (encodeStrings)
                {
                    array_value = encodeString(array_value);
                }
                result.append(delimiter);
                result.append(array_value);
                result.append(delimiter);
            }
            return result.toString();
        }
    }
   /**
    * Creates a new <code>String</code> object, containing the elements of a
    * supplied array, joined by a given seperator.
    *
    * @param array The boolean array containing the values to join.
    * @param seperator The seperator used to join the string elements.
    * @return A new <code>String</code> with the join result.
    * @since 1.0
    */
   public static String join(boolean[] array, String seperator)
   {
      if (null == array)
      {
         return null;
      }
    /**
     * Creates a new <code>String</code> object, containing the elements of a
     * supplied array, joined by a given seperator.
     *
     * @param array     The boolean array containing the values to join.
     * @param seperator The seperator used to join the string elements.
     * @return A new <code>String</code> with the join result.
     * @since 1.0
     */
    public static String join(boolean[] array, String seperator)
    {
        if (null == array)
        {
            return null;
        }
      if (null == seperator)
      {
         seperator = "";
      }
        if (null == seperator)
        {
            seperator = "";
        }
      if (0 == array.length)
      {
         return "";
      }
      else
      {
         int current_index = 0;
         String result = "";
         while (current_index < array.length - 1)
         {
            result = result + array[current_index] + seperator;
            current_index++;
         }
        if (0 == array.length)
        {
            return "";
        } else
        {
            int current_index = 0;
            String result = "";
            while (current_index < array.length - 1)
            {
                result = result + array[current_index] + seperator;
                current_index++;
            }
         result = result +  array[current_index];
         return result;
      }
   }
            result = result + array[current_index];
            return result;
        }
    }
   /**
    * Creates a new <code>String</code> object, containing the elements of a
    * supplied array, joined by a given seperator.
    *
    * @param array The byte array containing the values to join.
    * @param seperator The seperator used to join the string elements.
    * @return A new <code>String</code> with the join result.
    * @since 1.0
    */
   public static String join(byte[] array, String seperator)
   {
      if (null == array)
      {
         return null;
      }
    /**
     * Creates a new <code>String</code> object, containing the elements of a
     * supplied array, joined by a given seperator.
     *
     * @param array     The byte array containing the values to join.
     * @param seperator The seperator used to join the string elements.
     * @return A new <code>String</code> with the join result.
     * @since 1.0
     */
    public static String join(byte[] array, String seperator)
    {
        if (null == array)
        {
            return null;
        }
      if (null == seperator)
      {
         seperator = "";
      }
        if (null == seperator)
        {
            seperator = "";
        }
      if (0 == array.length)
      {
         return "";
      }
      else
      {
         int current_index = 0;
         String result = "";
         while (current_index < array.length - 1)
         {
            result = result + array[current_index] + seperator;
            current_index++;
         }
        if (0 == array.length)
        {
            return "";
        } else
        {
            int current_index = 0;
            String result = "";
            while (current_index < array.length - 1)
            {
                result = result + array[current_index] + seperator;
                current_index++;
            }
         result = result +  array[current_index];
         return result;
      }
   }
            result = result + array[current_index];
            return result;
        }
    }
   /**
    * Creates a new <code>String</code> object, containing the elements of a
    * supplied array, joined by a given seperator.
    *
    * @param array The double array containing the values to join.
    * @param seperator The seperator used to join the string elements.
    * @return A new <code>String</code> with the join result.
    * @since 1.0
    */
   public static String join(double[] array, String seperator)
   {
      if (null == array)
      {
         return null;
      }
    /**
     * Creates a new <code>String</code> object, containing the elements of a
     * supplied array, joined by a given seperator.
     *
     * @param array     The double array containing the values to join.
     * @param seperator The seperator used to join the string elements.
     * @return A new <code>String</code> with the join result.
     * @since 1.0
     */
    public static String join(double[] array, String seperator)
    {
        if (null == array)
        {
            return null;
        }
      if (null == seperator)
      {
         seperator = "";
      }
        if (null == seperator)
        {
            seperator = "";
        }
      if (0 == array.length)
      {
         return "";
      }
      else
      {
         int current_index = 0;
         String result = "";
         while (current_index < array.length - 1)
         {
            result = result + array[current_index] + seperator;
            current_index++;
         }
        if (0 == array.length)
        {
            return "";
        } else
        {
            int current_index = 0;
            String result = "";
            while (current_index < array.length - 1)
            {
                result = result + array[current_index] + seperator;
                current_index++;
            }
         result = result +  array[current_index];
         return result;
      }
   }
            result = result + array[current_index];
            return result;
        }
    }
   /**
    * Creates a new <code>String</code> object, containing the elements of a
    * supplied array, joined by a given seperator.
    *
    * @param array The float array containing the values to join.
    * @param seperator The seperator used to join the string elements.
    * @return A new <code>String</code> with the join result.
    * @since 1.0
    */
   public static String join(float[] array, String seperator)
   {
      if (null == array)
      {
         return null;
      }
    /**
     * Creates a new <code>String</code> object, containing the elements of a
     * supplied array, joined by a given seperator.
     *
     * @param array     The float array containing the values to join.
     * @param seperator The seperator used to join the string elements.
     * @return A new <code>String</code> with the join result.
     * @since 1.0
     */
    public static String join(float[] array, String seperator)
    {
        if (null == array)
        {
            return null;
        }
      if (null == seperator)
      {
         seperator = "";
      }
        if (null == seperator)
        {
            seperator = "";
        }
      if (0 == array.length)
      {
         return "";
      }
      else
      {
         int current_index = 0;
         String result = "";
         while (current_index < array.length - 1)
         {
            result = result + array[current_index] + seperator;
            current_index++;
         }
        if (0 == array.length)
        {
            return "";
        } else
        {
            int current_index = 0;
            String result = "";
            while (current_index < array.length - 1)
            {
                result = result + array[current_index] + seperator;
                current_index++;
            }
         result = result +  array[current_index];
         return result;
      }
   }
            result = result + array[current_index];
            return result;
        }
    }
   /**
    * Creates a new <code>String</code> object, containing the elements of a
    * supplied array, joined by a given seperator.
    *
    * @param array The integer array containing the values to join.
    * @param seperator The seperator used to join the string elements.
    * @return A new <code>String</code> with the join result.
    * @since 1.0
    */
   public static String join(int[] array, String seperator)
   {
      if (null == array)
      {
         return null;
      }
    /**
     * Creates a new <code>String</code> object, containing the elements of a
     * supplied array, joined by a given seperator.
     *
     * @param array     The integer array containing the values to join.
     * @param seperator The seperator used to join the string elements.
     * @return A new <code>String</code> with the join result.
     * @since 1.0
     */
    public static String join(int[] array, String seperator)
    {
        if (null == array)
        {
            return null;
        }
      if (null == seperator)
      {
         seperator = "";
      }
        if (null == seperator)
        {
            seperator = "";
        }
      if (0 == array.length)
      {
         return "";
      }
      else
      {
         int current_index = 0;
         String result = "";
         while (current_index < array.length - 1)
         {
            result = result + array[current_index] + seperator;
            current_index++;
         }
        if (0 == array.length)
        {
            return "";
        } else
        {
            int current_index = 0;
            String result = "";
            while (current_index < array.length - 1)
            {
                result = result + array[current_index] + seperator;
                current_index++;
            }
         result = result +  array[current_index];
         return result;
      }
   }
            result = result + array[current_index];
            return result;
        }
    }
   /**
    * Creates a new <code>String</code> object, containing the elements of a
    * supplied array, joined by a given seperator.
    *
    * @param array The long array containing the values to join.
    * @param seperator The seperator used to join the string elements.
    * @return A new <code>String</code> with the join result.
    * @since 1.0
    */
   public static String join(long[] array, String seperator)
   {
      if (null == array)
      {
         return null;
      }
    /**
     * Creates a new <code>String</code> object, containing the elements of a
     * supplied array, joined by a given seperator.
     *
     * @param array     The long array containing the values to join.
     * @param seperator The seperator used to join the string elements.
     * @return A new <code>String</code> with the join result.
     * @since 1.0
     */
    public static String join(long[] array, String seperator)
    {
        if (null == array)
        {
            return null;
        }
      if (null == seperator)
      {
         seperator = "";
      }
        if (null == seperator)
        {
            seperator = "";
        }
      if (0 == array.length)
      {
         return "";
      }
      else
      {
         int current_index = 0;
         String result = "";
         while (current_index < array.length - 1)
         {
            result = result + array[current_index] + seperator;
            current_index++;
         }
        if (0 == array.length)
        {
            return "";
        } else
        {
            int current_index = 0;
            String result = "";
            while (current_index < array.length - 1)
            {
                result = result + array[current_index] + seperator;
                current_index++;
            }
         result = result +  array[current_index];
         return result;
      }
   }
            result = result + array[current_index];
            return result;
        }
    }
   /**
    * Creates a new <code>String</code> object, containing the elements of a
    * supplied array, joined by a given seperator.
    *
    * @param array The short array containing the values to join.
    * @param seperator The seperator used to join the string elements.
    * @return A new <code>String</code> with the join result.
    * @since 1.0
    */
   public static String join(short[] array, String seperator)
   {
      if (null == array)
      {
         return null;
      }
    /**
     * Creates a new <code>String</code> object, containing the elements of a
     * supplied array, joined by a given seperator.
     *
     * @param array     The short array containing the values to join.
     * @param seperator The seperator used to join the string elements.
     * @return A new <code>String</code> with the join result.
     * @since 1.0
     */
    public static String join(short[] array, String seperator)
    {
        if (null == array)
        {
            return null;
        }
      if (null == seperator)
      {
         seperator = "";
      }
        if (null == seperator)
        {
            seperator = "";
        }
      if (0 == array.length)
      {
         return "";
      }
      else
      {
         int current_index = 0;
         String result = "";
         while (current_index < array.length - 1)
         {
            result = result + array[current_index] + seperator;
            current_index++;
         }
        if (0 == array.length)
        {
            return "";
        } else
        {
            int current_index = 0;
            String result = "";
            while (current_index < array.length - 1)
            {
                result = result + array[current_index] + seperator;
                current_index++;
            }
         result = result +  array[current_index];
         return result;
      }
   }
            result = result + array[current_index];
            return result;
        }
    }
   /**
    * Creates a new <code>String</code> object, containing the elements of a
    * supplied array, joined by a given seperator.
    *
    * @param array The char array containing the values to join.
    * @param seperator The seperator used to join the string elements.
    * @return A new <code>String</code> with the join result.
    * @since 1.0
    */
   public static String join(char[] array, String seperator)
   {
      return join(array, seperator, null);
   }
    /**
     * Creates a new <code>String</code> object, containing the elements of a
     * supplied array, joined by a given seperator.
     *
     * @param array     The char array containing the values to join.
     * @param seperator The seperator used to join the string elements.
     * @return A new <code>String</code> with the join result.
     * @since 1.0
     */
    public static String join(char[] array, String seperator)
    {
        return join(array, seperator, null);
    }
   /**
    * Creates a new <code>String</code> object, containing the elements of a
    * supplied array, joined by a given seperator.
    *
    * @param array The char array containing the values to join.
    * @param seperator The seperator used to join the string elements.
    * @param delimiter The delimiter used to surround the string elements.
    * @return A new <code>String</code> with the join result.
    * @since 1.0
    */
   public static String join(char[] array, String seperator, String delimiter)
   {
      if (null == array)
      {
         return null;
      }
    /**
     * Creates a new <code>String</code> object, containing the elements of a
     * supplied array, joined by a given seperator.
     *
     * @param array     The char array containing the values to join.
     * @param seperator The seperator used to join the string elements.
     * @param delimiter The delimiter used to surround the string elements.
     * @return A new <code>String</code> with the join result.
     * @since 1.0
     */
    public static String join(char[] array, String seperator, String delimiter)
    {
        if (null == array)
        {
            return null;
        }
      if (null == seperator)
      {
         seperator = "";
      }
        if (null == seperator)
        {
            seperator = "";
        }
      if (null == delimiter)
      {
         delimiter = "";
      }
        if (null == delimiter)
        {
            delimiter = "";
        }
      if (0 == array.length)
      {
         return "";
      }
      else
      {
         int current_index = 0;
         StringBuilder   result = new StringBuilder();
         while (current_index < array.length - 1)
         {
            result.append(delimiter);
            result.append(array[current_index]);
            result.append(delimiter);
            result.append(seperator);
            current_index++;
         }
        if (0 == array.length)
        {
            return "";
        } else
        {
            int current_index = 0;
            StringBuilder result = new StringBuilder();
            while (current_index < array.length - 1)
            {
                result.append(delimiter);
                result.append(array[current_index]);
                result.append(delimiter);
                result.append(seperator);
                current_index++;
            }
         result.append(delimiter);
         result.append(String.valueOf(array[current_index]));
         result.append(delimiter);
         return result.toString();
      }
   }
            result.append(delimiter);
            result.append(String.valueOf(array[current_index]));
            result.append(delimiter);
            return result.toString();
        }
    }
   /**
    * Returns an array that contains all the occurances of a substring in a
    * string in the correct order. The search will be performed in a
    * case-sensitive manner.
    *
    * @param source The <code>String</code> object that will be searched in.
    * @param substring The string whose occurances will we counted.
    * @return An <code>int[]</code> array containing the indices of the
    * substring.
    * @since 1.0
    */
   public static int[] indicesOf(String source, String substring)
   {
      return indicesOf(source, substring, true);
   }
    /**
     * Returns an array that contains all the occurances of a substring in a
     * string in the correct order. The search will be performed in a
     * case-sensitive manner.
     *
     * @param source    The <code>String</code> object that will be searched in.
     * @param substring The string whose occurances will we counted.
     * @return An <code>int[]</code> array containing the indices of the
     *         substring.
     * @since 1.0
     */
    public static int[] indicesOf(String source, String substring)
    {
        return indicesOf(source, substring, true);
    }
   /**
    * Returns an array that contains all the occurances of a substring in a
    * string in the correct order.
    *
    * @param source The <code>String</code> object that will be searched in.
    * @param substring The string whose occurances will we counted.
    * @param matchCase A <code>boolean</code> indicating if the match is
    * going to be performed in a case-sensitive manner or not.
    * @return An <code>int[]</code> array containing the indices of the
    * substring.
    * @since 1.0
    */
   public static int[] indicesOf(String source, String substring, boolean matchCase)
   {
      if (null == source ||
         null == substring)
      {
         return new int[0];
      }
    /**
     * Returns an array that contains all the occurances of a substring in a
     * string in the correct order.
     *
     * @param source    The <code>String</code> object that will be searched in.
     * @param substring The string whose occurances will we counted.
     * @param matchCase A <code>boolean</code> indicating if the match is
     *                  going to be performed in a case-sensitive manner or not.
     * @return An <code>int[]</code> array containing the indices of the
     *         substring.
     * @since 1.0
     */
    public static int[] indicesOf(String source, String substring, boolean matchCase)
    {
        if (null == source ||
                null == substring)
        {
            return new int[0];
        }
      String  source_lookup_reference = null;
      if (!matchCase)
      {
         source_lookup_reference = source.toLowerCase();
         substring = substring.toLowerCase();
      }
      else
      {
         source_lookup_reference = source;
      }
        String source_lookup_reference = null;
        if (!matchCase)
        {
            source_lookup_reference = source.toLowerCase();
            substring = substring.toLowerCase();
        } else
        {
            source_lookup_reference = source;
        }
      int current_index = 0;
      int substring_index = 0;
      int count = count(source_lookup_reference, substring);
      int[] indices = new int[count];
      int counter = 0;
        int current_index = 0;
        int substring_index = 0;
        int count = count(source_lookup_reference, substring);
        int[] indices = new int[count];
        int counter = 0;
      while (current_index < source.length()-1)
      {
         substring_index = source_lookup_reference.indexOf(substring, current_index);
        while (current_index < source.length() - 1)
        {
            substring_index = source_lookup_reference.indexOf(substring, current_index);
         if (-1 == substring_index)
         {
            break;
         }
         else
         {
            current_index = substring_index + substring.length();
            indices[counter] = substring_index;
            counter++;
         }
      }
            if (-1 == substring_index)
            {
                break;
            } else
            {
                current_index = substring_index + substring.length();
                indices[counter] = substring_index;
                counter++;
            }
        }
      return indices;
   }
        return indices;
    }
   /**
    * Matches a collection of regular expressions against a string.
    *
    * @param value The <code>String</code> that will be checked.
    * @param regexps The collection of regular expressions against which the
    * match will be performed.
    * @return The <code>Matcher</code> instance that corresponds to the
    * <code>String</code> that returned a successful match; or
    * <p><code>null</code> if no match could be found.
    * @since 1.0
    */
   public static Matcher getMatchingRegexp(String value, Collection<Pattern> regexps)
   {
      if (value != null &&
         value.length() > 0 &&
         regexps != null &&
         regexps.size() > 0)
      {
         Matcher matcher = null;
         for (Pattern regexp : regexps)
         {
            matcher = regexp.matcher(value);
            if (matcher.matches())
            {
               return matcher;
            }
         }
      }
    /**
     * Matches a collection of regular expressions against a string.
     *
     * @param value   The <code>String</code> that will be checked.
     * @param regexps The collection of regular expressions against which the
     *                match will be performed.
     * @return The <code>Matcher</code> instance that corresponds to the
     *         <code>String</code> that returned a successful match; or
     *         <p><code>null</code> if no match could be found.
     * @since 1.0
     */
    public static Matcher getMatchingRegexp(String value, Collection<Pattern> regexps)
    {
        if (value != null &&
                value.length() > 0 &&
                regexps != null &&
                regexps.size() > 0)
        {
            Matcher matcher = null;
            for (Pattern regexp : regexps)
            {
                matcher = regexp.matcher(value);
                if (matcher.matches())
                {
                    return matcher;
                }
            }
        }
      return null;
   }
        return null;
    }
   /**
    * Matches a collection of strings against a regular expression.
    *
    * @param values The <code>Collection</code> of <code>String</code>
    * objects that will be checked.
    * @param regexp The regular expression <code>Pattern</code> against which
    * the matches will be performed.
    * @return The <code>Matcher</code> instance that corresponds to the
    * <code>String</code> that returned a successful match; or
    * <p><code>null</code> if no match could be found.
    * @since 1.0
    */
   public static Matcher getRegexpMatch(Collection<String> values, Pattern regexp)
   {
      if (values != null &&
         values.size() > 0 &&
         regexp != null)
      {
         Matcher matcher = null;
         for (String value : values)
         {
            matcher = regexp.matcher(value);
            if (matcher.matches())
            {
               return matcher;
            }
         }
      }
    /**
     * Matches a collection of strings against a regular expression.
     *
     * @param values The <code>Collection</code> of <code>String</code>
     *               objects that will be checked.
     * @param regexp The regular expression <code>Pattern</code> against which
     *               the matches will be performed.
     * @return The <code>Matcher</code> instance that corresponds to the
     *         <code>String</code> that returned a successful match; or
     *         <p><code>null</code> if no match could be found.
     * @since 1.0
     */
    public static Matcher getRegexpMatch(Collection<String> values, Pattern regexp)
    {
        if (values != null &&
                values.size() > 0 &&
                regexp != null)
        {
            Matcher matcher = null;
            for (String value : values)
            {
                matcher = regexp.matcher(value);
                if (matcher.matches())
                {
                    return matcher;
                }
            }
        }
      return null;
   }
        return null;
    }
   /**
    * Checks if the name filters through an including and an excluding
    * regular expression.
    *
    * @param name The <code>String</code> that will be filtered.
    * @param included The regular expressions that needs to succeed
    * @param excluded The regular expressions that needs to fail
    * @return <code>true</code> if the name filtered through correctly; or
    * <p><code>false</code> otherwise.
    * @since 1.0
    */
   public static boolean filter(String name, Pattern included, Pattern excluded)
   {
      Pattern[] included_array = null;
      if (included != null)
      {
         included_array = new Pattern[] {included};
      }
    /**
     * Checks if the name filters through an including and an excluding
     * regular expression.
     *
     * @param name     The <code>String</code> that will be filtered.
     * @param included The regular expressions that needs to succeed
     * @param excluded The regular expressions that needs to fail
     * @return <code>true</code> if the name filtered through correctly; or
     *         <p><code>false</code> otherwise.
     * @since 1.0
     */
    public static boolean filter(String name, Pattern included, Pattern excluded)
    {
        Pattern[] included_array = null;
        if (included != null)
        {
            included_array = new Pattern[]{included};
        }
      Pattern[] excluded_array = null;
      if (excluded != null)
      {
         excluded_array = new Pattern[] {excluded};
      }
        Pattern[] excluded_array = null;
        if (excluded != null)
        {
            excluded_array = new Pattern[]{excluded};
        }
      return filter(name, included_array, excluded_array);
   }
        return filter(name, included_array, excluded_array);
    }
   /**
    * Checks if the name filters through a series of including and excluding
    * regular expressions.
    *
    * @param name The <code>String</code> that will be filtered.
    * @param included An array of regular expressions that need to succeed
    * @param excluded An array of regular expressions that need to fail
    * @return <code>true</code> if the name filtered through correctly; or
    * <p><code>false</code> otherwise.
    * @since 1.0
    */
   public static boolean filter(String name, Pattern[] included, Pattern[] excluded)
   {
      if (null == name)
      {
         return false;
      }
    /**
     * Checks if the name filters through a series of including and excluding
     * regular expressions.
     *
     * @param name     The <code>String</code> that will be filtered.
     * @param included An array of regular expressions that need to succeed
     * @param excluded An array of regular expressions that need to fail
     * @return <code>true</code> if the name filtered through correctly; or
     *         <p><code>false</code> otherwise.
     * @since 1.0
     */
    public static boolean filter(String name, Pattern[] included, Pattern[] excluded)
    {
        if (null == name)
        {
            return false;
        }
      boolean accepted = false;
        boolean accepted = false;
      // retain only the includes
      if (null == included)
      {
         accepted = true;
      }
      else
      {
         for (Pattern pattern : included)
         {
            if (pattern != null &&
               pattern.matcher(name).matches())
            {
               accepted = true;
               break;
            }
         }
      }
        // retain only the includes
        if (null == included)
        {
            accepted = true;
        } else
        {
            for (Pattern pattern : included)
            {
                if (pattern != null &&
                        pattern.matcher(name).matches())
                {
                    accepted = true;
                    break;
                }
            }
        }
      // remove the excludes
      if (accepted &&
         excluded != null)
      {
         for (Pattern pattern : excluded)
         {
            if (pattern != null &&
               pattern.matcher(name).matches())
            {
               accepted = false;
               break;
            }
         }
      }
        // remove the excludes
        if (accepted &&
                excluded != null)
        {
            for (Pattern pattern : excluded)
            {
                if (pattern != null &&
                        pattern.matcher(name).matches())
                {
                    accepted = false;
                    break;
                }
            }
        }
      return accepted;
   }
        return accepted;
    }
   /**
    * Ensure that the first character of the provided string is upper case.
    *
    * @param source The <code>String</code> to capitalize.
    * @return The capitalized <code>String</code>.
    * @since 1.0
    */
   public static String capitalize(String source)
   {
      if (source == null || source.length() == 0)
      {
         return source;
      }
    /**
     * Ensure that the first character of the provided string is upper case.
     *
     * @param source The <code>String</code> to capitalize.
     * @return The capitalized <code>String</code>.
     * @since 1.0
     */
    public static String capitalize(String source)
    {
        if (source == null || source.length() == 0)
        {
            return source;
        }
      if (source.length() > 1 &&
         Character.isUpperCase(source.charAt(0)))
      {
         return source;
      }
        if (source.length() > 1 &&
                Character.isUpperCase(source.charAt(0)))
        {
            return source;
        }
      char chars[] = source.toCharArray();
      chars[0] = Character.toUpperCase(chars[0]);
      return new String(chars);
   }
        char chars[] = source.toCharArray();
        chars[0] = Character.toUpperCase(chars[0]);
        return new String(chars);
    }
   /**
    * Ensure that the first character of the provided string lower case.
    *
    * @param source The <code>String</code> to uncapitalize.
    * @return The uncapitalized <code>String</code>.
    * @since 1.5
    */
   public static String uncapitalize(String source)
   {
      if (source == null || source.length() == 0)
      {
         return source;
      }
    /**
     * Ensure that the first character of the provided string lower case.
     *
     * @param source The <code>String</code> to uncapitalize.
     * @return The uncapitalized <code>String</code>.
     * @since 1.5
     */
    public static String uncapitalize(String source)
    {
        if (source == null || source.length() == 0)
        {
            return source;
        }
      if (source.length() > 1 &&
         Character.isLowerCase(source.charAt(0)))
      {
         return source;
      }
        if (source.length() > 1 &&
                Character.isLowerCase(source.charAt(0)))
        {
            return source;
        }
      char chars[] = source.toCharArray();
      chars[0] = Character.toLowerCase(chars[0]);
      return new String(chars);
   }
        char chars[] = source.toCharArray();
        chars[0] = Character.toLowerCase(chars[0]);
        return new String(chars);
    }
   private static String convertUrl(String source, Pattern pattern, boolean shorten, boolean sanitize, boolean no_follow)
   {
      int max_length = 1024;
    private static String convertUrl(String source, Pattern pattern, boolean shorten, boolean sanitize, boolean no_follow)
    {
        int max_length = 1024;
      String result = source;
        String result = source;
      Matcher url_matcher = pattern.matcher(source);
      boolean found = url_matcher.find();
      if (found)
      {
         String visual_url = null;
         String actual_url = null;
         int last = 0;
         StringBuilder sb = new StringBuilder();
         do
         {
            actual_url = url_matcher.group(1);
            if (url_matcher.groupCount() > 1)
            {
               visual_url = url_matcher.group(2);
            }
            else
            {
               visual_url = actual_url;
            }
        Matcher url_matcher = pattern.matcher(source);
        boolean found = url_matcher.find();
        if (found)
        {
            String visual_url = null;
            String actual_url = null;
            int last = 0;
            StringBuilder sb = new StringBuilder();
            do
            {
                actual_url = url_matcher.group(1);
                if (url_matcher.groupCount() > 1)
                {
                    visual_url = url_matcher.group(2);
                } else
                {
                    visual_url = actual_url;
                }
            if (sanitize)
            {
               // defang javascript
               actual_url = StringUtils.replace(actual_url, "javascript:", "");
                if (sanitize)
                {
                    // defang javascript
                    actual_url = StringUtils.replace(actual_url, "javascript:", "");
               // fill in http:// for URLs that don't begin with /
               if ((actual_url.indexOf("://") == -1) &&
                  (!actual_url.startsWith("/")))
               {
                  actual_url = "http://"+actual_url;
               }
            }
                    // fill in http:// for URLs that don't begin with /
                    if ((actual_url.indexOf("://") == -1) &&
                            (!actual_url.startsWith("/")))
                    {
                        actual_url = "http://" + actual_url;
                    }
                }
            if (pattern.equals(BBCODE_BAREURL))
            {
               sb.append(source.substring(last, url_matcher.start(1)));
            }
            else
            {
               sb.append(source.substring(last, url_matcher.start(0)));
            }
            sb.append("<a href=\"");
            sb.append(actual_url);
            sb.append("\"");
            if (actual_url.startsWith("http://") ||
               actual_url.startsWith("https://"))
            {
               sb.append(" target=\"_blank\"");
            }
            if (no_follow)
            {
               sb.append(" rel=\"nofollow\"");
            }
            sb.append(">");
            if (visual_url.length() <= max_length || !shorten)
            {
               sb.append(visual_url);
            }
            else
            {
               String ellipsis = "...";
               int query_index = visual_url.indexOf("?");
                if (pattern.equals(BBCODE_BAREURL))
                {
                    sb.append(source.substring(last, url_matcher.start(1)));
                } else
                {
                    sb.append(source.substring(last, url_matcher.start(0)));
                }
                sb.append("<a href=\"");
                sb.append(actual_url);
                sb.append("\"");
                if (actual_url.startsWith("http://") ||
                        actual_url.startsWith("https://"))
                {
                    sb.append(" target=\"_blank\"");
                }
                if (no_follow)
                {
                    sb.append(" rel=\"nofollow\"");
                }
                sb.append(">");
                if (visual_url.length() <= max_length || !shorten)
                {
                    sb.append(visual_url);
                } else
                {
                    String ellipsis = "...";
                    int query_index = visual_url.indexOf("?");
               // hack query string off
               // keep '?'
               if (query_index != -1)
               {
                  visual_url = visual_url.substring(0, query_index + 1) + ellipsis;
               }
                    // hack query string off
                    // keep '?'
                    if (query_index != -1)
                    {
                        visual_url = visual_url.substring(0, query_index + 1) + ellipsis;
                    }
               if (visual_url.length() >= max_length)
               {
                  int last_slash = visual_url.lastIndexOf("/");
                  int start_slash = visual_url.indexOf("/", visual_url.indexOf("://")+3);
                    if (visual_url.length() >= max_length)
                    {
                        int last_slash = visual_url.lastIndexOf("/");
                        int start_slash = visual_url.indexOf("/", visual_url.indexOf("://") + 3);
                  if (last_slash != start_slash)
                  {
                     visual_url = visual_url.substring(0, start_slash + 1) + ellipsis + visual_url.substring(last_slash);
                  }
               }
                        if (last_slash != start_slash)
                        {
                            visual_url = visual_url.substring(0, start_slash + 1) + ellipsis + visual_url.substring(last_slash);
                        }
                    }
               sb.append(visual_url);
            }
            sb.append("</a>");
                    sb.append(visual_url);
                }
                sb.append("</a>");
            if (pattern.equals(BBCODE_BAREURL))
            {
               last = url_matcher.end(1);
            }
            else
            {
               last = url_matcher.end(0);
            }
                if (pattern.equals(BBCODE_BAREURL))
                {
                    last = url_matcher.end(1);
                } else
                {
                    last = url_matcher.end(0);
                }
            found = url_matcher.find();
         }
         while (found);
                found = url_matcher.find();
            }
            while (found);
         sb.append(source.substring(last));
         result = sb.toString();
      }
            sb.append(source.substring(last));
            result = sb.toString();
        }
      return result;
   }
        return result;
    }
   private static String parseBBCode(String source, boolean shorten, boolean sanitize, boolean convert_bare, boolean no_follow)
   {
      String result = source;
    private static String parseBBCode(String source, boolean shorten, boolean sanitize, boolean convert_bare, boolean no_follow)
    {
        String result = source;
      result = StringUtils.replace(result, "[b]", "<b>", false);
      result = StringUtils.replace(result, "[/b]", "</b>", false);
      result = StringUtils.replace(result, "[u]", "<u>", false);
      result = StringUtils.replace(result, "[/u]", "</u>", false);
      result = StringUtils.replace(result, "[i]", "<i>", false);
      result = StringUtils.replace(result, "[/i]", "</i>", false);
      result = StringUtils.replace(result, "[pre]", "<pre>", false);
      result = StringUtils.replace(result, "[/pre]", "</pre>", false);
        result = StringUtils.replace(result, "[b]", "<b>", false);
        result = StringUtils.replace(result, "[/b]", "</b>", false);
        result = StringUtils.replace(result, "[u]", "<u>", false);
        result = StringUtils.replace(result, "[/u]", "</u>", false);
        result = StringUtils.replace(result, "[i]", "<i>", false);
        result = StringUtils.replace(result, "[/i]", "</i>", false);
        result = StringUtils.replace(result, "[pre]", "<pre>", false);
        result = StringUtils.replace(result, "[/pre]", "</pre>", false);
      String         resultCopy = result;
      String         resultLowerCopy = result.toLowerCase();
      StringBuilder   buffer = new StringBuilder();
      int startIndex;
      int endIndex;
      while (-1 != (startIndex = resultLowerCopy.indexOf("[*]")))
      {
         int begin = resultLowerCopy.indexOf("[list]", startIndex + 3);
         int end = resultLowerCopy.indexOf("[/list]", startIndex + 3);
         int next = resultLowerCopy.indexOf("[*]", startIndex + 3); // 3 == sizeof [*]
        String resultCopy = result;
        String resultLowerCopy = result.toLowerCase();
        StringBuilder buffer = new StringBuilder();
        int startIndex;
        int endIndex;
        while (-1 != (startIndex = resultLowerCopy.indexOf("[*]")))
        {
            int begin = resultLowerCopy.indexOf("[list]", startIndex + 3);
            int end = resultLowerCopy.indexOf("[/list]", startIndex + 3);
            int next = resultLowerCopy.indexOf("[*]", startIndex + 3); // 3 == sizeof [*]
         if (begin == -1)
         {
            begin = Integer.MAX_VALUE;
         }
            if (begin == -1)
            {
                begin = Integer.MAX_VALUE;
            }
         if (end == -1)
         {
            end = Integer.MAX_VALUE;
         }
            if (end == -1)
            {
                end = Integer.MAX_VALUE;
            }
         if (next == -1)
         {
            next = Integer.MAX_VALUE;
         }
            if (next == -1)
            {
                next = Integer.MAX_VALUE;
            }
         if (next < begin && next < end)
         {
            endIndex = next;
         }
         else if (begin < next && begin < end)
         {
            endIndex = begin;
         }
         else if (end < next && end < begin)
         {
            endIndex = end;
         }
         else
         {
            endIndex = resultLowerCopy.length();
         }
            if (next < begin && next < end)
            {
                endIndex = next;
            } else if (begin < next && begin < end)
            {
                endIndex = begin;
            } else if (end < next && end < begin)
            {
                endIndex = end;
            } else
            {
                endIndex = resultLowerCopy.length();
            }
         buffer
            .append(resultCopy.substring(0, startIndex))
            .append("<li>")
            .append(resultCopy.substring(startIndex + 3, endIndex)) // 3 == sizeof [*]
            .append("</li>");
            buffer
                    .append(resultCopy.substring(0, startIndex))
                    .append("<li>")
                    .append(resultCopy.substring(startIndex + 3, endIndex)) // 3 == sizeof [*]
                    .append("</li>");
         resultCopy = resultCopy.substring(endIndex);
         resultLowerCopy = resultLowerCopy.substring(endIndex);
      }
      buffer.append(resultCopy.substring(0));
            resultCopy = resultCopy.substring(endIndex);
            resultLowerCopy = resultLowerCopy.substring(endIndex);
        }
        buffer.append(resultCopy.substring(0));
      result = buffer.toString();
        result = buffer.toString();
      result = StringUtils.replace(result, "[list]", "<ul>", false);
      result = StringUtils.replace(result, "[/list]", "</ul>", false);
        result = StringUtils.replace(result, "[list]", "<ul>", false);
        result = StringUtils.replace(result, "[/list]", "</ul>", false);
      Matcher color_matcher = BBCODE_COLOR.matcher(result);
      result = color_matcher.replaceAll("<font color=\"$1\">");
      result = StringUtils.replace(result, "[/color]", "</font>", false);
        Matcher color_matcher = BBCODE_COLOR.matcher(result);
        result = color_matcher.replaceAll("<font color=\"$1\">");
        result = StringUtils.replace(result, "[/color]", "</font>", false);
      Matcher size_matcher = BBCODE_SIZE.matcher(result);
      result = size_matcher.replaceAll("<font size=\"$1\">");
      result = StringUtils.replace(result, "[/size]", "</font>", false);
        Matcher size_matcher = BBCODE_SIZE.matcher(result);
        result = size_matcher.replaceAll("<font size=\"$1\">");
        result = StringUtils.replace(result, "[/size]", "</font>", false);
      result = convertUrl(result, BBCODE_URL_SHORT, shorten, sanitize, no_follow);
      result = convertUrl(result, BBCODE_URL_LONG, shorten, sanitize, no_follow);
        result = convertUrl(result, BBCODE_URL_SHORT, shorten, sanitize, no_follow);
        result = convertUrl(result, BBCODE_URL_LONG, shorten, sanitize, no_follow);
      if (convert_bare)
      {
         result = convertUrl(result, BBCODE_BAREURL, shorten, sanitize, no_follow);
      }
        if (convert_bare)
        {
            result = convertUrl(result, BBCODE_BAREURL, shorten, sanitize, no_follow);
        }
      Matcher img_matcher = BBCODE_IMG.matcher(result);
      result = img_matcher.replaceAll("<div class=\"bbcode_img\"><img src=\"$1\" border=\"0\" alt=\"\" /></div>");
        Matcher img_matcher = BBCODE_IMG.matcher(result);
        result = img_matcher.replaceAll("<div class=\"bbcode_img\"><img src=\"$1\" border=\"0\" alt=\"\" /></div>");
      Matcher quote_matcher_long = BBCODE_QUOTE_LONG.matcher(result);
      result = quote_matcher_long.replaceAll("<div class=\"quoteaccount\">$1:</div><div class=\"quotebody\">");
      result = StringUtils.replace(result, "[quote]", "<div class=\"quotebody\">", false);
      result = StringUtils.replace(result, "[/quote]", "</div>", false);
        Matcher quote_matcher_long = BBCODE_QUOTE_LONG.matcher(result);
        result = quote_matcher_long.replaceAll("<div class=\"quoteaccount\">$1:</div><div class=\"quotebody\">");
        result = StringUtils.replace(result, "[quote]", "<div class=\"quotebody\">", false);
        result = StringUtils.replace(result, "[/quote]", "</div>", false);
      result = StringUtils.replace(result, "\r\n", "<br />\r");
      result = StringUtils.replace(result, "\n", "<br />\n");
      result = StringUtils.replace(result, "\r", "\r\n");
        result = StringUtils.replace(result, "\r\n", "<br />\r");
        result = StringUtils.replace(result, "\n", "<br />\n");
        result = StringUtils.replace(result, "\r", "\r\n");
      // remove the BR that could be added due to code formatting ppl
      // use to format lists
      result = StringUtils.replace(result, "ul><br />\r\n", "ul>\r\n");
      result = StringUtils.replace(result, "ul><br />\n", "ul>\n");
        // remove the BR that could be added due to code formatting ppl
        // use to format lists
        result = StringUtils.replace(result, "ul><br />\r\n", "ul>\r\n");
        result = StringUtils.replace(result, "ul><br />\n", "ul>\n");
      return result;
   }
        return result;
    }
   /**
    * Converts a <code>String</code> to a <code>boolean</code> value.
    *
    * @param value The <code>String</code> to convert.
    * @return The corresponding <code>boolean</code> value.
    * @since 1.0
    */
   public static boolean convertToBoolean(String value)
   {
      if (null == value)
      {
         return false;
      }
    /**
     * Converts a <code>String</code> to a <code>boolean</code> value.
     *
     * @param value The <code>String</code> to convert.
     * @return The corresponding <code>boolean</code> value.
     * @since 1.0
     */
    public static boolean convertToBoolean(String value)
    {
        if (null == value)
        {
            return false;
        }
      if (value.equals("1") ||
         value.equalsIgnoreCase("t") ||
         value.equalsIgnoreCase("true") ||
         value.equalsIgnoreCase("y") ||
         value.equalsIgnoreCase("yes") ||
         value.equalsIgnoreCase("on"))
      {
         return true;
      }
        if (value.equals("1") ||
                value.equalsIgnoreCase("t") ||
                value.equalsIgnoreCase("true") ||
                value.equalsIgnoreCase("y") ||
                value.equalsIgnoreCase("yes") ||
                value.equalsIgnoreCase("on"))
        {
            return true;
        }
      return false;
   }
        return false;
    }
   /**
    * Converts all tabs on a line to spaces according to the provided tab
    * width.
    *
    * @param line The line whose tabs have to be converted.
    * @param tabWidth The tab width.
    * @return A new <code>String</code> object containing the line with the
    * replaced tabs.
    * @since 1.0
    */
   public static String convertTabsToSpaces(String line, int tabWidth)
   {
      StringBuilder result = new StringBuilder();
      int tab_index = -1;
      int last_tab_index = 0;
      int added_chars = 0;
      int tab_size;
      while ((tab_index = line.indexOf("\t", last_tab_index)) != -1)
      {
         tab_size = tabWidth-((tab_index+added_chars)%tabWidth);
         if (0 == tab_size)
         {
            tab_size = tabWidth;
         }
         added_chars += tab_size-1;
         result.append(line.substring(last_tab_index, tab_index));
         result.append(StringUtils.repeat(" ", tab_size));
         last_tab_index = tab_index+1;
      }
      if (0 == last_tab_index)
      {
         return line;
      }
      else
      {
         result.append(line.substring(last_tab_index));
      }
    /**
     * Converts all tabs on a line to spaces according to the provided tab
     * width.
     *
     * @param line     The line whose tabs have to be converted.
     * @param tabWidth The tab width.
     * @return A new <code>String</code> object containing the line with the
     *         replaced tabs.
     * @since 1.0
     */
    public static String convertTabsToSpaces(String line, int tabWidth)
    {
        StringBuilder result = new StringBuilder();
        int tab_index = -1;
        int last_tab_index = 0;
        int added_chars = 0;
        int tab_size;
        while ((tab_index = line.indexOf("\t", last_tab_index)) != -1)
        {
            tab_size = tabWidth - ((tab_index + added_chars) % tabWidth);
            if (0 == tab_size)
            {
                tab_size = tabWidth;
            }
            added_chars += tab_size - 1;
            result.append(line.substring(last_tab_index, tab_index));
            result.append(StringUtils.repeat(" ", tab_size));
            last_tab_index = tab_index + 1;
        }
        if (0 == last_tab_index)
        {
            return line;
        } else
        {
            result.append(line.substring(last_tab_index));
        }
      return result.toString();
   }
        return result.toString();
    }
   /**
    * Ensures that all whitespace is removed from a <code>String</code>.
    * <p>It also works with a <code>null</code> argument.
    *
    * @param source The <code>String</code> to trim.
    * @return The trimmed <code>String</code>.
    * @since 1.0
    */
   public static String trim(String source)
   {
      if (source == null || source.length() == 0)
      {
         return source;
      }
    /**
     * Ensures that all whitespace is removed from a <code>String</code>.
     * <p>It also works with a <code>null</code> argument.
     *
     * @param source The <code>String</code> to trim.
     * @return The trimmed <code>String</code>.
     * @since 1.0
     */
    public static String trim(String source)
    {
        if (source == null || source.length() == 0)
        {
            return source;
        }
      return source.trim();
   }
        return source.trim();
    }
    /**
     * Reformats a string where lines that are longer than <tt>width</tt>
     * are split apart at the earliest wordbreak or at maxLength, whichever is
     * sooner. If the width specified is less than 5 or greater than the input
     * Strings length the string will be returned as is.
     * <p>
     * <p/>
     * Please note that this method can be lossy - trailing spaces on wrapped
     * lines may be trimmed.
     *
@@ -2814,12 +2778,10 @@
        if (input == null)
        {
            return "";
        }
        else if (width < 5)
        } else if (width < 5)
        {
            return input;
        }
        else if (width >= input.length())
        } else if (width >= input.length())
        {
            return input;
        }
@@ -2831,18 +2793,18 @@
        }
        StringBuilder buffer = new StringBuilder(input.length());
      int      current_index = 0;
      int      delimiter_index = 0;
      String   seperator = "\n";
      String   line;
        int current_index = 0;
        int delimiter_index = 0;
        String seperator = "\n";
        String line;
      // go over the input string and jump from line to line
      while (current_index <= input.length())
      {
         // look for the next linebreak
         delimiter_index = input.indexOf(seperator, current_index);
        // go over the input string and jump from line to line
        while (current_index <= input.length())
        {
            // look for the next linebreak
            delimiter_index = input.indexOf(seperator, current_index);
         // get the line that corresponds to it
            // get the line that corresponds to it
         if (-1 == delimiter_index)
         {
            line = new String(input.substring(current_index, input.length()));