package com.github.droidfu.support; import java.util.ArrayList; import android.text.TextUtils; // contains code from the Apache Software foundation public class StringSupport { /** * Turns a camel case string into an underscored one, e.g. "HelloWorld" * becomes "hello_world". * * @param camelCaseString * the string to underscore * @return the underscored string */ public static String underscore(String camelCaseString) { String[] words = splitByCharacterTypeCamelCase(camelCaseString); return TextUtils.join("_", words).toLowerCase(); } /** * <p> * Splits a String by Character type as returned by * <code>java.lang.Character.getType(char)</code>. Groups of contiguous * characters of the same type are returned as complete tokens, with the * following exception: the character of type * <code>Character.UPPERCASE_LETTER</code>, if any, immediately preceding a * token of type <code>Character.LOWERCASE_LETTER</code> will belong to the * following token rather than to the preceding, if any, * <code>Character.UPPERCASE_LETTER</code> token. * * <pre> * StringUtils.splitByCharacterTypeCamelCase(null) = null * StringUtils.splitByCharacterTypeCamelCase("") = [] * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"] * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"] * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"] * StringUtils.splitByCharacterTypeCamelCase("number5") = ["number", "5"] * StringUtils.splitByCharacterTypeCamelCase("fooBar") = ["foo", "Bar"] * StringUtils.splitByCharacterTypeCamelCase("foo200Bar") = ["foo", "200", "Bar"] * StringUtils.splitByCharacterTypeCamelCase("ASFRules") = ["ASF", "Rules"] * </pre> * * @param str * the String to split, may be <code>null</code> * @return an array of parsed Strings, <code>null</code> if null String * input * @since 2.4 */ public static String[] splitByCharacterTypeCamelCase(String str) { return splitByCharacterType(str, true); } /** * <p> * Splits a String by Character type as returned by * <code>java.lang.Character.getType(char)</code>. Groups of contiguous * characters of the same type are returned as complete tokens, with the * following exception: if <code>camelCase</code> is <code>true</code>, the * character of type <code>Character.UPPERCASE_LETTER</code>, if any, * immediately preceding a token of type * <code>Character.LOWERCASE_LETTER</code> will belong to the following * token rather than to the preceding, if any, * <code>Character.UPPERCASE_LETTER</code> token. * * @param str * the String to split, may be <code>null</code> * @param camelCase * whether to use so-called "camel-case" for letter types * @return an array of parsed Strings, <code>null</code> if null String * input * @since 2.4 */ private static String[] splitByCharacterType(String str, boolean camelCase) { if (str == null) { return null; } if (str.length() == 0) { return new String[0]; } char[] c = str.toCharArray(); ArrayList<String> list = new ArrayList<String>(); int tokenStart = 0; int currentType = Character.getType(c[tokenStart]); for (int pos = tokenStart + 1; pos < c.length; pos++) { int type = Character.getType(c[pos]); if (type == currentType) { continue; } if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) { int newTokenStart = pos - 1; if (newTokenStart != tokenStart) { list.add(new String(c, tokenStart, newTokenStart - tokenStart)); tokenStart = newTokenStart; } } else { list.add(new String(c, tokenStart, pos - tokenStart)); tokenStart = pos; } currentType = type; } list.add(new String(c, tokenStart, c.length - tokenStart)); return (String[]) list.toArray(new String[list.size()]); } }