/*
 * $Id: VKCStringUtils.java,v 1.37 2007/08/08 12:14:49 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: VKCStringUtils.java,v $
 * Revision 1.37  2007/08/08 12:14:49  marbobo
 * + License-Funktionalität komplett umgeschrieben
 * + Bugfix bzgl. Beschreibungsfelder von Entitäten
 * + Bugfix mailing
 *
 * Revision 1.36  2006/10/23 12:12:58  marbobo
 * + Bugfix
 *
 * Revision 1.35  2006/09/20 01:17:34  marbobo
 * + In der Javascript-Filtermethode werden nun auch speziele Zeichen gefiltert
 *
 * Revision 1.34  2006/05/31 14:01:18  marbobo
 * + decodeNewLine() und encodeNewLine() hinzugefügt
 *
 * Revision 1.33  2006/05/24 18:02:03  marbobo
 * + decodeNamedXmlEntitiesNotInSwing() und encodeNamedXmlEntities() huinzugefügt
 * + bugfix
 *
 * Revision 1.32  2006/05/14 17:28:58  marbobo
 * + removeHtmlTags() auf JEditorPane-Basis umgestellt
 *
 * Revision 1.31  2006/05/10 20:12:35  marbobo
 * + removeHtmlTags() hinzugefügt
 *
 * Revision 1.30  2006/05/09 15:25:37  marbobo
 * + decodeNamedXmlEntities() und htmlFormatedText() hinzugefügt
 *
 * Revision 1.29  2006/04/29 18:38:35  marbobo
 * + base64Encode/Decode-Methoden zur Behandlung von Parametern hinzugefügt
 *
 * Revision 1.28  2006/03/09 01:28:43  marbobo
 * + filterJavascriptChars() hinzugefügt
 *
 * Revision 1.27  2006/02/27 16:15:55  marbobo
 * + Systemsichten hinzugefügt
 * + SysLinks angepasst
 * + Benutzer können falls gewünscht Dokumentqueries anlegen
 *
 * Revision 1.26  2006/01/20 14:13:07  korowa
 * *** empty log message ***
 *
 * Revision 1.25  2005/07/29 19:55:53  marbobo
 * + NPE Abgefangen
 *
 * Revision 1.24  2005/07/16 23:58:17  marbobo
 * + decodeXmlEntities() für StringArrays hinzugefügt
 *
 * Revision 1.23  2005/03/24 12:56:22  marbobo
 * + Größenanzeige für Dokumente und Kategorien auf 2 Dezimalstellen eingestellt
 *
 * Revision 1.22  2005/03/23 19:45:34  marbobo
 * + Lokalisierung der Größenanzeige
 *
 * Revision 1.21  2005/03/21 20:26:04  marbobo
 * + DocSize auf Type Long umgestellt
 *
 * Revision 1.20  2005/02/10 13:45:09  marbobo
 * + Kodierung aller Zeichen größer 255 in der filterUnicodeChars()
 *
 * Revision 1.19  2005/02/10 01:11:04  marbobo
 * + Bugfixes
 *
 * Revision 1.18  2005/02/09 14:06:28  lawern
 * Daniels Version der decodeXmlEntities korrigiert und eingefügt.
 *
 * Revision 1.17  2005/02/09 11:46:02  lawern
 * decodeXmlEntities wieder auf die alte Version umgestellt
 *
 * Revision 1.16  2005/02/08 23:16:36  marbobo
 * + encodeXmlEntities()
 *
 * Revision 1.15  2005/02/08 15:28:12  lawern
 * decodeXmlEntities eingefügt
 *
 * Revision 1.14  2005/02/03 23:28:09  marbobo
 * + convertNewLineInHTML()
 *
 * Revision 1.13  2005/02/03 14:41:09  marbobo
 * + Filtern der CP1252-Zeichen
 *
 * Revision 1.12  2005/02/02 22:58:55  marbobo
 * + filterUnicodeChars()
 *
 * Revision 1.11  2004/11/10 15:02:46  koppy
 * Projektweite Überarbeitung von Error-Logs, Stacktraces,..
 *
 * Revision 1.10  2004/06/24 23:33:32  marbobo
 * Quellcode maintenance
 *
 * Revision 1.9  2004/03/13 19:15:10  marbobo
 * Unbenutze lokale Variablen projektweit entsorgt
 *
 * Revision 1.8  2003/12/24 10:11:58  bigmac
 * Projektweite Import-Optimierung
 *
 * Revision 1.7  2003/07/31 13:59:29  bigmac
 * Compilerwarnungen beseitigt
 *
 * Revision 1.6  2003/07/09 13:57:48  koppy
 * bugfix in formatBytes(..)
 *
 * Revision 1.5  2003/07/09 12:42:17  koppy
 * + formatBytes
 *
 * Revision 1.4  2003/06/06 23:16:49  koppy
 * + filterHTMLChars( value:String ): String
 *
 * Revision 1.3  2003/05/13 09:17:38  koppy
 * *** empty log message ***
 *
 * Revision 1.2  2003/04/14 13:25:03  koppy
 * +getEncodedString()
 *
 * Revision 1.1  2002/10/21 14:36:27  bigmac
 * *** empty log message ***
 *
 * Revision 1.2  2002/05/14 13:49:21  moelle
 * *** empty log message ***
 *
 * Revision 1.1.1.1  2002/04/02 10:55:46  lawern
 * initiale Version
 *
 * Revision 1.4  2002/02/14 19:05:07  koppy
 * stringToVector() und vectorToString() mit optionalem Trennzeichen
 *
 * Revision 1.3  2002/01/07 17:24:03  koppy
 * + normalizeFilePath()
 *
 * Revision 1.2  2001/12/14 15:17:42  koppy
 * + normalizeURL()
 *
 */
package vkc.util;

import vkc.db.entities.VKCLanguage;
import vkc.db.serializer.VKCLanguageSerializer;
import vkc.misc.VKCLogManager;

import java.io.File;
import java.io.UnsupportedEncodingException;

import java.text.DecimalFormat;
import java.text.NumberFormat;

import java.util.ArrayList;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JEditorPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;

/**
 * Die Klasse stellt Methoden bereits, die das Arbeiten (und Leben)
 * mit Strings in VKC erleichtern soll
 * <p>
 * @author bigmac
 */
public final class VKCStringUtils {
	public static final long oneKB = 1024;
	public static final long oneMB = oneKB * oneKB;
	public static final long oneGB = oneKB * oneMB;
	public static final long oneTB = oneKB * oneGB;
	public static final long onePB = oneKB * oneTB;
	public static final long oneEB = oneKB * onePB;

	public static boolean debug = false;

    /**
     * Ersetzt alle Zeichenfolgen "token" in "str" durch "value"
     * <p>
     * @author  bigmac
     * @param   str         die Zeichenkette
     * @param   token          die zu ersetzende Zeichenfolge
     * @param   value   die neue Zeichenfolge
     * @return  die modifizierte Zeichenkette
     */
    public static String replaceVar(String str, String token, String value) {
        if (str == null) {
            return "";
        }

        if (token == null || token.length() == 0) {
            return str;
        }

        if (str.indexOf(token) < 0) {
            return str;
        }

        if (value == null || value.length() == 0) {
            return "";
        }

        int index = -1;
        int tokenLength = token.length();
        boolean found = false;

        try {
            while (true) {
                index = str.indexOf(token);

                //kein token mehr
                if (index < 0) {
                    if (found) {
                        return str;
                    }

                    return ("");
                }

                found = true;

                String head = str.substring(0, index);
                String tail = str.substring(index + tokenLength, str.length());
                str = head + value + tail;
            }
        } catch (Exception e) {
            VKCLogManager.errorLog(VKCStringUtils.class, "", e.getMessage(), e);

            return "";
        }
    }

    /**
     * Ersetzt in tmp eine Variable var durch Ihren Wert value, wenn dieser
     * ungleich "" ist.
     * <p>
     */
    public static String replaceWeb(String tmp, String var, String value) {
        if (value == null) {
            value = "";
        }

        if (value.startsWith("\"") && value.endsWith("\"")) { // falls in Gänsefuesschen, diese entfernen
            value = value.substring(1, value.length() - 1);
        }

        if (value.length() < 0) {
            return tmp;
        }

        int pos = tmp.indexOf(var);

        //jarjar! Auch gleich null!
        while (pos >= 0) {
            String tail = tmp.substring(pos + var.length());
            tmp = tmp.substring(0, pos) + value + tail;
            pos = tmp.indexOf(var);
        }

        return tmp;
    }

    /**
     * Ersetzt in einer Zeichenkette eine Zeichenfolge durch eine andere.
     * <p>
     * @param   text - die Zeichenkette
     * @param   repl - die zu ersetzende Zeichenfolge
     * @param   with - die neue Zeichenfolge
     * @return  die modifizierte Zeichenkette
     */
    public static String replace(String text, String repl, String with) {
        if (text == null || repl == null || with == null || repl.length() == 0) {
            return text;
        }

        StringBuffer buf = new StringBuffer(text.length());
        int start = 0, end = 0;
        
        while ((end = text.indexOf(repl, start)) != -1) {
            buf.append(text.substring(start, end)).append(with);
            start = end + repl.length();
        }

        buf.append(text.substring(start));
        
        return buf.toString();
    }

    /** Ersetzt $$ in einem String durch $ */
    public static String replaceDubbleDollar(String tmp) {
        int ddi = tmp.indexOf("$$");

        if (ddi >= 0) {
            while (ddi >= 0) {
                tmp = replace(tmp, "$$", "$");
                ddi = tmp.indexOf("$$");
            }
        }

        return tmp;
    }

    /**
     * Gibt true zurueck, wenn im uebergebenen String kein
     * einzeln vorkommendes $ mehr enthalten ist.
     */
    public static boolean replaced(String tmp) {
        int sdi = tmp.indexOf("$");
        int ddi = tmp.indexOf("$$");

        if (sdi >= 0) {
            while (ddi == sdi && ((sdi + 2) < tmp.length())) {
                tmp = tmp.substring(sdi + 2, tmp.length());
                sdi = tmp.indexOf("$");
                ddi = tmp.indexOf("$$");
            }

            return ddi == sdi;
        }

        return true;
    }

    /**
     * Ersetzt alle Zeichenfolgen "token" in "str" durch "value"
     * <p>
     * @author  bigmac
     * @param   str         die Zeichenkette
     * @param   token          die zu ersetzende Zeichenfolge
     * @param   value   die neue Zeichenfolge
     * @return             die modifizierte Zeichenkette
     */
    public static String replaceToken(String str, String token, String value) {
        if (str == null) {
            return null;
        }

        try {
            int index = -1;
            int tokenLength = token.length();

            while (true) {
                index = str.indexOf(token);

                if (index < 0) {
                    return str; // kein token mehr
                }

                String head = str.substring(0, index);
                String tail = str.substring(index + tokenLength, str.length());
                str = head + value + tail;
            }
        } catch (Exception e) {
            if (debug) {
                VKCLogManager.errorLog(VKCStringUtils.class, "", e.getMessage(), e);
            }

            return null;
        }
    }

    // ####################################################################
    // Method: getBytes()
    // ErrorCode: 2045
    // ####################################################################
    public static byte[] getBytes(String s) {
        //like String.getBytes, but uniform to all OS'
        byte[] b = new byte[s.length()];
        char[] c = new char[s.length()];
        c = s.toCharArray();

        for (int i = 0; i < s.length(); i++) {
            b[i] = (byte) ((c[i] >>> 8) | (c[i] & 0xff));
        }

        return b;
    }

    /**
     * Filter the specified string for characters that are senstive to
     * HTML interpreters, returning the string with these characters replaced
     * by the corresponding character entities.
     *
     * @param value The string to be filtered and returned
     */
    public static final String filterHTMLChars(String value) {
        if (value == null) {
            return null;
        }

        char[] content = new char[value.length()];
        value.getChars(0, value.length(), content, 0);

        StringBuffer result = new StringBuffer(content.length + 50);

        for (int i = 0; i < content.length; i++) {
            switch (content[i]) {
	            case '<':
	                result.append("&lt;");
	                break;
	            case '>':
	                result.append("&gt;");
	                break;
	            case '&':
	                if (((i + 4) < content.length) && (value.substring(i, i + 5).equals("&amp;"))) {
	                    result.append(content[i]);
	                } else {
	                    result.append("&amp;");
	                }
	
	                break;
	            case '"':
	                result.append("&quot;");
	                break;
	            case '\'':
	                result.append("&#39;");
	                break;
	            case '\n':
	                result.append("<br/>");
	                break;
	            default:
	                result.append(content[i]);
            }
        }

        return result.toString();
    }

    public static final String filterUnicodeChars(String value) {
        if (value == null) {
            return null;
        }

        value = replace(value, "&", "&#38;");
        StringBuffer newInput = new StringBuffer();

        Pattern p = Pattern.compile("&#38;#(\\d)+;");
        Matcher m = p.matcher(value);

        try {
            while (m.find()) {
                String property = m.group();
                property = "&" + property.substring(5, property.length());
                m.appendReplacement(newInput, property);
            }
        } catch (Exception e) {
            return value;
        }

        m.appendTail(newInput);

        String newValue = newInput.toString();
        char[] content = new char[newValue.length()];
        newValue.getChars(0, newValue.length(), content, 0);

        StringBuffer result = new StringBuffer(content.length + 50);

        for (int i = 0; i < content.length; i++) {
            int c = content[i];

            switch (c) {
	            case 60:
	                result.append("&#60;");
	                break;
	            case 62:
	                result.append("&#62;");
	                break;
	            case 34:
	                result.append("&#34;");
	                break;
	            case 39:
	                result.append("&#39;");
	                break;
	            case 128:
	                result.append("&#8364;");
	                break;
	            case 130:
	                result.append("&#8218;");
	                break;
	            case 131:
	                result.append("&#402;");
	                break;
	            case 132:
	                result.append("&#8222;");
	                break;
	            case 133:
	                result.append("&#8230;");
	                break;
	            case 134:
	                result.append("&#8224;");
	                break;
	            case 135:
	                result.append("&#8225;");
	                break;
	            case 136:
	                result.append("&#710;");
	                break;
	            case 137:
	                result.append("&#8240;");
	                break;
	            case 138:
	                result.append("&#352;");
	                break;
	            case 139:
	                result.append("&#8249;");
	                break;
	            case 140:
	                result.append("&#338;");
	                break;
	            case 142:
	                result.append("&#381;");
	                break;
	            case 145:
	                result.append("&#8216;");
	                break;
	            case 146:
	                result.append("&#8217;");
	                break;
	            case 147:
	                result.append("&#8220;");
	                break;
	            case 148:
	                result.append("&#8221;");
	                break;
	            case 149:
	                result.append("&#8226;");
	                break;
	            case 150:
	                result.append("&#8211;");
	                break;
	            case 151:
	                result.append("&#8212;");
	                break;
	            case 152:
	                result.append("&#732;");
	                break;
	            case 153:
	                result.append("&#8482;");
	                break;
	            case 154:
	                result.append("&#353;");
	                break;
	            case 155:
	                result.append("&#8250;");
	                break;
	            case 156:
	                result.append("&#339;");
	                break;
	            case 158:
	                result.append("&#382;");
	                break;
	            case 159:
	                result.append("&#376;");
	                break;
	            default:
	                if (c > 255) {
	                    result.append("&#" + c + ";");
	                } else {
	                    result.append(content[i]);
	                }
            }
        }

        return result.toString();
    }

    public static final String[] filterUnicodeChars(String[] values) {
        if (values == null) {
            return null;
        }
        
        String[] newValues = new String[values.length];
        
        for (int i = 0; i < newValues.length; i++) {
            newValues[i] = filterUnicodeChars(values[i]);
        }
        
        return newValues;
    }

    public static final String filterJavascriptChars(String value) {
        if (value == null) {
            return null;
        }

        String specialChars = "!@#$%^&*()+=-[];,./{}|\"':<>?";
        char[] content = new char[value.length()];
        value.getChars(0, value.length(), content, 0);

        StringBuffer result = new StringBuffer(content.length + 50);
        
        for (int i = 0; i < content.length; i++) {
            int c = content[i];

            switch (c) {
	            default:
	                if (c > 255 || specialChars.indexOf(c) != -1) {
	                	String h = Integer.toHexString(c);
	                	
	                	switch (h.length()) {
	                		case 1: 
	                			h = "000" + h;
	                			break;
	                		case 2: 
	                			h = "00" + h;
	                			break;
	                		case 3: 
	                			h = "0" + h;
	                			break;
	                	}
	                	
	                    result.append("\\u" + h);
	                } else {
	                    result.append(content[i]);
	                }
            }
        }

        return result.toString();
    }

    /**
     * Dekodiert nur Named-XML-Entities die in Swing nicht vorkommen (z.B. &amp;euro;) 
     * wieder in einen Java-String.
     * 
     * @param value String mit XML-Entities
     * @return dekodierter String
     */
    public static final String decodeNamedXmlEntitiesNotInSwing(String value) {
        if (value == null) {
            return null;
        }
        
        StringBuffer newInput = new StringBuffer(value.length());
        
        Pattern p = Pattern.compile("&([a-zA-Z0-9]){3,12};");
        Matcher m = p.matcher(value);

        try {
            while (m.find()) {
                String entity = m.group();
                String c = VKCHtmlEntities2Unicode.getUnicodeCharForSwing(entity);

                if (c != null) {
                    m.appendReplacement(newInput, c);
                }
            }
        } catch (Exception e) {
            return value;
        }

        m.appendTail(newInput);

        return newInput.toString();
    }

    /**
     * Dekodiert einen String mit Named-XML-Entities (z.B. &amp;euro;) wieder in einen Java-String.
     * @param value String mit XML-Entities
     * @return dekodierter String
     */
    public static final String decodeNamedXmlEntities(String value) {
        if (value == null) {
            return null;
        }
        
        StringBuffer newInput = new StringBuffer(value.length());
        
        Pattern p = Pattern.compile("&([a-zA-Z0-9]){3,12};");
        Matcher m = p.matcher(value);

        try {
            while (m.find()) {
                String entity = m.group();
                String c = VKCHtmlEntities2Unicode.getUnicodeChar(entity);

                if (c != null) {
                    m.appendReplacement(newInput, c);
                }
            }
        } catch (Exception e) {
            return value;
        }

        m.appendTail(newInput);

        return newInput.toString();
    }

    /**
     * Dekodiert einen String mit XML-Entities (z.B. &#8364;) wieder in einen Java-String.
     * @param value String mit XML-Entities
     * @return dekodierter String
     */
    public static final String decodeXmlEntities(String value) {
        if (value == null) {
            return null;
        }
        
        StringBuffer newInput = new StringBuffer(value.length());
        
        Pattern p = Pattern.compile("&#(\\d)+;");
        Matcher m = p.matcher(value);

        try {
            while (m.find()) {
                String property = m.group();
                property = property.substring(2, property.length() - 1);
                String s = new String(new char[] {(char) Integer.parseInt(property)});

                m.appendReplacement(newInput, s);
            }
        } catch (Exception e) {
            return value;
        }

        m.appendTail(newInput);

        return newInput.toString();
    }

    /**
     * Dekodiert einen StringArray mit XML-Entities (z.B. &#8364;) wieder in einen Java-String.
     * @param value StringArray mit XML-Entities
     * @return dekodierter StringArray
     */
    public static final String[] decodeXmlEntities(String[] values) {
        if (values == null) {
            return null;
        }
        
        String[] newValues = new String[values.length];
        
        for (int i = 0; i < newValues.length; i++) {
            newValues[i] = decodeXmlEntities(values[i]);
        }
        
        return newValues;
    }

    public static String decodeNewLine(String value) {
        if (value == null) {
            return null;
        }

        value = StringUtils.replaceToken(value, "§$rishnun%#", "\r\n");
        value = StringUtils.replaceToken(value, "§$nunrish%#", "\n\r");
        value = StringUtils.replaceToken(value, "§$nun%#", "\n");
        value = StringUtils.replaceToken(value, "§$rish%#", "\r");
        
        return value;
    }
    
    /**
     * Kodiert einen Java-String (z.B. &#8364;) in Named-XML-Entities (z.B. &amp;euro;).
     * @param value String mit XML-Entities
     * @return kodierter String
     */
    public static final String encodeNamedXmlEntities(String value) {
        if (value == null) {
            return null;
        }

        char[] content = new char[value.length()];
        value.getChars(0, value.length(), content, 0);

        StringBuffer result = new StringBuffer(content.length + 50);

        for (int i = 0; i < content.length; i++) {
            String entity = VKCUnicode2HtmlEntities.getHtmlEntity(content[i]);
        	
            if (entity == null) {
                int c = content[i];

                switch (c) {
    	            case 128:
    	                result.append("&#8364;");
    	                break;
    	            case 130:
    	                result.append("&#8218;");
    	                break;
    	            case 131:
    	                result.append("&#402;");
    	                break;
    	            case 132:
    	                result.append("&#8222;");
    	                break;
    	            case 133:
    	                result.append("&#8230;");
    	                break;
    	            case 134:
    	                result.append("&#8224;");
    	                break;
    	            case 135:
    	                result.append("&#8225;");
    	                break;
    	            case 136:
    	                result.append("&#710;");
    	                break;
    	            case 137:
    	                result.append("&#8240;");
    	                break;
    	            case 138:
    	                result.append("&#352;");
    	                break;
    	            case 139:
    	                result.append("&#8249;");
    	                break;
    	            case 140:
    	                result.append("&#338;");
    	                break;
    	            case 142:
    	                result.append("&#381;");
    	                break;
    	            case 145:
    	                result.append("&#8216;");
    	                break;
    	            case 146:
    	                result.append("&#8217;");
    	                break;
    	            case 147:
    	                result.append("&#8220;");
    	                break;
    	            case 148:
    	                result.append("&#8221;");
    	                break;
    	            case 149:
    	                result.append("&#8226;");
    	                break;
    	            case 150:
    	                result.append("&#8211;");
    	                break;
    	            case 151:
    	                result.append("&#8212;");
    	                break;
    	            case 152:
    	                result.append("&#732;");
    	                break;
    	            case 153:
    	                result.append("&#8482;");
    	                break;
    	            case 154:
    	                result.append("&#353;");
    	                break;
    	            case 155:
    	                result.append("&#8250;");
    	                break;
    	            case 156:
    	                result.append("&#339;");
    	                break;
    	            case 158:
    	                result.append("&#382;");
    	                break;
    	            case 159:
    	                result.append("&#376;");
    	                break;
    	            default:
    	                if (c > 255) {
    	                    result.append("&#" + c + ";");
    	                } else {
    	                    result.append(content[i]);
    	                }
                }
			} else {
				result.append(entity);
			}
        }
        
        return result.toString();
    }
    
    /**
     * Kodiert einen Java-String in XML-Entities (z.B. &#8364;).
     * @param value String mit XML-Entities
     * @return kodierter String
     */
    public static final String encodeXmlEntities(String value) {
        if (value == null) {
            return null;
        }

        char[] content = new char[value.length()];
        value.getChars(0, value.length(), content, 0);

        StringBuffer result = new StringBuffer(content.length + 50);

        for (int i = 0; i < content.length; i++) {
            int c = content[i];
            result.append("&#" + c + ";");
        }
        
        String s = result.toString();
        s = replace(s, "&#13;&#10;", "\n");
        s = replace(s, "&#10;&#13;", "\n");
        s = replace(s, "&#10;", "\n");
        s = replace(s, "&#13;", "\n");
        
        return s;
    }
    
    public static String encodeNewLine(String value) {
        if (value == null) {
            return null;
        }

        value = StringUtils.replaceToken(value, "\r\n", "§$rishnun%#");
        value = StringUtils.replaceToken(value, "\n\r", "§$nunrish%#");
        value = StringUtils.replaceToken(value, "\n", "§$nun%#");
        value = StringUtils.replaceToken(value, "\r", "§$rish%#");
        value = StringUtils.replaceToken(value, "<br>", "§$nun%#");
        value = StringUtils.replaceToken(value, "<br/>", "§$nun%#");
        value = StringUtils.replaceToken(value, "<br />", "§$nun%#");
        
        return value;
    }
    
    /**
     * Formatiert die Eingabe entsprechend
     * der Größe nach bytes, KB, MB, GB, TB, PB, EB
     *
     * @param bytes die zu formatierende Zahl
     * @param languagId die zu formatierende Zahl
     * @return
     */
    public static final String formatBytes(long bytes, String languageId) {
		VKCLanguage language = VKCLanguageSerializer.getLanguage(Integer.valueOf(languageId));
	    DecimalFormat formatter = (DecimalFormat)NumberFormat.getInstance(language.getLocale());
		formatter.setMaximumFractionDigits(2);

		if (bytes < oneKB) {
            return bytes + " Byte";
        } 

        if (bytes < oneMB) {
            return formatter.format(bytes / (double) oneKB) + " KB";
        } 

        if (bytes < oneGB) {
            return formatter.format(bytes / (double) oneMB) + " MB";
        } 

        if (bytes < oneTB) {
            return formatter.format(bytes / (double) oneGB) + " GB";
        } 

        if (bytes < onePB) {
            return formatter.format(bytes / (double) oneTB) + " TB";
        } 

        if (bytes < oneEB) {
            return formatter.format(bytes / (double) onePB) + " PB";
        } 

        return formatter.format(bytes / (double) oneEB) + " EB";
    }

    /**
     * Hilfsmethode fuer den VKCCreator. Wandelt eine Zeichnekette in einen Vector zurück
     * <p>
     * @param   str  - die Zeichenkette
     * @param delimiter - das Trennzeichen z.B. ";"
     * @return     der Vector
     */
    public static final Vector stringToVector(String str, String delimiter) {
        Vector v = new Vector();

        if (str == null) {
            return v;
        }

        while (str.indexOf(delimiter) >= 0) {
            v.add(str.substring(0, str.indexOf(delimiter)));
            str = str.substring(str.indexOf(delimiter) + delimiter.length(), str.length());
        }

        if (str.trim().length() > 0) {
            v.add(str);
        }

        return v;
    }

    /**
     * Hilgsmethode fuer den VKCCreator. Wandelt eine Zeichnekette in einen Vector zurück
     * <p>
     * @param   str  die Zeichenkette
     * @return     der Vector
     */
    public static Vector stringToVector(String str) {
        return stringToVector(str, "-/#VECTORSEPERATOR#/-");
    }

    /**
     * Hilfsmethode fuer den VKCCreator. Wandelt einen Vector in eine Zeichenkette um
     * <p>
     * @param   v  der Vector
     * @param delimiter - das Trennzeichen z.B. ";"
     * @return     die Zeichenkette
     */
    public static String vectorToString(Vector v, String delimiter) {
        StringBuffer strbuf = new StringBuffer();

        try {
            for (int i = 0; i < v.size(); i++) {
                strbuf.append((String) v.get(i));

                if (i != (v.size() - 1)) {
                    strbuf.append(delimiter);
                }
            }
        } catch (Exception e) {
            System.out.println(e);
        }

        return strbuf.toString();
    }

    /**
     * Hilfsmethode fuer den VKCCreator. Wandelt einen Vector in eine Zeichenkette um
     * <p>
     * @param   v  der Vector
     * @return     die Zeichenkette
     */
    public static String vectorToString(Vector v) {
        return vectorToString(v, "-/#VECTORSEPERATOR#/-");
    }

    public static final String normalizeURL(String urlString) {
        if (urlString.endsWith("index.html")) {
            urlString = urlString.substring(0, urlString.lastIndexOf("/") + 1);
        } else if (!urlString.endsWith("/")) {
            urlString += "/";
        }

        return urlString;
    }

    public static final String normalizeFilePath(String path) {
        if (path.endsWith("index.html")) {
            path = path.substring(0, path.lastIndexOf(File.separator) + 1);
        } else if (!path.endsWith(File.separator)) {
            path += File.separator;
        }

        return path;
    }

    public static final ArrayList split(String toSplit, String token) {
        toSplit.trim();

        int start = 0;
        int index = -1;
        String resultString = null;
        ArrayList result = new ArrayList();

        while ((toSplit.indexOf(token, start) != -1) || (toSplit.length() > 0)) {
            index = toSplit.indexOf(token, start);

            //System.err.println(">" + toSplit + "<");
            if (index != -1) {
                resultString = toSplit.substring(0, index);
                toSplit = toSplit.substring(index + 1, toSplit.length());

                if (resultString.length() > 0) {
                    result.add(resultString);
                }
            } else {
                result.add(toSplit);
                toSplit = "";
            }
        }

        return result;
    }

    public static String convertNewLineInHTML(String value) {
        if (value == null) {
            return null;
        }

        value = StringUtils.replaceToken(value, "\r\n", "<br/>");
        value = StringUtils.replaceToken(value, "\n\r", "<br/>");
        value = StringUtils.replaceToken(value, "\n", "<br/>");
        value = StringUtils.replaceToken(value, "\r", "<br/>");
        
        return value;
    }
    
    public static String htmlFormatedText(String value) {
        if (value == null) {
            return null;
        }

        value = StringUtils.replaceToken(value, "&#38;", "&");
        value = StringUtils.replaceToken(value, "&#34;", "\"");
        value = StringUtils.replaceToken(value, "&#60;", "<");
        value = StringUtils.replaceToken(value, "&#62;", ">");
        
        return value;
    }
    
    /**
     * Diese Methode entfernt alle Teilstring der Form &lt;...&gt;
     * @throws BadLocationException 
     */
    public static final String removeHtmlTags(String value) throws BadLocationException {
        if (value == null) {
            return null;
        }
        
        StringBuffer newInput = new StringBuffer(value.length());

        Pattern p = Pattern.compile("(<.+?>)");
        Matcher m = p.matcher(value);

        try {
            while (m.find()) {
                String tag = m.group();
                tag = tag.substring(1, tag.length() - 1).trim();
                
                
                if ("br /".equalsIgnoreCase(tag) || "br/".equalsIgnoreCase(tag)) {
                    m.appendReplacement(newInput, "<br>");
                }            
            }
        } catch (Exception e) {
            return value;
        }

        m.appendTail(newInput);

        JEditorPane pane = new JEditorPane("text/html", newInput.toString());
        Document doc = pane.getDocument();
        String content = doc.getText(doc.getStartPosition().getOffset(), doc.getEndPosition().getOffset());

        return content;
    }

    public static final String base64Encode(String value) {
    	if (value == null) {
    		return null;
    	}
    	
		try {
			byte[] bs = VKCCoder.base64Encode(value.getBytes("ISO-8859-1"));
			String s = new String(bs, "ISO-8859-1");
			s = replaceToken(s, "+", "%2B");

			return s;
		} catch (UnsupportedEncodingException e) {
			byte[] bs = VKCCoder.base64Encode(value.getBytes());
			String s = new String(bs);
			s = replaceToken(s, "+", "%2B");
			
			return s;
		}
        
    }

    public static final String base64Decode(String value) {
    	return VKCCoder.base64Decode(value);
    }
}