From e01c82e6c5314645304e73746078ee7246fb48f1 Mon Sep 17 00:00:00 2001 From: konermann Date: Thu, 9 Jul 2015 10:27:24 +0000 Subject: [PATCH] CCM NG: added Tests for StringUtils, and improved some of the methods of StringUtils git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@3522 8810af33-2d31-482b-a856-94f89814c4df --- .../java/com/arsdigita/util/StringUtils.java | 735 +++++++++--------- .../com/arsdigita/util/StringUtilsTest.java | 509 ++++++++++++ 2 files changed, 861 insertions(+), 383 deletions(-) create mode 100644 ccm-core/src/test/java/com/arsdigita/util/StringUtilsTest.java diff --git a/ccm-core/src/main/java/com/arsdigita/util/StringUtils.java b/ccm-core/src/main/java/com/arsdigita/util/StringUtils.java index e887b5ed2..6921a1654 100644 --- a/ccm-core/src/main/java/com/arsdigita/util/StringUtils.java +++ b/ccm-core/src/main/java/com/arsdigita/util/StringUtils.java @@ -13,7 +13,6 @@ * 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 com.arsdigita.util; import java.io.PrintWriter; @@ -53,38 +52,41 @@ public class StringUtils { public static final String NEW_LINE = System.getProperty("line.separator"); - private StringUtils() { // can't instantiate me! } - /** * Tests if a string is empty. + * * @param s A string to test - * @return true if s is null or empty; - * otherwise false + * @return true if s is null or empty; otherwise + * false + * */ public static boolean emptyString(String s) { - boolean expr = (s == null || s.trim().length() == 0); - return expr; + if (s != null) { + return s.isEmpty(); + } + return true; } /** * Tests if a string is empty. + * * @param o A string to test - * @return true if o is null or empty; - * otherwise false + * @return true if o is null or empty; otherwise + * false */ public static boolean emptyString(Object o) { - boolean expr = - (o == null || (o instanceof String && ((String)o).length() ==0)); + boolean expr + = (o == null || (o instanceof String && ((String) o).length() == 0)); return expr; } /** - * If the String is null, returns an empty string. Otherwise, - * returns the string unaltered + * If the String is null, returns an empty string. Otherwise, returns the + * string unaltered */ public static String nullToEmptyString(String s) { return (s == null) ? "" : s; @@ -93,111 +95,98 @@ public class StringUtils { /** * Escapes some "special" characters in HTML text (ampersand, angle * brackets, quote). + * * @param s The plain-text string to quote - * @return The string with special characters escpaed. + * @return The string with special characters escaped. */ public static String quoteHtml(String s) { if (s != null) { - StringBuffer result = new StringBuffer(s.length() + 10); - for (int i = 0; i < s.length(); i++) { - char ch = s.charAt(i); - switch (ch) { - case '&': - result.append("&"); - break; - case '"': - result.append("""); - break; - case '<': - result.append("<"); - break; - case '>': - result.append(">"); - break; - default: - result.append(ch); - } - } - return result.toString(); - } else { - return ""; - } - } - - /** - * Takes a plaintext string, and returns an HTML string that, when - * rendered by a web browser, will appear as the original input string - * - * @param s The input plaintext string - * @return A HTML string with blank lines coverted to
<p>
- * and ampersands/angle brackets escaped. - */ - public static String textToHtml(String s) { - s = quoteHtml(s); - s = s_re.substitute("s/\r\n\r\n/

/g", s); - s = s_re.substitute("s/\n\n/

/g", s); - s = s_re.substitute("s/\r\r/

/g", s); - s = s_re.substitute("s/\r\n/
/g", s); - s = s_re.substitute("s/\n/
/g", s); - s = s_re.substitute("s/\r/
/g", s); - return s; - } - - /** - * Removes tags and substitutes P tags with newlines. For much - * more extensive conversion of HTML fragments to plain text - * equivalents, see {@link HtmlToText}. - */ - public static String htmlToText(String s) { - if (s != null) { - // first take out new-lines - s = s_re.substitute("s/\n//g", s); - s = s_re.substitute("s/\r//g", s); - s = s_re.substitute("s/<[Pp]>/\n\n/g", s); - s = s_re.substitute("s/
/\n/ig", s); - // take out other tags - s = s_re.substitute("s/<([^>]*)>/ /g", s); + s = s.replaceAll("&", "&"); + s = s.replaceAll("\"", """); + s = s.replaceAll("<", "<"); + s = s.replaceAll(">", ">"); return s; } else { return ""; } } + /** + * Takes a plaintext string, and returns an HTML string that, when rendered + * by a web browser, will appear as the original input string + * + * @param s The input plaintext string + * @return A HTML string with blank lines coverted to

<p>
and + * ampersands/angle brackets escaped. + */ + public static String textToHtml(String s) { + s = quoteHtml(s); + s = s.replaceAll("\r\n\r\n", "

"); + s = s.replaceAll("\n\n", "

"); + s = s.replaceAll("\r\r", "

"); + s = s.replaceAll("\r\n", "
"); + s = s.replaceAll("\n", "
"); + s = s.replaceAll("\r", "
"); + return s; + } /** - * Converts plain text with simple inline markup - * into HTML. The following constructs are recognised: + * Removes tags and substitutes P tags with newlines. For much more + * extensive conversion of HTML fragments to plain text equivalents, see + * {@link HtmlToText}. + */ + public static String htmlToText(String s) { + if (s != null) { + // first take out new-lines + s = s.replaceAll("\n", ""); + s = s.replaceAll("\r", ""); + + s = s.replaceAll("<[pP]>", "\n\n"); + s = s.replaceAll("
", "\n"); + // take out other tags + s = s.replaceAll("<[^>]*>", " "); + return s; + } else { + return ""; + } + } + + /** + * Converts plain text with simple inline markup into HTML. The following + * constructs are recognised: * *

*/ @@ -208,7 +197,7 @@ public class StringUtils { StringBuffer html = new StringBuffer(""); Iterator i = blocks.iterator(); while (i.hasNext()) { - String block = (String)i.next(); + String block = (String) i.next(); if (s_re.match("/^\\s*(___+|---+)\\s*$/", block)) { html.append("
"); } else if (s_re.match("/^\\*\\s/", block)) { @@ -224,15 +213,15 @@ public class StringUtils { } private static String smartTextList(String match, - String type, - String s) { + String type, + String s) { ArrayList blocks = new ArrayList(); s_re.split(blocks, match, s); StringBuffer list = new StringBuffer("<" + type + ">\n"); Iterator i = blocks.iterator(); while (i.hasNext()) { - String block = (String)i.next(); + String block = (String) i.next(); if ("".equals(block)) { continue; @@ -248,6 +237,7 @@ public class StringUtils { } private static Map s_entities = new HashMap(); + static { s_log.debug("Static initalizer starting..."); s_entities.put("fraction12", "½"); @@ -289,19 +279,18 @@ public class StringUtils { // that interferes with the monospace stuff below.... s = s_re.substitute("s|@@|\u0001|gx", s); s = smartTextReplace(new TitledLinkSubstitution(links), - "@([^\\(@]+)\\(([^\\)]+)\\)", s); + "@([^\\(@]+)\\(([^\\)]+)\\)", s); // We protect hyperlinks so that the '/' or '@' doesn't get // mistaken for a block of italics / link s = smartTextReplace(new UntitledLinkSubstitution(links), - "([a-z]+:\\/\\/[^\\s,\\(\\)><]*)", s); + "([a-z]+:\\/\\/[^\\s,\\(\\)><]*)", s); s = smartTextReplace(new UntitledLinkSubstitution(links), - "(mailto:[^\\s,\\(\\)><]*)", s); + "(mailto:[^\\s,\\(\\)><]*)", s); if (s_log.isDebugEnabled()) { s_log.debug("After links {" + s + "}"); } - // Next lets process italics /italic/ // NB. this must be first, otherwise closing tags // interfere with the pattern matching @@ -326,7 +315,6 @@ public class StringUtils { s_log.debug("After styles {" + s + "}"); } - // Links are next on the list @text(url) s = s_re.substitute("s|@@|\u0001|gx", s); s = s_re.substitute("s|@([^\\(@]+)\\(([^\\)]+)\\)|$1|gx", s); @@ -337,7 +325,7 @@ public class StringUtils { // Finally we can unobscure the hyperlinks s = smartTextReplace(new UnobscureSubstitution(links), - "\u0002([^\u0002]+)\u0002", s); + "\u0002([^\u0002]+)\u0002", s); s = s_re.substitute("s|\u0001|@|gx", s); if (s_log.isDebugEnabled()) { s_log.debug("After links pass three {" + s + "}"); @@ -345,7 +333,7 @@ public class StringUtils { // And those entities s = smartTextReplace(new EntitySubstitution(), - "\u0003([^\u0003]+)\u0003", s); + "\u0003([^\u0003]+)\u0003", s); if (s_log.isDebugEnabled()) { s_log.debug("After entities (complete) {" + s + "}"); } @@ -354,15 +342,15 @@ public class StringUtils { } /** - * + * * @param subst * @param pattern * @param s - * @return + * @return */ private static String smartTextReplace(Substitution subst, - String pattern, - String s) { + String pattern, + String s) { Perl5Matcher matcher = new Perl5Matcher(); Perl5Compiler compiler = new Perl5Compiler(); StringBuffer result = new StringBuffer(); @@ -370,11 +358,11 @@ public class StringUtils { try { Util.substitute(result, - matcher, - compiler.compile(pattern), - subst, - input, - Util.SUBSTITUTE_ALL); + matcher, + compiler.compile(pattern), + subst, + input, + Util.SUBSTITUTE_ALL); } catch (MalformedPatternException e) { throw new UncheckedWrapperException("cannot perform substitution", e); } @@ -382,9 +370,10 @@ public class StringUtils { } /** - * + * */ private static class TitledLinkSubstitution implements Substitution { + private Map m_hash; public TitledLinkSubstitution(Map hash) { @@ -393,11 +382,11 @@ public class StringUtils { @Override public void appendSubstitution(StringBuffer appendBuffer, - MatchResult match, - int substitutionCount, - PatternMatcherInput originalInput, - PatternMatcher matcher, - Pattern pattern) { + MatchResult match, + int substitutionCount, + PatternMatcherInput originalInput, + PatternMatcher matcher, + Pattern pattern) { String title = match.group(1); String link = match.group(2); s_log.debug("Link: " + link); @@ -412,9 +401,10 @@ public class StringUtils { } /** - * + * */ private static class UntitledLinkSubstitution implements Substitution { + private Map m_hash; public UntitledLinkSubstitution(Map hash) { @@ -422,28 +412,29 @@ public class StringUtils { } public void appendSubstitution(StringBuffer appendBuffer, - MatchResult match, - int substitutionCount, - PatternMatcherInput originalInput, - PatternMatcher matcher, - Pattern pattern) { + MatchResult match, + int substitutionCount, + PatternMatcherInput originalInput, + PatternMatcher matcher, + Pattern pattern) { String link = match.group(1); s_log.debug("Link: " + link); Integer i = m_hash.size(); s_log.debug("Key: " + i); m_hash.put(i, link); - String dst = "@\u0002" + i.toString() + "\u0002(\u0002" + - i.toString() + "\u0002)"; + String dst = "@\u0002" + i.toString() + "\u0002(\u0002" + + i.toString() + "\u0002)"; appendBuffer.append(dst); s_log.debug("Encoded Link: " + dst); } } /** - * + * */ private static class UnobscureSubstitution implements Substitution { + private Map m_hash; public UnobscureSubstitution(Map hash) { @@ -451,49 +442,49 @@ public class StringUtils { } public void appendSubstitution(StringBuffer appendBuffer, - MatchResult match, - int substitutionCount, - PatternMatcherInput originalInput, - PatternMatcher matcher, - Pattern pattern) { + MatchResult match, + int substitutionCount, + PatternMatcherInput originalInput, + PatternMatcher matcher, + Pattern pattern) { String s = match.group(1); s_log.debug("Key: " + s); Integer i = Integer.valueOf(s); - appendBuffer.append((String)m_hash.get(i)); + appendBuffer.append((String) m_hash.get(i)); s_log.debug("Link: " + m_hash.get(i)); } } /** - * + * */ private static class EntitySubstitution implements Substitution { + public void appendSubstitution(StringBuffer appendBuffer, - MatchResult match, - int substitutionCount, - PatternMatcherInput originalInput, - PatternMatcher matcher, - Pattern pattern) { + MatchResult match, + int substitutionCount, + PatternMatcherInput originalInput, + PatternMatcher matcher, + Pattern pattern) { String s = match.group(1); s_log.debug("Key: " + s); - appendBuffer.append((String)s_entities.get(s)); + appendBuffer.append((String) s_entities.get(s)); s_log.debug("Entity: " + s_entities.get(s)); } } - /** - * Convert a string of items separated by a separator - * character to an (string)array of the items. sep is the separator - * character. Example: Input - s == "cat,house,dog" sep==',' - * Output - {"cat", "house", "dog"} + * Convert a string of items separated by a separator character to an + * (string)array of the items. sep is the separator character. Example: + * Input - s == "cat,house,dog" sep==',' Output - {"cat", "house", "dog"} + * * @param s string contains items separated by a separator character. * @param sep separator character. * @return Array of items. */ - public static String [] split(String s, char sep) { + public static String[] split(String s, char sep) { ArrayList al = new ArrayList(); int start_pos, end_pos; start_pos = 0; @@ -506,50 +497,56 @@ public class StringUtils { al.add(found_item); start_pos = end_pos + 1; } - if (s.length() > 0 && s.charAt(s.length()-1) == sep) { + if (s.length() > 0 && s.charAt(s.length() - 1) == sep) { al.add(""); // In case last character is separator } - String [] returned_array = new String[al.size()]; + String[] returned_array = new String[al.size()]; al.toArray(returned_array); return returned_array; } /** - *

Given a string, split it into substrings matching a regular - * expression that you supply. Parts of the original string which - * don't match the regular expression also appear as substrings. The - * upshot of this is that the final substrings can be concatenated - * to get the original string.

+ *

+ * Given a string, split it into substrings matching a regular expression + * that you supply. Parts of the original string which don't match the + * regular expression also appear as substrings. The upshot of this is that + * the final substrings can be concatenated to get the original string.

* - *

As an example, let's say the original string is:

+ *

+ * As an example, let's say the original string is:

* *
      * s = "/packages/foo/xsl/::vhost::/foo_::locale::.xsl";
      * 
* - *

We call the function like this:

+ *

+ * We call the function like this:

* *
      * output = splitUp (s, "/::\\w+::/");
      * 
* - *

The result (output) will be the following list:

+ *

+ * The result (output) will be the following list:

* *
      * ("/packages/foo/xsl/", "::vhost::", "/foo_", "::locale::", ".xsl")
      * 
* - *

Notice the important property that concatenating all these - * strings together will restore the original string.

+ *

+ * Notice the important property that concatenating all these strings + * together will restore the original string.

* - *

Here is another useful example. To split up HTML into elements - * and content, do:

+ *

+ * Here is another useful example. To split up HTML into elements and + * content, do:

* *
      * output = splitUp (html, "/<.*?>/");
      * 
* - *

You will end up with something like this:

+ *

+ * You will end up with something like this:

* *
      * ("The following text will be ", "", "bold", "", ".")
@@ -562,33 +559,33 @@ public class StringUtils {
      *
      * @author Richard W.M. Jones
      *
-     * 

This is equivalent to the Perl "global match in array context", + *

+ * This is equivalent to the Perl "global match in array context", * specifically: @a = /(RE)|(.+)/g;

* */ - public static List splitUp (String s, String re) - { - Perl5Util p5 = new Perl5Util (); - ArrayList list = new ArrayList (); + public static List splitUp(String s, String re) { + Perl5Util p5 = new Perl5Util(); + ArrayList list = new ArrayList(); while (s != null && s.length() > 0) { // Find the next match. - if (p5.match (re, s)) { - MatchResult result = p5.getMatch (); + if (p5.match(re, s)) { + MatchResult result = p5.getMatch(); // String up to the start of the match. - if (result.beginOffset (0) > 0) - list.add (s.substring (0, result.beginOffset (0))); + if (result.beginOffset(0) > 0) { + list.add(s.substring(0, result.beginOffset(0))); + } // Matching part. - list.add (result.toString ()); + list.add(result.toString()); // Update s to be the remainder of the string. - s = s.substring (result.endOffset (0)); - } - else { + s = s.substring(result.endOffset(0)); + } else { // Finished. - list.add (s); + list.add(s); s = null; } @@ -598,10 +595,9 @@ public class StringUtils { } /** - * Converts an array of Strings into a single String separated by - * a given character. - * Example Input: {"cat", "house", "dog"}, ',' - * Output - "cat,house,dog" + * Converts an array of Strings into a single String separated by a given + * character. Example Input: {"cat", "house", "dog"}, ',' Output - + * "cat,house,dog" * * @param strings The string array too join. * @param joinChar The character to join the array members together. @@ -622,12 +618,11 @@ public class StringUtils { return result.toString(); } - + /** - * Converts an array of Strings into a single String separated by - * a given string. - * Example Input: {"cat", "house", "dog"}, ", " - * Output - "cat, house, dog" + * Converts an array of Strings into a single String separated by a given + * string. Example Input: {"cat", "house", "dog"}, ", " Output - "cat, + * house, dog" * * @param strings The string array too join. * @param joinStr The string to join the array members together. @@ -648,27 +643,23 @@ public class StringUtils { return result.toString(); } - + /** * Extract a parameter value from a packed list of parameter values. - * Example: - * input: key="age", sep=',', - * plist="cost=23,age=27,name=Thom" - * output = "27". - * This is a simple implementation that is meant for controlled use in which - * the key and values are known to be safe. - * Specifically, the equals character must be used to indicate - * parameter assignments. There is no escape character. Thus the - * parameter names and values cannot contain the equals character or the - * separator character. + * Example: input: key="age", sep=',', plist="cost=23,age=27,name=Thom" + * output = "27". This is a simple implementation that is meant for + * controlled use in which the key and values are known to be safe. + * Specifically, the equals character must be used to indicate parameter + * assignments. There is no escape character. Thus the parameter names and + * values cannot contain the equals character or the separator character. * * @param key the key indicating which parameter value to extract. - * @param plist packed list of key=value assignments. The character '=' - * must be used to indicate the assignment. + * @param plist packed list of key=value assignments. The character '=' must + * be used to indicate the assignment. * @param sep separator character. * @return the value corresponding to the key, or null if the key is not - * present. If the key appears in the list more than once, - * the first value is returned. + * present. If the key appears in the list more than once, the first value + * is returned. */ public static String getParameter(String key, String plist, char sep) { int key_end; @@ -680,8 +671,8 @@ public class StringUtils { return null; // Did not find key } key_end = key_start + key.length(); - if (plist.charAt(key_end) == '=' && - (key_start == 0 || plist.charAt(key_start - 1) == sep)) { + if (plist.charAt(key_end) == '=' + && (key_start == 0 || plist.charAt(key_start - 1) == sep)) { // Found isolated parameter value, this is the match int value_end = plist.indexOf(sep, key_end); if (value_end == -1) { @@ -700,21 +691,22 @@ public class StringUtils { } /** - * Strip extra white space from a string. This replaces any white space - * character or consecutive white space characters with a single space. - * It is useful when comparing strings that should be equal except for - * possible differences in white space. Example: input = "I \ndo\tsee". - * Output = "I do see". + * Strip extra white space from a string. This replaces any white space + * character or consecutive white space characters with a single space. It + * is useful when comparing strings that should be equal except for possible + * differences in white space. Example: input = "I \ndo\tsee". Output = "I + * do see". + * * @param s string that may contain extra white space - * @return string the same as the input, but with extra white space - * removed and replaced by a single space. + * @return string the same as the input, but with extra white space removed + * and replaced by a single space. */ static public String stripWhiteSpace(String s) { StringBuffer to = new StringBuffer(); boolean inSpace = true; boolean isSpace; char c; - for (int i=0; i ") - .append(toString(e.getValue())); + to.append(toString(e.getKey())) + .append(" => ") + .append(toString(e.getValue())); } to.append(NEW_LINE).append("}"); } @@ -784,9 +775,9 @@ public class StringUtils { /** * Strips all new-line characters from the input string. + * * @param str a string to strip - * @return the input string with all new-line characters - * removed. + * @return the input string with all new-line characters removed. * @post result.indexOf('\r') == 0 * @post result.indexOf('\n') == 0 */ @@ -803,17 +794,19 @@ public class StringUtils { } /** - *

Add a possible newline for proper wrapping.

+ *

+ * Add a possible newline for proper wrapping.

* - *

Checks the given String to see if it ends with whitspace. If so, it + *

+ * Checks the given String to see if it ends with whitspace. If so, it * assumes this whitespace is intentional formatting and returns a reference - * to the original string. If not, a new String object is + * to the original string. If not, a new String object is * created containing the original plus a platform-dependent newline * character obtained from {@link System#getProperty(String) * System.getProperty("line.separator")}.

*/ public static String addNewline(String s) { - int n = s.length()-1; + int n = s.length() - 1; if (n == -1) { return s; } else if (Character.isWhitespace(s.charAt(n))) { @@ -823,34 +816,29 @@ public class StringUtils { } } - /** - * This takes the passed in string and truncates it. - * It cuts the string off at the length specified and then - * goes back to the most recent space and truncates any - * word that may have been cut off. It also takes the - * string and converts it to plain text so that no HTML - * will be shown. + * This takes the passed in string and truncates it. It cuts the string off + * at the length specified and then goes back to the most recent space and + * truncates any word that may have been cut off. It also takes the string + * and converts it to plain text so that no HTML will be shown. */ public static String truncateString(String s, int length) { return truncateString(s, length, true); } - /** - * This takes the passed in string and truncates it. - * It cuts the string off at the length specified and then - * goes back to the most recent space and truncates any - * word that may have been cut off. The htmlToText dictates - * whehter or not the string should be converted from HTML to - * text before being truncated + * This takes the passed in string and truncates it. It cuts the string off + * at the length specified and then goes back to the most recent space and + * truncates any word that may have been cut off. The htmlToText dictates + * whehter or not the string should be converted from HTML to text before + * being truncated * - * @param s The string to be truncated - * @param length The length which to truncate the string - * @param removeHTML Whether or not to convert the HTML to text + * @param s The string to be truncated + * @param length The length which to truncate the string + * @param removeHTML Whether or not to convert the HTML to text */ public static String truncateString(String s, int length, - boolean removeHTML) { + boolean removeHTML) { if (s == null) { return ""; } @@ -864,13 +852,18 @@ public class StringUtils { return string; } - return string.substring(0, string.lastIndexOf(" ", length)); + if (string.lastIndexOf(" ", length) == -1) { + //no whitespace found, so truncate at the specified length even if + // it is in the middle of a word + return string.substring(0, length); + } + + return string.substring(0, string.lastIndexOf(" ", length)).trim(); } - /** - * "join" a List of Strings into a single string, with each string - * separated by a defined separator string. + * "join" a List of Strings into a single string, with each string separated + * by a defined separator string. * * @param elements the strings to join together * @param sep the separator string @@ -882,7 +875,7 @@ public class StringUtils { Iterator iter = elements.iterator(); while (iter.hasNext()) { - String element = (String)iter.next(); + String element = (String) iter.next(); if (!first) { sb.append(sep); @@ -897,9 +890,8 @@ public class StringUtils { } /** - * Removes whitespace from the beginning of a string. If the - * string consists of nothing but whitespace characters, an empty - * string is returned. + * Removes whitespace from the beginning of a string. If the string consists + * of nothing but whitespace characters, an empty string is returned. */ public final static String trimleft(String s) { for (int i = 0; i < s.length(); i++) { @@ -911,8 +903,8 @@ public class StringUtils { } /** - * Returns a String containing the specified repeat count of a - * given pattern String. + * Returns a String containing the specified repeat count of a given pattern + * String. * * @param pattern the pattern String * @param repeatCount the number of time to repeat it @@ -926,8 +918,8 @@ public class StringUtils { } /** - * Returns a String containing the specified repeat count of a - * given pattern character. + * Returns a String containing the specified repeat count of a given pattern + * character. * * @param pattern the pattern character * @param repeatCount the number of time to repeat it @@ -937,50 +929,47 @@ public class StringUtils { } /** - * Wrap a string to be no wider than 80 characters. This is just - * a convenience method for calling the more general method with a - * default string width. + * Wrap a string to be no wider than 80 characters. This is just a + * convenience method for calling the more general method with a default + * string width. * * @param input the String to wrap * - * @since 5.1.2 + * @since 5.1.2 */ public static String wrap(String input) { - return wrap(input,80); + return wrap(input, 80); } /** - * Wrap a string to be no wider than a specified number of - * characters by inserting line breaks. If the input is null or - * the empty string, a string consisting of only the newline - * character will be returned. Otherwise the input string will be - * wrapped to the specified line length. In all cases the last - * character of the return value will be a single newline. + * Wrap a string to be no wider than a specified number of characters by + * inserting line breaks. If the input is null or the empty string, a string + * consisting of only the newline character will be returned. Otherwise the + * input string will be wrapped to the specified line length. In all cases + * the last character of the return value will be a single newline. * - *

Notes: + *

+ * Notes: * *

    *
  1. line breaks in the input string are preserved - *
  2. wrapping is "soft" in that lines in the output string may - * be longer than maxLength if they consist of contiguous - * non-whitespace characters. + *
  3. wrapping is "soft" in that lines in the output string may be longer + * than maxLength if they consist of contiguous non-whitespace characters. *
* * @param input the String to wrap - * @param maxLength the maximum number of characters between line - * breaks + * @param maxLength the maximum number of characters between line breaks * - * @since 5.1.2 + * @since 5.1.2 */ public static String wrap(String input, int maxLength) { final char SPACE = ' '; - final char ENDL = '\n'; + final char ENDL = '\n'; // Make sure that we start with a string terminated by a // newline character. Some of the index calculations below // depend on this. - if (emptyString(input)) { return String.valueOf(ENDL); } else { @@ -993,9 +982,8 @@ public class StringUtils { while (startOfLine < input.length()) { - String line = input.substring - (startOfLine, Math.min(input.length(), - startOfLine + maxLength)); + String line = input.substring(startOfLine, Math.min(input.length(), + startOfLine + maxLength)); if (line.equals("")) { break; @@ -1005,9 +993,8 @@ public class StringUtils { if (firstNewLine != -1) { // there is a newline - output.append - (input.substring(startOfLine, - startOfLine + firstNewLine)); + output.append(input.substring(startOfLine, + startOfLine + firstNewLine)); output.append(ENDL); startOfLine += firstNewLine + 1; continue; @@ -1017,7 +1004,6 @@ public class StringUtils { // we're on the last line and it is < maxLength so // just return it - output.append(line); break; } @@ -1027,17 +1013,13 @@ public class StringUtils { // no space found! Try the first space in the whole // rest of the string - - int nextSpace = input.indexOf - (SPACE, startOfLine); - int nextNewLine = input.indexOf - (ENDL, startOfLine); + int nextSpace = input.indexOf(SPACE, startOfLine); + int nextNewLine = input.indexOf(ENDL, startOfLine); if (nextSpace == -1) { lastSpace = nextNewLine; } else { - lastSpace = Math.min - (nextSpace,nextNewLine); + lastSpace = Math.min(nextSpace, nextNewLine); } if (lastSpace == -1) { @@ -1048,14 +1030,12 @@ public class StringUtils { } // code below will add this to the start of the line - lastSpace -= startOfLine; } // append up to the last space - output.append(input.substring(startOfLine, - startOfLine + lastSpace)); + startOfLine + lastSpace)); output.append(ENDL); startOfLine += lastSpace + 1; @@ -1065,34 +1045,24 @@ public class StringUtils { } /** - * Returns true if the String is AlphaNumeric. Obviously, this is not at all + * Returns true if the String is AlphaNumeric. Obviously, this is not at all * globalized and should only be used with English text. * * @param value String to check * @return true if value is alphanumeric, false otherwise. */ public static boolean isAlphaNumeric(String value) { - for (int i = 0; i < value.length(); i++) { - char c = value.charAt(i); - if (!(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || - ('0' <= c && c <= '9'))) { - return false; - } - } - - return true; + return !value.matches("^.*[^a-zA-Z0-9 ].*$"); } /** - * This method performs interpolation on multiple variables. - * The keys in the hash table correspond directly to the placeholders - * in the string. The values in the hash table can either be - * plain strings, or an instance of the PlaceholderValueGenerator - * interface + * This method performs interpolation on multiple variables. The keys in the + * hash table correspond directly to the placeholders in the string. The + * values in the hash table can either be plain strings, or an instance of + * the PlaceholderValueGenerator interface * - * Variable placeholders are indicated in text by surrounding - * a key word with a pair of colons. The keys in the hash - * table correspond to the names + * Variable placeholders are indicated in text by surrounding a key word + * with a pair of colons. The keys in the hash table correspond to the names * * eg. "::forename:: has the email address ::email::" * @@ -1110,22 +1080,20 @@ public class StringUtils { try { Util.substitute(result, - matcher, - compiler.compile("(::(?:\\w+(?:[.-]+\\w+)*)::)"), - subst, - input, - Util.SUBSTITUTE_ALL); + matcher, + compiler.compile("(::(?:\\w+(?:[.-]+\\w+)*)::)"), + subst, + input, + Util.SUBSTITUTE_ALL); } catch (MalformedPatternException e) { throw new UncheckedWrapperException("cannot perform substitution", e); } return result.toString(); } - /** - * THis method performs a single variable substitution - * on a string. The placeholder takes the form of - * ::key:: within the sample text. + * THis method performs a single variable substitution on a string. The + * placeholder takes the form of ::key:: within the sample text. * * @see java.text.MessageFormat * @@ -1139,8 +1107,6 @@ public class StringUtils { return s_re.substitute(pattern, text); } - - /** * Finds all occurrences of find in str and * replaces them with them with replace. @@ -1149,65 +1115,67 @@ public class StringUtils { * @pre replace != null */ public static String replace(final String str, - final String find, - final String replace) { + final String find, + final String replace) { Assert.exists(find, String.class); Assert.exists(replace, String.class); - if ( str == null ) return null; + if (str == null) { + return null; + } int cur = str.indexOf(find); - if ( cur < 0 ) return str; + if (cur < 0) { + return str; + } final int findLength = find.length(); // If replace is longer than find, assume the result is going to be // slightly longer than the original string. - final int bufferLength = - replace.length() > findLength ? (int) (str.length() * 1.1) : str.length(); + final int bufferLength + = replace.length() > findLength ? (int) (str.length() * 1.1) : str.length(); StringBuffer sb = new StringBuffer(bufferLength); int last = 0; - if ( cur == 0 ) { + if (cur == 0) { sb.append(replace); - cur = str.indexOf(find, cur+findLength); + cur = str.indexOf(find, cur + findLength); last = findLength; } - while ( cur > 0 ) { + while (cur > 0) { sb.append(str.substring(last, cur)); sb.append(replace); last = cur + findLength; - cur = str.indexOf(find, cur+findLength); + cur = str.indexOf(find, cur + findLength); } - if ( last < str.length()-1) { + if (last < str.length() - 1) { sb.append(str.substring(last)); } return sb.toString(); } - /** - * An interface allowing the value for a placeholder to be - * dynamically generated. + * An interface allowing the value for a placeholder to be dynamically + * generated. */ public interface PlaceholderValueGenerator { + /** - * Returns the value corresponding to the supplied key - * placeholder. + * Returns the value corresponding to the supplied key placeholder. * * @param key the key being substituted */ public String generate(String key); } - - /** - * + * */ private static class HashSubstitution implements Substitution { + private Map m_hash; public HashSubstitution(Map hash) { @@ -1215,48 +1183,48 @@ public class StringUtils { } public void appendSubstitution(StringBuffer appendBuffer, - MatchResult match, - int substitutionCount, - PatternMatcherInput originalInput, - PatternMatcher matcher, - Pattern pattern) { + MatchResult match, + int substitutionCount, + PatternMatcherInput originalInput, + PatternMatcher matcher, + Pattern pattern) { String placeholder = match.toString(); - String key = placeholder.substring(2, placeholder.length()-2); + String key = placeholder.substring(2, placeholder.length() - 2); - Object value = (m_hash.containsKey(key) ? - m_hash.get(key) : - placeholder); + Object value = (m_hash.containsKey(key) + ? m_hash.get(key) + : placeholder); - if( s_log.isDebugEnabled() ) { - Object hashValue = m_hash.get( key ); + if (s_log.isDebugEnabled()) { + Object hashValue = m_hash.get(key); - s_log.debug( "Placeholder: " + placeholder ); - s_log.debug( "Key: " + key ); - if( null != value ) { - s_log.debug( "Value (" + value.getClass().getName() + - "): " + value.toString() ); + s_log.debug("Placeholder: " + placeholder); + s_log.debug("Key: " + key); + if (null != value) { + s_log.debug("Value (" + value.getClass().getName() + + "): " + value.toString()); } - if( null != hashValue ) { - s_log.debug( "Hash Value (" + - hashValue.getClass().getName() + "): " + - hashValue.toString() ); + if (null != hashValue) { + s_log.debug("Hash Value (" + + hashValue.getClass().getName() + "): " + + hashValue.toString()); } } value = (m_hash.containsKey(key) ? m_hash.get(key) : ""); String val; - if( value instanceof PlaceholderValueGenerator ) { - PlaceholderValueGenerator gen = (PlaceholderValueGenerator)value; + if (value instanceof PlaceholderValueGenerator) { + PlaceholderValueGenerator gen = (PlaceholderValueGenerator) value; val = gen.generate(key); - } else if( value.getClass().isArray() ) { + } else if (value.getClass().isArray()) { Object[] values = (Object[]) value; StringBuffer buf = new StringBuffer(); - for( int i = 0; i < values.length; i++ ) { - buf.append( values[i].toString() ); - if( (values.length - 1) != i ) { - buf.append( ", " ); + for (int i = 0; i < values.length; i++) { + buf.append(values[i].toString()); + if ((values.length - 1) != i) { + buf.append(", "); } } @@ -1273,7 +1241,9 @@ public class StringUtils { * @throws NullPointerException if throwable is null */ public static String getStackTrace(Throwable throwable) { - if (throwable==null) { throw new NullPointerException("throwable"); } + if (throwable == null) { + throw new NullPointerException("throwable"); + } StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); @@ -1283,10 +1253,11 @@ public class StringUtils { } /** - * Returns a list of lines where each line represents one level - * in the stack trace captured by throwable. + * Returns a list of lines where each line represents one level in the stack + * trace captured by throwable. * - *

For a stack trace like this:

+ *

+ * For a stack trace like this:

* *
      * java.lang.Throwable
@@ -1296,7 +1267,8 @@ public class StringUtils {
      *         at Main.main(Main.java:7)
      * 
* - *

the returned list looks like this:

+ *

+ * the returned list looks like this:

* *
      * ["java.lang.Throwable",
@@ -1310,13 +1282,14 @@ public class StringUtils {
      * @throws NullPointerException if throwable is null
      */
     public static List getStackList(Throwable throwable) {
-        StringTokenizer tkn = new StringTokenizer
-            (getStackTrace(throwable), System.getProperty("line.separator"));
+        StringTokenizer tkn = new StringTokenizer(getStackTrace(throwable), System.getProperty("line.separator"));
         List list = new LinkedList();
-        while ( tkn.hasMoreTokens() ) {
+        while (tkn.hasMoreTokens()) {
             String token = tkn.nextToken().trim();
-            if ( "".equals(token) ) { continue; }
-            if ( token.startsWith("at ") ) {
+            if ("".equals(token)) {
+                continue;
+            }
+            if (token.startsWith("at ")) {
                 list.add(token.substring(3));
             } else {
                 list.add(token);
@@ -1331,11 +1304,11 @@ public class StringUtils {
      * "manipulate-input.js"
      *
      * For example, "Business promotions!" will be converted to
-     *              "business-promotions".
+     * "business-promotions".
      *
-     * @param name
-     *            the to be converted into a URL.
-     * @return the converted name, possibly unchanged and null if the input is null.
+     * @param name the to be converted into a URL.
+     * @return the converted name, possibly unchanged and null if the input is
+     * null.
      */
     public static String urlize(String name) {
         if (name == null) {
@@ -1348,16 +1321,12 @@ public class StringUtils {
 
             if (Character.isLetter(ch)) {
                 urlizedName.append(Character.toLowerCase(ch));
-            }
-            else if (Character.isDigit(ch) || ch == '_' || ch == '-') {
+            } else if (Character.isDigit(ch) || ch == '_' || ch == '-') {
                 urlizedName.append(ch);
-            }
-            else if (ch == ' ' || ch == '&' || ch == '/') {
+            } else if (ch == ' ' || ch == '&' || ch == '/') {
                 urlizedName.append('-');
             }
         }
         return urlizedName.toString();
     }
 }
-
-
diff --git a/ccm-core/src/test/java/com/arsdigita/util/StringUtilsTest.java b/ccm-core/src/test/java/com/arsdigita/util/StringUtilsTest.java
new file mode 100644
index 000000000..0747a9ecd
--- /dev/null
+++ b/ccm-core/src/test/java/com/arsdigita/util/StringUtilsTest.java
@@ -0,0 +1,509 @@
+/*
+ * Copyright (C) 2015 LibreCCM Foundation.
+ *
+ * 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.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301  USA
+ */
+package com.arsdigita.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.libreccm.tests.categories.UnitTest;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Konermann
+ */
+@Category(UnitTest.class)
+public class StringUtilsTest {
+
+    public StringUtilsTest() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() {
+    }
+
+    @AfterClass
+    public static void tearDownClass() {
+    }
+
+    @Before
+    public void setUp() {
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+//    @Test(expected = AssertionError.class)
+//    public void checkFailMessage() {
+//        Assert.fail("errormessage");
+//    }
+    @Test
+    public void testSmartText() {
+        String src = "foo *bar* wibble /eek/\n"
+                + "and mailto:dan@berrange.com eek!\n"
+                + "\n"
+                + "the second =paragraph= contains\n"
+                + "a link to http://www.google.com\n"
+                + "and the fractions 1/2 3/4 1/4 and\n"
+                + "the symbols for copyright (C),\n"
+                + "trademark (TM) and rights (R)\n"
+                + "\n"
+                + "* a bullet list\n"
+                + "* more *bullets* in\n"
+                + " this list element\n"
+                + "* a final element\n"
+                + "\n"
+                + "-------\n"
+                + "\n"
+                + "+ now an enumerated list item\n"
+                + "+ and one /more/\n"
+                + "+ this one is split over two lines\n"
+                + "for testing purposes\n"
+                + "\n"
+                + "___\n"
+                + "\n"
+                + "and now the end is near, lets test\n"
+                + "@google(http://www.google.com) a few\n"
+                + "titled links, including a mailto\n"
+                + "@Dan B(mailto:dan@@berrange.com)";
+        String expected = "
\n" + + "foo bar wibble eek\n" + + "and mailto:dan@berrange.com eek!\n" + + "
\n" + + "\n" + + "
\n" + + "the second paragraph contains\n" + + "a link to http://www.google.com\n" + + "and the fractions ½ ¾ ¼ and\n" + + "the symbols for copyright ©,\n" + + "trademark TM and rights ®\n" + + "
\n" + + "\n" + + "
    \n" + + "
  • \n" + + "a bullet list\n" + + "
  • \n" + + "
  • \n" + + "more bullets in\n" + + " this list element\n" + + "
  • \n" + + "
  • \n" + + "a final element
  • \n" + + "
\n" + + "\n" + + "
\n" + + "\n" + + "
    \n" + + "
  1. \n" + + "now an enumerated list item\n" + + "
  2. \n" + + "
  3. \n" + + "and one more\n" + + "
  4. \n" + + "
  5. \n" + + "this one is split over two lines\n" + + "for testing purposes
  6. \n" + + "
\n" + + "\n" + + "
\n" + + "\n" + + "
\n" + + "and now the end is near, lets test\n" + + "google a few\n" + + "titled links, including a mailto\n" + + "Dan B\n" + + "
\n"; + String actual = StringUtils.smartTextToHtml(src); + + assertTrue(expected.equals(actual)); + } + + @Test + public void testEmptyString() { + + assertTrue(StringUtils.emptyString(null)); + assertTrue(StringUtils.emptyString("")); + assertTrue(StringUtils.emptyString((Object) "")); + + assertTrue(!StringUtils.emptyString("foo")); + assertTrue(!StringUtils.emptyString((Object) "foo")); + assertTrue(!StringUtils.emptyString((Object) (new Integer(1)))); + + } + + @Test + public void testQuoteHtml() { + + assertEquals("", StringUtils.quoteHtml(null)); + assertEquals("", StringUtils.quoteHtml("")); + assertEquals("foo", StringUtils.quoteHtml("foo")); + assertEquals("foo&", StringUtils.quoteHtml("foo&")); + assertEquals("&foo", StringUtils.quoteHtml("&foo")); + assertEquals("&foo&", StringUtils.quoteHtml("&foo&")); + assertEquals("&"<>"&", + StringUtils.quoteHtml("&\"<>\"&")); + + } + + @Test + public void testGetParameter() throws Exception { + + String plist = "boyspet=play,pet=dog,play=yes,age=34,eopt=,opt=23"; + verifyGet(plist, "boyspet", "play"); + verifyGet(plist, "pet", "dog"); + verifyGet(plist, "play", "yes"); + verifyGet(plist, "age", "34"); + verifyGet(plist, "eopt", ""); + verifyGet(plist, "opt", "23"); + verifyGet(plist, "spet", null); + verifyGet(plist, "notin", null); + } + + // helper method for above test. + private static void verifyGet(String plist, String key, String expected) { + String found = StringUtils.getParameter(key, plist, ','); + assertEquals("Expected parameter not found, key=" + key + + " expected=" + expected + " found=" + found, + expected, found); + } + + @Test + public void testSplit() throws Exception { + + String plist = "cat,hat,,bat,rat"; + String[] ar = StringUtils.split(plist, ','); + verifySplit("cat", ar[0]); + verifySplit("hat", ar[1]); + verifySplit("", ar[2]); + verifySplit("bat", ar[3]); + verifySplit("rat", ar[4]); + assertEquals("expected array length 5, found=" + + ar.length, ar.length, 5); + plist = ",,dog,fish,,,"; + ar = StringUtils.split(plist, ','); + verifySplit("", ar[0]); + verifySplit("", ar[1]); + verifySplit("dog", ar[2]); + verifySplit("fish", ar[3]); + verifySplit("", ar[4]); + verifySplit("", ar[5]); + verifySplit("", ar[6]); + assertEquals("expected array length 7, found=" + + ar.length, ar.length, 7); + + } + + // helper method for above test. + private void verifySplit(String expected, String found) { + String errMsg = "Split, expected = " + expected + + " found = " + found; + assertEquals(errMsg, expected, found); + } + + @Test + public void testJoinChar() { + + String[] input = {"foo", "bar", "Qux"}; + String expected = "foo,bar,Qux"; + String found = StringUtils.join(input, ','); + String errMsg = "join char, expected = " + expected + + " found = " + found; + assertEquals(errMsg, expected, found); + + } + + @Test + public void testJoinString() { + + String[] input = {"foo", "bar", "Qux"}; + String expected = "foo,bar,Qux"; + String found = StringUtils.join(input, ","); + String errMsg = "join string, expected = " + expected + + " found = " + found; + assertEquals(errMsg, expected, found); + + } + + @Test + public void testStripWhiteSpace() throws Exception { + + String in = " < H> e \t\n ll/> o . \n "; + String expected_out = "< H> e ll/> o ."; + String actual_out = StringUtils.stripWhiteSpace(in); + assertEquals("stripWhiteSpace failed. Expected = '" + + expected_out + "', Found = '" + actual_out + "'", + expected_out, actual_out); + + } + + @Test + public void testAddNewline() throws Exception { + String in = "*"; + String nl = System.getProperty("line.separator"); + + String expected_out = in + nl; + String actual_out = StringUtils.addNewline(in); + assertEquals("failed to add newline", expected_out, actual_out); + + in = "* "; + expected_out = in; + actual_out = StringUtils.addNewline(in); + assertEquals("added unecessary newline", expected_out, actual_out); + + in = "*" + nl; + expected_out = in; + actual_out = StringUtils.addNewline(in); + assertEquals("added unecessary newline", expected_out, actual_out); + + in = "" + nl; + expected_out = in; + actual_out = StringUtils.addNewline(in); + assertEquals("added unecessary newline", expected_out, actual_out); + } + + @Test + public void testHtmlToText() { + + String in = "

this is the text
newline .

one
two
"; + String expected_out = "\n\nthis is the text\nnewline . one\n two \n"; + String actual_out = StringUtils.htmlToText(in); + + String errMsg = "htmlToText, expected = " + expected_out + + " found = " + actual_out; + + assertEquals(errMsg, expected_out, actual_out); + + + + in = "Text with strange markup"; + expected_out = "Text with strange markup"; + actual_out = StringUtils.htmlToText(in); + + errMsg = "htmlToText, expected = " + expected_out + + " found = " + actual_out; + assertEquals(errMsg,expected_out, actual_out); + } + + @Test + public void testTrimleft() { + String in = "a"; + String expected_out = "a"; + String actual_out = StringUtils.trimleft(in); + assertEquals("trimleft invalid", expected_out, actual_out); + + in = " a"; + expected_out = "a"; + actual_out = StringUtils.trimleft(in); + assertEquals("trimleft invalid", expected_out, actual_out); + + in = " "; + expected_out = ""; + actual_out = StringUtils.trimleft(in); + assertEquals("trimleft invalid", expected_out, actual_out); + } + + @Test + public void testRepeat() { + String in = "a"; + String expected_out = "aaaaa"; + String actual_out = StringUtils.repeat(in, 5); + assertEquals("repeat invalid", expected_out, actual_out); + + actual_out = StringUtils.repeat('a', 5); + assertEquals("repeat invalid", expected_out, actual_out); + } + + @Test + public void testWrap() { + + // Identity test + String in = "a\n"; + String expected_out = in; + String actual_out = StringUtils.wrap(in); + assertEquals("wrap failed identify test", + expected_out, + actual_out); + + // Identify test with multiple words + in = "a b c d e\n"; + expected_out = in; + actual_out = StringUtils.wrap(in); + assertEquals("wrap failed identify test", + expected_out, + actual_out); + + // Simple test with short lines + in = StringUtils.repeat("1234 ", 5); + expected_out = StringUtils.repeat("1234\n", 5); + actual_out = StringUtils.wrap(in, 1); + assertEquals("wrap invalid", + expected_out, + actual_out); + + // Verify preservation of line breaks + in = StringUtils.repeat("1234\n", 5); + expected_out = in; + actual_out = StringUtils.wrap(in, 100); + assertEquals("line break preservation failed", + expected_out, + actual_out); + + // Verify a "standard" wrapping case + in = StringUtils.repeat("1234 ", 10); + expected_out + = StringUtils.repeat("1234 ", 5).trim() + "\n" + + StringUtils.repeat("1234 ", 5).trim() + "\n"; + + actual_out = StringUtils.wrap(in, 25); + assertEquals("line wrapping failed", + expected_out, + actual_out); + } + + @Test + public void testPlaceholders() { + String in = "foo ::bar:: wizz"; + String expected_out = "foo eek wizz"; + String actual_out = StringUtils.interpolate(in, "bar", "eek"); + + assertEquals("interpolate failed simple placeholder", + expected_out, + actual_out); + + HashMap vars = new HashMap(); + vars.put("bar", "eek"); + vars.put("more", "wibble"); + + in = "foo ::bar:: wizz ::more:: done"; + expected_out = "foo eek wizz wibble done"; + actual_out = StringUtils.interpolate(in, vars); + assertEquals("interpolate failed hashmap test", + expected_out, + actual_out); + + } + + @Test + public void testReplace() { + String[] pairs = {null, null, + "foobar", "foobar", + ";foobar", "\\;foobar", + ";foo;bar;baz", "\\;foo\\;bar\\;baz", + ";;foobar", "\\;\\;foobar", + "f;o;obar", "f\\;o\\;obar", + "f;o;;bar", "f\\;o\\;\\;bar", + "foobar;", "foobar\\;", + "foobar;;", "foobar\\;\\;"}; + + for (int ii = 0, jj = 1; jj < pairs.length; ii += 2, jj += 2) { + System.err.println("ii=" + ii + ", pairs[ii]=" + pairs[ii] + + ", jj=" + jj + ", pairs[jj]=" + pairs[jj]); + String expected = pairs[jj]; + String actual = StringUtils.replace(pairs[ii], ";", "\\;"); + assertEquals(expected, actual); + + expected = pairs[ii]; + actual = StringUtils.replace(pairs[jj], "\\;", ";"); + assertEquals(expected, actual); + } + } + + @Test + public void testUrlize() { + assertEquals(null, StringUtils.urlize(null)); + assertEquals("", StringUtils.urlize("")); + assertEquals("-", StringUtils.urlize(" ")); + assertEquals("----", StringUtils.urlize(" ")); + assertEquals("abc-def", StringUtils.urlize("ABC DEF")); + assertEquals("-abc-def-", StringUtils.urlize(" ABC DEF ")); + assertEquals("0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz-_---", StringUtils.urlize("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_ &/")); + assertEquals("helpaplawsorg", StringUtils.urlize("help@aplaws.org")); + } + + @Test + public void testIsAlphaNumeric() { + assertTrue(StringUtils.isAlphaNumeric("foo")); + assertTrue(StringUtils.isAlphaNumeric("123")); + assertTrue(StringUtils.isAlphaNumeric("bar778")); + + assertFalse(StringUtils.isAlphaNumeric("foo/bar")); + assertFalse(StringUtils.isAlphaNumeric("&")); + } + + @Test + public void testTruncateString() { + assertThat(StringUtils.truncateString("Lorem ipsum dolor sit amet", 8, true), is("Lorem")); + assertThat(StringUtils.truncateString("Lorem ipsum dolor sit amet", 2, true), is("Lo")); + assertThat(StringUtils.truncateString(null, 2, true), is("")); + assertThat(StringUtils.truncateString("Lorem ipsum dolor sit amet", 12, true), is("Lorem")); + assertThat(StringUtils.truncateString("Lorem ipsum dolor sit amet", 12, false), is("Lorem ")); + assertThat(StringUtils.truncateString("Lorem ipsum dolor sit amet", 99, true), is("Lorem ipsum dolor sit amet")); + } + + @Test + public void testJoinElements() { + + List input = new ArrayList<>(); + input.add("foo"); + input.add("bar"); + input.add("Qux"); + String expected = "foo,bar,Qux"; + String found = StringUtils.join(input, ","); + String errMsg = "join Elements, expected = " + expected + + " found = " + found; + assertEquals(errMsg, expected, found); + } + + @Test(expected = NullPointerException.class) + public void testIfGetStackTraceFails() { + StringUtils.getStackTrace(null); + } + + @Test + public void testStripNewLines() { + + assertEquals(StringUtils.stripNewLines("line1\nline2"), "line1line2"); + assertEquals(StringUtils.stripNewLines("Lorem ipsum dolor sit amet"), "Lorem ipsum dolor sit amet"); + } + + @Test + public void testNullToEmptyString() { + assertEquals(StringUtils.nullToEmptyString(null), ""); + assertEquals(StringUtils.nullToEmptyString("foo"), "foo"); + } + + @Test + + public void testTextToHtml() { + + assertEquals(StringUtils.textToHtml("line1\nline2"), "line1
line2"); + assertEquals(StringUtils.textToHtml("line1\n\nline2"), "line1

line2"); + } +}