/*
 * File   : $Source: /usr/local/cvs/opencms/test/org/opencms/util/TestCmsStringUtil.java,v $
 * Date   : $Date: 2008-02-27 12:05:30 $
 * Version: $Revision: 1.18 $
 *
 * This library is part of OpenCms -
 * the Open Source Content Management System
 *
 * Copyright (c) 2002 - 2008 Alkacon Software GmbH (http://www.alkacon.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * For further information about Alkacon Software GmbH, please see the
 * company website: http://www.alkacon.com
 *
 * For further information about OpenCms, please see the
 * project website: http://www.opencms.org
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.opencms.util;

import org.opencms.i18n.CmsEncoder;

import java.util.Arrays;
import java.util.List;

import junit.framework.TestCase;

/** 
 * Test cases for {@link org.opencms.util.CmsStringUtil}.<p>
 * 
 * @author Andreas Zahner 
 * @author Achim Westermann 
 * 
 * @version $Revision: 1.18 $
 */
public class TestCmsStringUtil extends TestCase {

    /**
     * Default JUnit constructor.<p>
     * 
     * @param arg0 JUnit parameters
     */
    public TestCmsStringUtil(String arg0) {

        super(arg0);
    }

    /**
     * Tests content replacement during import.<p>
     */
    public void testCmsContentReplacement() {

        String content, result, context, search, replace;

        content = "<html><body>\n"
            + "See <a href=\"http://www.opencms.org/opencms/opencms/opencms/index.html\">\n"
            + "http://www.opencms.org/opencms/opencms/opencms/index.html</a>\n"
            + "or <a href=\"/opencms/opencms/opencms/index.html\">\n"
            + "/opencms/opencms/opencms/index.html</a>\n"
            + "<img src=\"/opencms/opencms/system/galleries/pics/test/test.gif\">\n"
            + "<img src=\"http://www.othersite.org/opencms/opencms/system/galleries/pics/test/test.gif\">\n"
            + "Some URL in the Text: http://www.thirdsite.org/opencms/opencms/some/url.html.\n"
            + "Another URL in the Text: /opencms/opencms/some/url.html.\n"
            + "</body></html>\n";

        result = "<html><body>\n"
            + "See <a href=\"http://www.opencms.org/opencms/opencms/opencms/index.html\">\n"
            + "http://www.opencms.org/opencms/opencms/opencms/index.html</a>\n"
            + "or <a href=\""
            + CmsStringUtil.MACRO_OPENCMS_CONTEXT
            + "/opencms/index.html\">\n"
            + CmsStringUtil.MACRO_OPENCMS_CONTEXT
            + "/opencms/index.html</a>\n"
            + "<img src=\""
            + CmsStringUtil.MACRO_OPENCMS_CONTEXT
            + "/system/galleries/pics/test/test.gif\">\n"
            + "<img src=\"http://www.othersite.org/opencms/opencms/system/galleries/pics/test/test.gif\">\n"
            + "Some URL in the Text: http://www.thirdsite.org/opencms/opencms/some/url.html.\n"
            + "Another URL in the Text: "
            + CmsStringUtil.MACRO_OPENCMS_CONTEXT
            + "/some/url.html.\n"
            + "</body></html>\n";

        context = "/opencms/opencms/";

        // search = "([>\"']\\s*)" + context;
        search = "([^\\w/])" + context;
        replace = "$1" + CmsStringUtil.escapePattern(CmsStringUtil.MACRO_OPENCMS_CONTEXT) + "/";

        String test = CmsStringUtil.substitutePerl(content, search, replace, "g");

        System.err.println(this.getClass().getName() + ".testCmsContentReplacement():");
        System.err.println(test);
        assertEquals(test, result);

        test = CmsStringUtil.substituteContextPath(content, context);
        assertEquals(test, result);
    }

    /**
     * Combined tests.<p>
     */
    public void testCombined() {

        String test;
        String content = "<p>A paragraph with text...<img src=\"/opencms/opencms/empty.gif\"></p>\n<a href=\"/opencms/opencms/test.jpg\">";
        String search = "/opencms/opencms/";
        String replace = "${path}";
        test = CmsStringUtil.substitute(content, search, replace);
        assertEquals(
            test,
            "<p>A paragraph with text...<img src=\"${path}empty.gif\"></p>\n<a href=\"${path}test.jpg\">");
        test = CmsStringUtil.substitute(test, replace, search);
        assertEquals(
            test,
            "<p>A paragraph with text...<img src=\"/opencms/opencms/empty.gif\"></p>\n<a href=\"/opencms/opencms/test.jpg\">");
    }

    /**
     * Tests for complext import patterns.<p>
     */
    public void testComplexPatternForImport() {

        String content = "<cms:link>/pics/test.gif</cms:link> <img src=\"/pics/test.gif\"> script = '/pics/test.gif' <cms:link> /pics/othertest.gif </cms:link>\n"
            + "<cms:link>/mymodule/pics/test.gif</cms:link> <img src=\"/mymodule/pics/test.gif\"> script = '/mymodule/pics/test.gif' <cms:link> /mymodule/system/galleries/pics/othertest.gif </cms:link>";
        String search = "([>\"']\\s*)/pics/";
        String replace = "$1/system/galleries/pics/";
        String test = CmsStringUtil.substitutePerl(content, search, replace, "g");
        assertEquals(
            test,
            "<cms:link>/system/galleries/pics/test.gif</cms:link> <img src=\"/system/galleries/pics/test.gif\"> script = '/system/galleries/pics/test.gif' <cms:link> /system/galleries/pics/othertest.gif </cms:link>\n"
                + "<cms:link>/mymodule/pics/test.gif</cms:link> <img src=\"/mymodule/pics/test.gif\"> script = '/mymodule/pics/test.gif' <cms:link> /mymodule/system/galleries/pics/othertest.gif </cms:link>");
    }

    /**
     * Tests for the escape patterns.<p>
     */
    public void testEscapePattern() {

        String test;
        test = CmsStringUtil.escapePattern("/opencms/opencms");
        assertEquals(test, "\\/opencms\\/opencms");
        test = CmsStringUtil.escapePattern("/opencms/$");
        assertEquals(test, "\\/opencms\\/\\$");
    }

    /**
     * Tests the body tag extraction.<p> 
     */
    public void testExtractHtmlBody() {

        String content, result;
        String innerContent = "This is body content in the body\n<h1>A headline</h1>\nSome text in the body\n";

        content = "<html><body>" + innerContent + "</body></html>";
        result = CmsStringUtil.extractHtmlBody(content);
        assertEquals(result, innerContent);

        content = "<html><body style='css' background-color:#ffffff>" + innerContent + "</body></html>";
        result = CmsStringUtil.extractHtmlBody(content);
        assertEquals(result, innerContent);

        content = "<html>\n<title>Test</title>\n<body style='css' background-color:#ffffff>"
            + innerContent
            + "</body>\n</html>";
        result = CmsStringUtil.extractHtmlBody(content);
        assertEquals(result, innerContent);

        content = "<html>< body style='css' background-color:#ffffff>" + innerContent + "</ BODY>";
        result = CmsStringUtil.extractHtmlBody(content);
        assertEquals(result, innerContent);

        content = "<BODY>" + innerContent + "</boDY></html></body><body>somemoretext</BODY>";
        result = CmsStringUtil.extractHtmlBody(content);
        assertEquals(result, innerContent);

        content = innerContent + "</boDY></html>";
        result = CmsStringUtil.extractHtmlBody(content);
        assertEquals(result, innerContent);

        content = "<html><BODY>" + innerContent;
        result = CmsStringUtil.extractHtmlBody(content);
        assertEquals(result, innerContent);

        content = innerContent;
        result = CmsStringUtil.extractHtmlBody(content);
        assertEquals(result, innerContent);
    }

    /**
     * Tests the xml encoding extraction.<p>
     */
    public void testExtractXmlEncoding() {

        String xml, result;

        xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
            + "<!DOCTYPE opencms SYSTEM"
            + "\"http://www.opencms.org/dtd/6.0/opencms-importexport.dtd\">\n"
            + "<opencms/>";

        result = CmsStringUtil.extractXmlEncoding(xml);
        assertEquals(result, CmsEncoder.ENCODING_UTF_8);

        xml = "<?xml version=\"1.0\" encoding='ISO-8859-1'?>\n" + "<opencms/>";

        result = CmsStringUtil.extractXmlEncoding(xml);
        assertEquals(result, "ISO-8859-1");
    }

    /**
     * Tests for the resource name formatting.<p>
     */
    public void testFormatResourceName() {

        String test;
        test = "/xmlcontentdemo/list.jsp";
        assertEquals("/.../list.jsp", CmsStringUtil.formatResourceName(test, 10));
        test = "/xmlcontentdemo/list.jsp";
        assertEquals("/xmlcontentdemo/list.jsp", CmsStringUtil.formatResourceName(test, 25));
        test = "/averylongresourcename.jsp";
        assertEquals("/averylongresourcename.jsp", CmsStringUtil.formatResourceName(test, 25));
        test = "/folder1/folder2/averylongresourcename.jsp";
        assertEquals("/.../averylongresourcename.jsp", CmsStringUtil.formatResourceName(test, 25));
        test = "/myfolder/subfolder/index.html";
        assertEquals("/.../index.html", CmsStringUtil.formatResourceName(test, 21));
        assertEquals("/myfolder/.../index.html", CmsStringUtil.formatResourceName(test, 25));
        test = "/myfolder/subfolder/subsubfolder/index.html";
        assertEquals("/myfolder/.../subsubfolder/index.html", CmsStringUtil.formatResourceName(test, 40));
        assertEquals("/myfolder/.../index.html", CmsStringUtil.formatResourceName(test, 36));
        assertEquals("/myfolder/.../index.html", CmsStringUtil.formatResourceName(test, 24));
        assertEquals("/.../index.html", CmsStringUtil.formatResourceName(test, 21));
        test = "/demopages/search-demo/example-documents/";
        assertEquals("/demopages/.../example-documents/", CmsStringUtil.formatResourceName(test, 40));
        assertEquals("/demopages/search-demo/example-documents/", CmsStringUtil.formatResourceName(test, 41));
    }

    /**
     * Further tests.<p> 
     */
    public void testLine() {

        String content = "<edittemplate><![CDATA[<H4><IMG style=\"WIDTH: 77px; HEIGHT: 77px\" alt=\"Homepage animation\" hspace=8 src=\"/opencms/opencms/pics/alkacon/x_hp_ani04.gif\" align=right vspace=8 border=0><IMG style=\"WIDTH: 307px; HEIGHT: 52px\" alt=\"Homepage animation\" hspace=0 src=\"/opencms/opencms/pics/alkacon/x_hp_ani05.gif\" vspace=8 border=0></H4>\n<P>Alkacon Software provides software development services for the digital business. We are specialized in web - based content management solutions build on open source Java Software. </P>\n<P>Alkacon Software is a major contributor to the <A href=\"http://www.opencms.org\" target=_blank>OpenCms Project</A>. OpenCms is an enterprise - ready content management platform build in Java from open source components. OpenCms can easily be deployed on almost any existing IT infrastructure and provides powerful features especially suited for large enterprise internet or intranet applications. </P>\n<P>Alkacon Software offers standard <A href=\"/alkacon/en/services/opencms/index.html\" target=_self>service and support </A>packages for OpenCms, providing an optional layer of security and convenience often required for mission critical OpenCms installations.</P>\n<UL>\n<LI><IMG style=\"WIDTH: 125px; HEIGHT: 34px\" alt=OpenCms hspace=3 src=\"/opencms/opencms/pics/alkacon/logo_opencms_125.gif\" align=right border=0>Learn more about our <A href=\"/alkacon/en/services/index.html\" target=_self>Services</A> \n<LI>Subscribe to our&nbsp;<A href=\"/alkacon/en/company/contact/newsletter.html\" target=_self>Company Newsletter</A> \n<LI>Questions? <A href=\"/alkacon/en/company/contact/index.html\" target=_self>Contact us</A></LI></UL>\n<P>&nbsp;</P>]]></edittemplate>";
        String search = "/pics/";
        String replace = "/system/galleries/pics/";
        String test = CmsStringUtil.substitute(content, search, replace);
        assertEquals(
            test,
            "<edittemplate><![CDATA[<H4><IMG style=\"WIDTH: 77px; HEIGHT: 77px\" alt=\"Homepage animation\" hspace=8 src=\"/opencms/opencms/system/galleries/pics/alkacon/x_hp_ani04.gif\" align=right vspace=8 border=0><IMG style=\"WIDTH: 307px; HEIGHT: 52px\" alt=\"Homepage animation\" hspace=0 src=\"/opencms/opencms/system/galleries/pics/alkacon/x_hp_ani05.gif\" vspace=8 border=0></H4>\n<P>Alkacon Software provides software development services for the digital business. We are specialized in web - based content management solutions build on open source Java Software. </P>\n<P>Alkacon Software is a major contributor to the <A href=\"http://www.opencms.org\" target=_blank>OpenCms Project</A>. OpenCms is an enterprise - ready content management platform build in Java from open source components. OpenCms can easily be deployed on almost any existing IT infrastructure and provides powerful features especially suited for large enterprise internet or intranet applications. </P>\n<P>Alkacon Software offers standard <A href=\"/alkacon/en/services/opencms/index.html\" target=_self>service and support </A>packages for OpenCms, providing an optional layer of security and convenience often required for mission critical OpenCms installations.</P>\n<UL>\n<LI><IMG style=\"WIDTH: 125px; HEIGHT: 34px\" alt=OpenCms hspace=3 src=\"/opencms/opencms/system/galleries/pics/alkacon/logo_opencms_125.gif\" align=right border=0>Learn more about our <A href=\"/alkacon/en/services/index.html\" target=_self>Services</A> \n<LI>Subscribe to our&nbsp;<A href=\"/alkacon/en/company/contact/newsletter.html\" target=_self>Company Newsletter</A> \n<LI>Questions? <A href=\"/alkacon/en/company/contact/index.html\" target=_self>Contact us</A></LI></UL>\n<P>&nbsp;</P>]]></edittemplate>");
    }

    /**
     * Tests <code>{@link CmsStringUtil#splitAsArray(String, char)}</code>.<p>
     */
    public void testSplitCharDelimiter() {

        String toSplit;
        char delimChar = '/';
        String[] arrayResult;
        List listResult;

        // test usability for path-tokenization (e.g. admin tool of workplace)
        toSplit = "/system/workplace/admin/searchindex/";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimChar);
        assertEquals(4, arrayResult.length);
        assertEquals("system", arrayResult[0]);
        assertEquals("workplace", arrayResult[1]);
        assertEquals("admin", arrayResult[2]);
        assertEquals("searchindex", arrayResult[3]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimChar);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // test an empty String: 
        toSplit = "";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimChar);
        assertEquals(0, arrayResult.length);
        listResult = CmsStringUtil.splitAsList(toSplit, delimChar);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // test a whitespace only String
        toSplit = "               ";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimChar);
        assertEquals(1, arrayResult.length);
        assertEquals(toSplit, arrayResult[0]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimChar);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // with truncation
        listResult = CmsStringUtil.splitAsList(toSplit, delimChar, true);
        assertEquals(1, listResult.size());
        assertEquals("", listResult.get(0));

        // test a 1 separator-only String
        toSplit = "/";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimChar);
        assertEquals(0, arrayResult.length);
        listResult = CmsStringUtil.splitAsList(toSplit, delimChar);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // test a 2 separator-only String
        toSplit = "//";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimChar);
        assertEquals(1, arrayResult.length);
        assertEquals("", arrayResult[0]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimChar);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // test a single token String with starting delimiter
        toSplit = "/token";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimChar);
        assertEquals(1, arrayResult.length);
        assertEquals("token", arrayResult[0]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimChar);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // test a single token String with ending delimiter
        toSplit = "token/";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimChar);
        assertEquals(1, arrayResult.length);
        assertEquals("token", arrayResult[0]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimChar);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // test a 3 separator-only String
        toSplit = "///";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimChar);
        assertEquals(2, arrayResult.length);
        assertEquals("", arrayResult[0]);
        assertEquals("", arrayResult[1]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimChar);
        assertEquals(Arrays.asList(arrayResult), listResult);

        toSplit = "/a // b/ c /";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimChar);
        assertEquals(4, arrayResult.length);
        assertEquals("a ", arrayResult[0]);
        assertEquals("", arrayResult[1]);
        assertEquals(" b", arrayResult[2]);
        assertEquals(" c ", arrayResult[3]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimChar);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // with truncation
        listResult = CmsStringUtil.splitAsList(toSplit, delimChar, true);
        assertEquals(4, listResult.size());
        assertEquals("a", listResult.get(0));
        assertEquals("", listResult.get(1));
        assertEquals("b", listResult.get(2));
        assertEquals("c", listResult.get(3));
    }

    /**
     * Tests <code>{@link CmsStringUtil#splitAsArray(String, String)}</code>.<p>
     */
    public void testSplitStringDelimiter() {

        String toSplit;
        String delimString = "/";
        String[] arrayResult;
        List listResult;

        toSplit = "/system/workplace/admin/searchindex/";

        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(4, arrayResult.length);
        assertEquals("system", arrayResult[0]);
        assertEquals("workplace", arrayResult[1]);
        assertEquals("admin", arrayResult[2]);
        assertEquals("searchindex", arrayResult[3]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // test an empty String: 
        toSplit = "";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(0, arrayResult.length);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // whitespace only String
        toSplit = "               ";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(1, arrayResult.length);
        assertEquals(toSplit, arrayResult[0]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // with truncation
        listResult = CmsStringUtil.splitAsList(toSplit, delimString, true);
        assertEquals(1, listResult.size());
        assertEquals("", listResult.get(0));

        // test a 1 separator-only String
        toSplit = "/";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(0, arrayResult.length);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // test a 2 separator-only String
        toSplit = "//";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(1, arrayResult.length);
        assertEquals("", arrayResult[0]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // test a single token String with starting delimiter
        toSplit = "/token";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(1, arrayResult.length);
        assertEquals("token", arrayResult[0]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // test a single token String with ending delimiter
        toSplit = "token/";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(1, arrayResult.length);
        assertEquals("token", arrayResult[0]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // test a 3 separator-only String
        toSplit = "///";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(2, arrayResult.length);
        assertEquals("", arrayResult[0]);
        assertEquals("", arrayResult[1]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        toSplit = "/a // b/ c /";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(4, arrayResult.length);
        assertEquals("a ", arrayResult[0]);
        assertEquals("", arrayResult[1]);
        assertEquals(" b", arrayResult[2]);
        assertEquals(" c ", arrayResult[3]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // with truncation
        listResult = CmsStringUtil.splitAsList(toSplit, delimString, true);
        assertEquals(4, listResult.size());
        assertEquals("a", listResult.get(0));
        assertEquals("", listResult.get(1));
        assertEquals("b", listResult.get(2));
        assertEquals("c", listResult.get(3));

        // some tests with a separator longer than 1 

        delimString = ",,";
        toSplit = ",,system,,workplace,,admin,,searchindex,,";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(4, arrayResult.length);
        assertEquals("system", arrayResult[0]);
        assertEquals("workplace", arrayResult[1]);
        assertEquals("admin", arrayResult[2]);
        assertEquals("searchindex", arrayResult[3]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // test an empty String: 
        toSplit = "";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(0, arrayResult.length);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // test a whitespace String with truncation:
        toSplit = "               ";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(1, arrayResult.length);
        assertEquals(toSplit, arrayResult[0]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // test a 1 separator-only String
        toSplit = ",,";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(0, arrayResult.length);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // test a 2 separator-only String
        toSplit = ",,,,";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(1, arrayResult.length);
        assertEquals("", arrayResult[0]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // test a single token String with starting delimiter
        toSplit = ",,token";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(1, arrayResult.length);
        assertEquals("token", arrayResult[0]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // test a single token String with ending delimiter
        toSplit = "token,,";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(1, arrayResult.length);
        assertEquals("token", arrayResult[0]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        // test a 3 separator-only String
        toSplit = ",,,,,,";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(2, arrayResult.length);
        assertEquals("", arrayResult[0]);
        assertEquals("", arrayResult[1]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        toSplit = ",,a, aber nicht b,,,,b, aber nicht c,,c, but not a,,";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(4, arrayResult.length);
        assertEquals("a, aber nicht b", arrayResult[0]);
        assertEquals("", arrayResult[1]);
        assertEquals("b, aber nicht c", arrayResult[2]);
        assertEquals("c, but not a", arrayResult[3]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        delimString = "/delim/";
        toSplit = "/delim fake at start/delim//not a delim//delim//delim//delim fake at end";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(4, arrayResult.length);
        assertEquals("/delim fake at start", arrayResult[0]);
        assertEquals("/not a delim/", arrayResult[1]);
        assertEquals("", arrayResult[2]);
        assertEquals("/delim fake at end", arrayResult[3]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        toSplit = "/delim fake at start/delim//not a delim//delim//delim//delim";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(4, arrayResult.length);
        assertEquals("/delim fake at start", arrayResult[0]);
        assertEquals("/not a delim/", arrayResult[1]);
        assertEquals("", arrayResult[2]);
        assertEquals("/delim", arrayResult[3]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);

        toSplit = "/delim//delim fake at start/delim//not a delim//delim//delim//delim fake at end/delim/";
        arrayResult = CmsStringUtil.splitAsArray(toSplit, delimString);
        assertEquals(4, arrayResult.length);
        assertEquals("/delim fake at start", arrayResult[0]);
        assertEquals("/not a delim/", arrayResult[1]);
        assertEquals("", arrayResult[2]);
        assertEquals("/delim fake at end", arrayResult[3]);
        listResult = CmsStringUtil.splitAsList(toSplit, delimString);
        assertEquals(Arrays.asList(arrayResult), listResult);
    }

    /**
     * Tests the basic String substitution.<p>
     */
    public void testSubstitute() {

        String test, result;

        String content = "<a href=\"/opencms/opencms/test.jpg\">";
        String search = "/opencms/opencms/";
        String replace = "\\${path}";

        test = CmsStringUtil.substitute(content, search, replace);
        System.out.println(test);
        assertEquals(test, "<a href=\"\\${path}test.jpg\">");

        test = CmsStringUtil.substitute(test, replace, search);
        assertEquals(test, "<a href=\"/opencms/opencms/test.jpg\">");

        content = "[0-9]$1/[^a]|/([}>\"'\\[]\\s*)/pics/";
        result = "[0-9]$1/[^a]|/([}>\"'\\[]\\s*)/pucs/";
        test = CmsStringUtil.substitute(content, "i", "u");
        assertEquals(test, result);

        content = "/delim//delim fake at start/delim//not a delim//delim//delim//delim fake at end/delim/";
        result = "REPLACED!/delim fake at startREPLACED!/not a delim/REPLACED!REPLACED!/delim fake at endREPLACED!";
        test = CmsStringUtil.substitute(content, "/delim/", "REPLACED!");
        assertEquals(test, result);
    }

    /**
     * Test case for {@link CmsStringUtil#trimToSize(String, int)} method.<p>
     */
    public void testTrimToSize() {

        String text, result, expected;

        text = "This is a short sentence.";
        expected = text;
        result = CmsStringUtil.trimToSize(text, 75);
        assertEquals(expected, result);

        text = "I am a short sentence.";
        expected = "I am a...";
        result = CmsStringUtil.trimToSize(text, 10, "...");
        assertEquals(expected, result);

        text = "I_am_a_short_sentence.";
        expected = "I_am_a_sh...";
        result = CmsStringUtil.trimToSize(text, 12, "...");
        assertEquals(expected, result);

        text = "I am a short sentence.";
        expected = "I am...";
        result = CmsStringUtil.trimToSize(text, 8, "...");
        assertEquals(expected, result);

        text = "I am a short sentence.";
        expected = "I...";
        result = CmsStringUtil.trimToSize(text, 7, "...");
        assertEquals(expected, result);

        text = "I am a short sentence.";
        expected = "I...";
        result = CmsStringUtil.trimToSize(text, 6, "...");
        assertEquals(expected, result);

        text = "I am a short sentence.";
        expected = "I...";
        result = CmsStringUtil.trimToSize(text, 5, "...");
        assertEquals(expected, result);

        text = "I am a short sentence.";
        expected = "I...";
        result = CmsStringUtil.trimToSize(text, 4, "...");
        assertEquals(expected, result);

        text = "I am a short sentence.";
        expected = "...";
        result = CmsStringUtil.trimToSize(text, 3, "...");
        assertEquals(expected, result);

        text = "I am a short sentence.";
        expected = "..";
        result = CmsStringUtil.trimToSize(text, 2, "...");
        assertEquals(expected, result);

        text = "I am a short sentence.";
        expected = ".";
        result = CmsStringUtil.trimToSize(text, 1, "...");
        assertEquals(expected, result);

        text = null;
        expected = null;
        result = CmsStringUtil.trimToSize(text, 10);
        assertEquals(expected, result);
    }

    /**
     * Test case for {@link CmsStringUtil#lastIndexOf(String, char[])} method.<p>
     */
    public void testLastIndexOf() {

        int result;

        result = CmsStringUtil.lastIndexOf("This is a Text", CmsStringUtil.SENTENCE_ENDING_CHARS);
        assertEquals(-1, result);

        result = CmsStringUtil.lastIndexOf("This ! is ? a . Text", CmsStringUtil.SENTENCE_ENDING_CHARS);
        assertEquals(14, result);
    }

    /**
     * Test case for {@link CmsStringUtil#trimToSize(String, int, int, String)}.<p>
     */
    public void testTrimToSizeText() {

        String text, result, expected;

        text = "This is a short sentence.";
        expected = text;
        result = CmsStringUtil.trimToSize(text, 75, 40, " ...");
        assertEquals(expected, result);

        text = "This is a short sentence. This is a longer sentence at the end of the short sentence.";
        expected = "This is a short sentence. This is a longer sentence at the end of the ...";
        result = CmsStringUtil.trimToSize(text, 75, 40, " ...");
        assertEquals(expected, result);

        text = "This is a short sentence. This is a longer sentence at the end of the short sentence.";
        expected = "This is a short sentence. ...";
        result = CmsStringUtil.trimToSize(text, 75, 75, " ...");
        assertEquals(expected, result);
    }
}