diff --git a/src/main/java/org/apache/commons/text/CaseUtils.java b/src/main/java/org/apache/commons/text/CaseUtils.java
index c3a7591a38..bb439d7690 100644
--- a/src/main/java/org/apache/commons/text/CaseUtils.java
+++ b/src/main/java/org/apache/commons/text/CaseUtils.java
@@ -16,10 +16,10 @@
*/
package org.apache.commons.text;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.regex.Pattern;
import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
/**
@@ -28,13 +28,51 @@
*
This class tries to handle {@code null} input gracefully.
* An exception will not be thrown for a {@code null} input.
* Each method documents its behavior in more detail.
+ * Examples:
+ *
+ * "Two words" "foo bar" "Piñata Café"
+ * camelCase toCamelCase(str) "twoWords" "fooBar" "pinataCafe"
+ * camelCase toCamelCase(str, false, " ") "twoWords" "fooBar" "piñataCafé"
+ * camel_Snake toDelimitedCase(str, false, '_') "two_Words" "foo_Bar" "pinata_Cafe"
+ * flatcase toPascalCase(str).toLowerCase() "twowords" "foobar" "pinatacafe"
+ * kebab-case toKebabCase(str) "two-words" "foo-bar" "pinata-cafe"
+ * PascalCase toPascalCase(str) "TwoWords" "FooBar" "PinataCafe"
+ * PascalCase toCamelCase(str, true, " ") "TwoWords" "FooBar" "PiñataCafé"
+ * SCREAMINGCASE toPascalCase(str).toUpperCase() "TWOWORDS" "FOOBAR" "PINATACAFE"
+ * SCREAMING-KEBAB toDelimitedCase(str, '-').toUpperCase() "TWO-WORDS" "FOO-BAR" "PINATA-CAFE"
+ * SCREAMING_SNAKE toDelimitedCase(str, '_').toUpperCase() "TWO_WORDS" "FOO_BAR" "PINATA_CAFE"
+ * snake_case toSnakeCase(str) "two_words" "foo_bar" "pinata_cafe"
+ * Title_Case toDelimitedCase(str, '_') "Two_Words" "Foo_Bar" "Pinata_Cafe"
+ * Train-Case toDelimitedCase(str, '-') "Two-Words" "Foo-Bar" "Pinata-Cafe"
+ *
+ *
+ * Note: Examples with {@code toUpperCase()} and {@code toLowerCase()} may be replaced with
+ * {@code StringUtils.upperCase(str)} or {@code StringUtils.lowerCase(str)} to be null-safe.
*
* @since 1.2
*/
public class CaseUtils {
/**
- * Converts all the delimiter separated words in a String into camelCase,
+ * All lower ASCII alphanumeric characters.
+ */
+ private static final Pattern ALPHANUMERIC = Pattern.compile("[0-9A-Za-z]");
+
+ /**
+ * All lower ASCII alphanumeric characters, single quote, and right single "curly" quote (\u2019).
+ */
+ private static final Pattern ALPHANUMERIC_WITH_APOSTROPHE = Pattern.compile("[0-9A-Za-z'\u2019]");
+
+ /**
+ * All characters not included in ALPHANUMERIC
+ */
+ private static final Pattern NON_ALPHANUMERIC = Pattern.compile("^[^0-9A-Za-z]*$");
+
+ private static final Pattern O_IRISH = Pattern.compile("(O')|(O\u2019)");
+
+
+ /**
+ * Converts all the delimiter-separated words in a String into camelCase,
* that is each word is made up of a title case character and then a series of
* lowercase characters.
*
@@ -46,7 +84,7 @@ public class CaseUtils {
* A {@code null} input String returns {@code null}.
*
* A input string with only delimiter characters returns {@code ""}.
- *
+ *
* Capitalization uses the Unicode title case, normally equivalent to
* upper case and cannot perform locale-sensitive mappings.
*
@@ -61,59 +99,214 @@ public class CaseUtils {
* CaseUtils.toCamelCase(" @", false, new char[]{'@'}) = ""
*
*
- * @param str the String to be converted to camelCase, may be null
- * @param capitalizeFirstLetter boolean that determines if the first character of first word should be title case.
- * @param delimiters set of characters to determine capitalization, null and/or empty array means whitespace
+ * @param str the String to be converted to camelCase, may be null
+ * @param capitalizeFirstLetter boolean. If true, set the first character of the first word to title case.
+ * @param delimiters set of characters to determine capitalization, null and/or empty array means whitespace
* @return camelCase of String, {@code null} if null String input
*/
- public static String toCamelCase(String str, final boolean capitalizeFirstLetter, final char... delimiters) {
+ public static String toCamelCase(String str, final Boolean capitalizeFirstLetter, char... delimiters) {
if (StringUtils.isEmpty(str)) {
return str;
}
- str = str.toLowerCase();
- final int strLen = str.length();
- final int[] newCodePoints = new int[strLen];
- int outOffset = 0;
- final Set delimiterSet = toDelimiterSet(delimiters);
- boolean capitalizeNext = capitalizeFirstLetter;
- for (int index = 0; index < strLen;) {
- final int codePoint = str.codePointAt(index);
-
- if (delimiterSet.contains(codePoint)) {
- capitalizeNext = outOffset != 0;
- index += Character.charCount(codePoint);
- } else if (capitalizeNext || outOffset == 0 && capitalizeFirstLetter) {
- final int titleCaseCodePoint = Character.toTitleCase(codePoint);
- newCodePoints[outOffset++] = titleCaseCodePoint;
- index += Character.charCount(titleCaseCodePoint);
- capitalizeNext = false;
+ boolean capitalizeFirst = BooleanUtils.isTrue(capitalizeFirstLetter);
+ if (ArrayUtils.isEmpty(delimiters)) {
+ delimiters = new char[]{' '};
+ }
+ // The delimiter array in text.WordUtils.capitalize(String, char[]) is not working properly
+ // in the current (1.12) build.
+ // The following loop is a temporary fix.
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < str.length(); i++) {
+ if (str.charAt(i) != ' ' && ArrayUtils.contains(delimiters, str.charAt(i))) {
+ sb.append(' ');
} else {
- newCodePoints[outOffset++] = codePoint;
- index += Character.charCount(codePoint);
+ int codepoint = str.codePointAt(i);
+ sb.append(Character.toChars(Character.toLowerCase(codepoint)));
}
}
+ str = sb.toString();
+ delimiters = new char[]{' '};
+ // End temporary fix.
+ if (capitalizeFirst) {
+ return StringUtils.deleteWhitespace(WordUtils.capitalize(str, delimiters));
+ } else {
+ return WordUtils.uncapitalize(StringUtils.deleteWhitespace(WordUtils.capitalize(str, delimiters)));
+ }
+ }
- return new String(newCodePoints, 0, outOffset);
+ /**
+ * Uses {@code toDelimitedCase()} to convert a string to camelCase.
+ * This method has different behavior from {@link #toCamelCase(String, Boolean, char[])}
+ * because all accented characters are normalized (accents removed).
+ * For example, {@code toCamelCase("Piñata Café")} will return {@code "pinataCafe"}, where
+ * {@code toCamelCase("Piñata Café", false, " ")} will return {@code "piñataCafé"}.
+ * Converts the first alphanumeric character of the string to lower case.
+ * Capitalizes first character of all other alphanumeric sequences.
+ * Converts all other characters in the sequence to lower case.
+ * Strips all non-alphanumeric characters or sequences of non-alphanumeric characters
+ * from the beginning and end of the string.
+ * Deletes all other non-alphanumeric characters or sequences of non-alphanumeric characters.
+ *
+ * @param str The text to convert.
+ * @return The convertedText.
+ * @see #toCamelCase(String, Boolean, char[])
+ * @see #toDelimitedCase(String, Boolean, Character)
+ */
+ public static String toCamelCase(String str) {
+ return StringUtils.deleteWhitespace(toDelimitedCase(str, false, ' '));
}
/**
- * Converts an array of delimiters to a hash set of code points. Code point of space(32) is added
- * as the default value. The generated hash set provides O(1) lookup time.
+ * Converts a string to Delimited Case.
+ * This is identical to using {@code toDelimitedCase(str, true, separator);}
+ * Normalizes accented characters (removes accents).
+ * Capitalizes the first character of any alphanumeric sequence.
+ * Converts the rest of the characters in the sequence to lower case
+ * Strips all non-alphanumeric characters or sequences of non-alphanumeric characters
+ * from the beginning and end of the string.
+ * Converts all other non-alphanumeric characters or sequences of non-alphanumeric characters
+ * to the separator delimiter.
*
- * @param delimiters set of characters to determine capitalization, null means whitespace
- * @return Set
+ * @param str String: the text to convert.
+ * @param separator char: The separator to use as a delimiter.
+ * @return The Converted_Text.
*/
- private static Set toDelimiterSet(final char[] delimiters) {
- final Set delimiterHashSet = new HashSet<>();
- delimiterHashSet.add(Character.codePointAt(new char[]{' '}, 0));
- if (ArrayUtils.isEmpty(delimiters)) {
- return delimiterHashSet;
+ public static String toDelimitedCase(String str, Character separator) {
+ return toDelimitedCase(str, true, separator);
+ }
+
+ /**
+ * Converts a string to Delimited Case.
+ * Normalizes accented characters (removes accents).
+ * If {@code capitalizeFirstLetter} is {@code true}, capitalizes the first character of the string.
+ * Otherwise, converts the first character of the string to lower case.
+ * Capitalizes the first character of any other alphanumeric sequence.
+ * Converts the rest of the characters in the sequence to lower case
+ * Strips all non-alphanumeric characters or sequences of non-alphanumeric characters
+ * from the beginning and end of the string.
+ * Converts all other non-alphanumeric characters or sequences of non-alphanumeric characters
+ * to the separator delimiter.
+ *
+ * @param str String: the text to convert.
+ * @param capitalizeFirstLetter boolean: If false, converts the first character of the string to lower case.
+ * @param separator char: The separator to use as a delimiter.
+ * @return The Converted_Text.
+ */
+ public static String toDelimitedCase(String str, final Boolean capitalizeFirstLetter, Character separator) {
+ // This method sanitizes the input to run through toDelimitedEngine().
+ if (StringUtils.isEmpty(str)) {
+ return str;
+ }
+ boolean capitalizeFirst = BooleanUtils.isNotFalse(capitalizeFirstLetter);
+ if (separator == null) {
+ if (capitalizeFirst) {
+ return toPascalCase(str);
+ } else {
+ return toCamelCase(str);
+ }
+ }
+ // return STRIP_ACCENTS_PATTERN.matcher(decomposed).replaceAll(EMPTY);
+ String normalized = O_IRISH.matcher(StringUtils.stripAccents(str).trim()).replaceAll("O ");
+ if (NON_ALPHANUMERIC.matcher(normalized).matches()) {
+ return "";
+ }
+ int startIndex = 0;
+ for (int i = 0; i < normalized.length(); i++) {
+ if (ALPHANUMERIC.matcher(Character.toString(normalized.charAt(i))).matches()) {
+ startIndex = i;
+ break;
+ }
}
- for (int index = 0; index < delimiters.length; index++) {
- delimiterHashSet.add(Character.codePointAt(delimiters, index));
+ return toDelimitedEngine(normalized, capitalizeFirst, separator, startIndex);
+ }
+
+ /**
+ * This is the engine that generates the return value of {@link #toDelimitedCase(String, Boolean, Character)}
+ *
+ * @param normalized String: the sanitized and normalized text to convert.
+ * @param capitalizeFirst boolean: If false, converts the first character of the string to lower case.
+ * @param separator char: The separator to use as a delimiter.
+ * @param startIndex int: The index of the first alphanumeric character.
+ * @return The Converted_Text.
+ */
+ private static String toDelimitedEngine(String normalized, boolean capitalizeFirst, char separator, int startIndex) {
+ StringBuilder delimited = new StringBuilder();
+ for (int i = startIndex; i < normalized.length(); i++) {
+ if (i > startIndex &&
+ !ALPHANUMERIC_WITH_APOSTROPHE.matcher(Character.toString(normalized.charAt(i))).matches()) {
+ if (delimited.charAt(delimited.length() - 1) != separator) {
+ delimited.append(separator);
+ }
+ } else if (normalized.charAt(i) != '\'' && normalized.charAt(i) != '\u2019') {
+ if (i == startIndex && capitalizeFirst) {
+ delimited.append(Character.toUpperCase(normalized.charAt(i)));
+ } else if (i != startIndex && delimited.charAt(delimited.length() - 1) == separator) {
+ delimited.append(Character.toUpperCase(normalized.charAt(i)));
+ } else {
+ delimited.append(Character.toLowerCase(normalized.charAt(i)));
+ }
+ }
+ }
+ if (delimited.charAt(delimited.length() - 1) == separator) {
+ delimited.deleteCharAt(delimited.length() - 1);
}
- return delimiterHashSet;
+
+ return delimited.toString();
+ }
+
+ /**
+ * Uses {@code toDelimitedCase()} to convert a string to kebab-case.
+ * Normalizes accented characters (removes accents).
+ * Converts all alphanumeric characters to lower case.
+ * Strips all non-alphanumeric characters or sequences of non-alphanumeric characters
+ * from the beginning and end of the string.
+ * Converts all other non-alphanumeric characters or sequences of non-alphanumeric characters
+ * to a single hyphen ('-').
+ *
+ * @param str The text to convert.
+ * @return The converted-text.
+ * @see #toDelimitedCase(String, Character)
+ * @see StringUtils#lowerCase(String)
+ */
+ public static String toKebabCase(String str) {
+ return StringUtils.lowerCase(toDelimitedCase(str, '-'));
+ }
+
+ /**
+ * Uses {@code toDelimitedCase()} to convert a string to UpperCamelCase.
+ * Normalizes accented characters (removes accents).
+ * Capitalizes The first character of any alphanumeric sequence.
+ * Converts the rest of the characters in the sequence to lower case
+ * Strips all non-alphanumeric characters or sequences of non-alphanumeric characters
+ * from the beginning and end of the string.
+ * Deletes all other non-alphanumeric characters or sequences of non-alphanumeric characters.
+ *
+ * @param str The text to convert.
+ * @return The ConvertedText.
+ * @see #toDelimitedCase(String, Character)
+ * @see StringUtils#deleteWhitespace(String)
+ */
+ public static String toPascalCase(String str) {
+ return StringUtils.deleteWhitespace(toDelimitedCase(str, ' '));
+ }
+
+ /**
+ * Uses {@code toDelimitedCase()} to convert a string to snake_case.
+ * Normalizes accented characters (removes accents).
+ * Converts all alphanumeric characters to lower case.
+ * Strips all non-alphanumeric characters or sequences of non-alphanumeric characters
+ * from the beginning and end of the string.
+ * Converts all other non-alphanumeric characters or sequences of non-alphanumeric characters
+ * to a single underscore ('_').
+ *
+ * @param str The text to convert.
+ * @return The converted_text.
+ * @see #toDelimitedCase(String, Character)
+ * @see StringUtils#lowerCase(String)
+ */
+ public static String toSnakeCase(String str) {
+ return StringUtils.lowerCase(toDelimitedCase(str, '_'));
}
/**
@@ -127,4 +320,3 @@ private static Set toDelimiterSet(final char[] delimiters) {
public CaseUtils() {
}
}
-
diff --git a/src/test/java/org/apache/commons/text/CaseUtilsTest.java b/src/test/java/org/apache/commons/text/CaseUtilsTest.java
index f7195e708c..ec8890b03f 100644
--- a/src/test/java/org/apache/commons/text/CaseUtilsTest.java
+++ b/src/test/java/org/apache/commons/text/CaseUtilsTest.java
@@ -43,34 +43,281 @@ public void testToCamelCase() {
assertThat(CaseUtils.toCamelCase(null, false, null)).isNull();
assertThat(CaseUtils.toCamelCase("", true, null)).isEqualTo("");
assertThat(CaseUtils.toCamelCase(" ", false, null)).isEqualTo("");
- assertThat(CaseUtils.toCamelCase("a b c @def", false, null)).isEqualTo("aBC@def");
+ assertThat(CaseUtils.toCamelCase("a b c @def", false, null))
+ .isEqualTo("aBC@def");
assertThat(CaseUtils.toCamelCase("a b c @def", true)).isEqualTo("ABC@def");
- assertThat(CaseUtils.toCamelCase("a b c @def", true, '-')).isEqualTo("ABC@def");
- assertThat(CaseUtils.toCamelCase("a b c @def", true, '-')).isEqualTo("ABC@def");
+ assertThat(CaseUtils.toCamelCase("a b c @def", true, '-'))
+ .isEqualTo("ABC@def");
+ assertThat(CaseUtils.toCamelCase("a b c @def", true, '-'))
+ .isEqualTo("ABC@def");
final char[] chars = {'-', '+', ' ', '@'};
assertThat(CaseUtils.toCamelCase("-+@ ", true, chars)).isEqualTo("");
- assertThat(CaseUtils.toCamelCase(" to-CAMEL-cASE", false, chars)).isEqualTo("toCamelCase");
- assertThat(CaseUtils.toCamelCase("@@@@ to+CAMEL@cASE ", true, chars)).isEqualTo("ToCamelCase");
- assertThat(CaseUtils.toCamelCase("To+CA+ME L@cASE", true, chars)).isEqualTo("ToCaMeLCase");
-
- assertThat(CaseUtils.toCamelCase("To.Camel.Case", false, '.')).isEqualTo("toCamelCase");
- assertThat(CaseUtils.toCamelCase("To.Camel-Case", false, '-', '.')).isEqualTo("toCamelCase");
- assertThat(CaseUtils.toCamelCase(" to @ Camel case", false, '-', '@')).isEqualTo("toCamelCase");
- assertThat(CaseUtils.toCamelCase(" @to @ Camel case", true, '-', '@')).isEqualTo("ToCamelCase");
-
- assertThat(CaseUtils.toCamelCase("TO CAMEL CASE", true, null)).isEqualTo("ToCamelCase");
- assertThat(CaseUtils.toCamelCase("TO CAMEL CASE", false, null)).isEqualTo("toCamelCase");
- assertThat(CaseUtils.toCamelCase("TO CAMEL CASE", false, null)).isEqualTo("toCamelCase");
- assertThat(CaseUtils.toCamelCase("tocamelcase", false, null)).isEqualTo("tocamelcase");
- assertThat(CaseUtils.toCamelCase("tocamelcase", true, null)).isEqualTo("Tocamelcase");
- assertThat(CaseUtils.toCamelCase("Tocamelcase", false, null)).isEqualTo("tocamelcase");
+ assertThat(CaseUtils.toCamelCase(" to-CAMEL-cASE", false, chars))
+ .isEqualTo("toCamelCase");
+ assertThat(CaseUtils.toCamelCase("@@@@ to+CAMEL@cASE ", true, chars))
+ .isEqualTo("ToCamelCase");
+ assertThat(CaseUtils.toCamelCase("To+CA+ME L@cASE", true, chars))
+ .isEqualTo("ToCaMeLCase");
+
+ assertThat(CaseUtils.toCamelCase("To.Camel.Case", false, '.'))
+ .isEqualTo("toCamelCase");
+ assertThat(CaseUtils.toCamelCase("To.Camel-Case", false, '-', '.'))
+ .isEqualTo("toCamelCase");
+ assertThat(CaseUtils.toCamelCase(" to @ Camel case", false, '-', '@'))
+ .isEqualTo("toCamelCase");
+ assertThat(CaseUtils.toCamelCase(" @to @ Camel case", true, '-', '@'))
+ .isEqualTo("ToCamelCase");
+
+ assertThat(CaseUtils.toCamelCase("TO CAMEL CASE", true, null))
+ .isEqualTo("ToCamelCase");
+ assertThat(CaseUtils.toCamelCase("TO CAMEL CASE", false, null))
+ .isEqualTo("toCamelCase");
+ assertThat(CaseUtils.toCamelCase("TO CAMEL CASE", false, null))
+ .isEqualTo("toCamelCase");
+ assertThat(CaseUtils.toCamelCase("tocamelcase", false, null))
+ .isEqualTo("tocamelcase");
+ assertThat(CaseUtils.toCamelCase("tocamelcase", true, null))
+ .isEqualTo("Tocamelcase");
+ assertThat(CaseUtils.toCamelCase("Tocamelcase", false, null))
+ .isEqualTo("tocamelcase");
assertThat(CaseUtils.toCamelCase("tocamelcase", true)).isEqualTo("Tocamelcase");
assertThat(CaseUtils.toCamelCase("tocamelcase", false)).isEqualTo("tocamelcase");
- assertThat(CaseUtils.toCamelCase("\uD800\uDF00 \uD800\uDF02", true)).isEqualTo("\uD800\uDF00\uD800\uDF02");
- assertThat(CaseUtils.toCamelCase("\uD800\uDF00\uD800\uDF01\uD800\uDF14\uD800\uDF02\uD800\uDF03", true, '\uD800',
- '\uDF14')).isEqualTo("\uD800\uDF00\uD800\uDF01\uD800\uDF02\uD800\uDF03");
+// // These tests fail the new toCamelCase(String, Boolean, char[]) method because
+// // surrogate pairs \uD800 to \uDFFF have been removed from the Unicode Character Set.
+// assertThat(CaseUtils.toCamelCase("\uD800\uDF00 \uD800\uDF02", true)).isEqualTo("\uD800\uDF00\uD800\uDF02");
+// assertThat(CaseUtils.toCamelCase("\uD800\uDF00\uD800\uDF01\uD800\uDF14\uD800\uDF02\uD800\uDF03", true, '\uD800',
+// '\uDF14')).isEqualTo("\uD800\uDF00\uD800\uDF01\uD800\uDF02\uD800\uDF03");
+
+ /* **** NEW TESTS **** */
+
+ assertThat(CaseUtils.toCamelCase("The café\u2019s piñata gave me déjà vu.",
+ false, ' ', '.')).isEqualTo("theCafé\u2019sPiñataGaveMeDéjàVu");
+
+ assertThat(CaseUtils.toCamelCase(null)).isNull();
+ assertThat(CaseUtils.toCamelCase("")).isEqualTo("");
+ assertThat(CaseUtils.toCamelCase(" ")).isEqualTo("");
+ assertThat(CaseUtils.toCamelCase("a b c @def")).isEqualTo("aBCDef");
+ assertThat(CaseUtils.toCamelCase("a b c @def")).isEqualTo("aBCDef");
+
+ assertThat(CaseUtils.toCamelCase("-+@ ")).isEqualTo("");
+ assertThat(CaseUtils.toCamelCase(" to-CAMEL-cASE")).isEqualTo("toCamelCase");
+ assertThat(CaseUtils.toCamelCase("@@@@ to+CAMEL@cASE ")).isEqualTo("toCamelCase");
+ assertThat(CaseUtils.toCamelCase("To+CA+ME L@cASE")).isEqualTo("toCaMeLCase");
+
+ assertThat(CaseUtils.toCamelCase("To.Camel.Case")).isEqualTo("toCamelCase");
+ assertThat(CaseUtils.toCamelCase("To.Camel-Case")).isEqualTo("toCamelCase");
+ assertThat(CaseUtils.toCamelCase(" to @ Camel case")).isEqualTo("toCamelCase");
+ assertThat(CaseUtils.toCamelCase(" @to @ Camel case_")).isEqualTo("toCamelCase");
+
+ assertThat(CaseUtils.toCamelCase("TO CAMEL CASE")).isEqualTo("toCamelCase");
+ assertThat(CaseUtils.toCamelCase("tocamelcase")).isEqualTo("tocamelcase");
+
+ assertThat(CaseUtils.toCamelCase("\uD800\uDF00\uD800\uDF01\uD800\uDF14\uD800\uDF02\uD800\uDF03"))
+ .isEqualTo("");
+
+ assertThat(CaseUtils.toCamelCase("The café\u2019s piñata gave me déjà vu."))
+ .isEqualTo("theCafesPinataGaveMeDejaVu");
+ assertThat(CaseUtils.toCamelCase("\u1E70\u01EB \u010C\u0227\u1E41\u0113\u0142 \u010D\u1E01\u0219\u1E1B"))
+ .isEqualTo("toCamelCase");
+ }
+
+ @Test
+ public void testToDelimitedCase() {
+ assertThat(CaseUtils.toDelimitedCase(null, null)).isNull();
+ assertThat(CaseUtils.toDelimitedCase(null, null, null)).isNull();
+ assertThat(CaseUtils.toDelimitedCase("", ' ')).isEqualTo("");
+ assertThat(CaseUtils.toDelimitedCase(" ", ' ')).isEqualTo("");
+ assertThat(CaseUtils.toDelimitedCase("a b c @def", '_')).isEqualTo("A_B_C_Def");
+ assertThat(CaseUtils.toDelimitedCase("a b c @def", '-')).isEqualTo("A-B-C-Def");
+ assertThat(CaseUtils.toDelimitedCase("a b c @def", true, null))
+ .isEqualTo("ABCDef");
+ assertThat(CaseUtils.toDelimitedCase("a b c @def", false, null))
+ .isEqualTo("aBCDef");
+ assertThat(CaseUtils.toDelimitedCase("a b c @def", null, null))
+ .isEqualTo("ABCDef");
+ assertThat(CaseUtils.toDelimitedCase("a b c @def", null, '_'))
+ .isEqualTo("A_B_C_Def");
+
+ assertThat(CaseUtils.toDelimitedCase("-+@ ", '@')).isEqualTo("");
+
+ assertThat(CaseUtils.toDelimitedCase(" to-Delimited-cASE", '_'))
+ .isEqualTo("To_Delimited_Case");
+ assertThat(CaseUtils.toDelimitedCase("@@@@ to+DELIMITED@cASE ", '_'))
+ .isEqualTo("To_Delimited_Case");
+ assertThat(CaseUtils.toDelimitedCase("To+DELIM+IT ED@cASE", '+'))
+ .isEqualTo("To+Delim+It+Ed+Case");
+
+ assertThat(CaseUtils.toDelimitedCase(" to-Delimited-cASE", false, '_'))
+ .isEqualTo("to_Delimited_Case");
+ assertThat(CaseUtils.toDelimitedCase("@@@@ to+DELIMITED@cASE ", false, '_'))
+ .isEqualTo("to_Delimited_Case");
+ assertThat(CaseUtils.toDelimitedCase("To+DELIM+IT ED@cASE", false, '+'))
+ .isEqualTo("to+Delim+It+Ed+Case");
+
+ assertThat(CaseUtils.toDelimitedCase("To.Delimited.Case", '.'))
+ .isEqualTo("To.Delimited.Case");
+ assertThat(CaseUtils.toDelimitedCase("To.Delimited-Case", '\u2250'))
+ .isEqualTo("To\u2250Delimited\u2250Case");
+ assertThat(CaseUtils.toDelimitedCase(" to @ Delimited case", ' '))
+ .isEqualTo("To Delimited Case");
+ assertThat(CaseUtils.toDelimitedCase(" @to @ Delimited case_", '@'))
+ .isEqualTo("To@Delimited@Case");
+
+ assertThat(CaseUtils.toDelimitedCase("To.Delimited.Case", false, '.'))
+ .isEqualTo("to.Delimited.Case");
+ assertThat(CaseUtils.toDelimitedCase("To.Delimited-Case", false, '\u2250'))
+ .isEqualTo("to\u2250Delimited\u2250Case");
+ assertThat(CaseUtils.toDelimitedCase(" to @ Delimited case", false, ' '))
+ .isEqualTo("to Delimited Case");
+ assertThat(CaseUtils.toDelimitedCase(" @to @ Delimited case_", false, '@'))
+ .isEqualTo("to@Delimited@Case");
+
+ assertThat(CaseUtils.toDelimitedCase("TO DELIMITED CASE", '_'))
+ .isEqualTo("To_Delimited_Case");
+ assertThat(CaseUtils.toDelimitedCase("todelimitedcase", '_'))
+ .isEqualTo("Todelimitedcase");
+
+ assertThat(CaseUtils.toDelimitedCase("\uD800\uDF00\uD800\uDF01\uD800\uDF14\uD800\uDF02\uD800\uDF03",
+ '\uD800')).isEqualTo("");
+
+ assertThat(CaseUtils.toDelimitedCase("The café\u2019s piñata gave me déjà vu.", '_'))
+ .isEqualTo("The_Cafes_Pinata_Gave_Me_Deja_Vu");
+ assertThat(CaseUtils.toDelimitedCase("The café\u2019s piñata gave me déjà vu.",
+ false, '_')).isEqualTo("the_Cafes_Pinata_Gave_Me_Deja_Vu");
+ assertThat(CaseUtils.toDelimitedCase("\u1E12\u0205\u0142\u012B\u1E43\u01D0\u1E6B\u0119\u1E0B " +
+ "\u010D\u1E01\u0219\u1E1B", '_'))
+ .isEqualTo("Delimited_Case");
+
+ assertThat(CaseUtils.toDelimitedCase("Will 'O The Wisp", '-')).isEqualTo("Will-O-The-Wisp");
+
+ assertThat(CaseUtils.toDelimitedCase("\u2026with boughs of holly\u2026\n\u2019Tis the season\u2026",
+ '\u272F'))
+ .isEqualTo("With\u272FBoughs\u272FOf\u272FHolly\u272FTis\u272FThe\u272FSeason");
+ assertThat(CaseUtils.toDelimitedCase("\u2026with boughs of holly\u2026\n\u2019Tis the season\u2026",
+ false,'\u272F'))
+ .isEqualTo("with\u272FBoughs\u272FOf\u272FHolly\u272FTis\u272FThe\u272FSeason");
+
+ assertThat(CaseUtils.toDelimitedCase("\"Officer O'Malley and Peart O'Niel " +
+ "walk into the Protestant's Bar.\"", '_'))
+ .isEqualTo("Officer_O_Malley_And_Peart_O_Niel_Walk_Into_The_Protestants_Bar");
+ }
+
+ @Test
+ public void testToKebabCase() {
+ assertThat(CaseUtils.toKebabCase(null)).isNull();
+ assertThat(CaseUtils.toKebabCase("")).isEqualTo("");
+ assertThat(CaseUtils.toKebabCase(" ")).isEqualTo("");
+ assertThat(CaseUtils.toKebabCase("a b c @def")).isEqualTo("a-b-c-def");
+ assertThat(CaseUtils.toKebabCase("a b c @def")).isEqualTo("a-b-c-def");
+
+ assertThat(CaseUtils.toKebabCase("-+@ ")).isEqualTo("");
+ assertThat(CaseUtils.toKebabCase(" to-KEBAB-cASE")).isEqualTo("to-kebab-case");
+ assertThat(CaseUtils.toKebabCase("@@@@ to+KEBAB@cASE ")).isEqualTo("to-kebab-case");
+ assertThat(CaseUtils.toKebabCase("To+KE+BA B@cASE")).isEqualTo("to-ke-ba-b-case");
+
+ assertThat(CaseUtils.toKebabCase("To.Kebab.Case")).isEqualTo("to-kebab-case");
+ assertThat(CaseUtils.toKebabCase("To.Kebab-Case")).isEqualTo("to-kebab-case");
+ assertThat(CaseUtils.toKebabCase(" to @ Kebab case")).isEqualTo("to-kebab-case");
+ assertThat(CaseUtils.toKebabCase(" @to @ Kebab case_")).isEqualTo("to-kebab-case");
+
+ assertThat(CaseUtils.toKebabCase("TO KEBAB CASE")).isEqualTo("to-kebab-case");
+ assertThat(CaseUtils.toKebabCase("tokebabcase")).isEqualTo("tokebabcase");
+
+ assertThat(CaseUtils.toKebabCase("\uD800\uDF00\uD800\uDF01\uD800\uDF14\uD800\uDF02\uD800\uDF03"))
+ .isEqualTo("");
+
+ assertThat(CaseUtils.toKebabCase("The café\u2019s piñata gave me déjà vu."))
+ .isEqualTo("the-cafes-pinata-gave-me-deja-vu");
+ assertThat(CaseUtils.toKebabCase("\u1E70\u01EB \u1E31\u0115\u1E07\u0227\u1E05 \u010D\u1E01\u0219\u1E1B"))
+ .isEqualTo("to-kebab-case");
+ }
+
+ @Test
+ public void testToPascalCase() {
+ assertThat(CaseUtils.toPascalCase(null)).isNull();
+ assertThat(CaseUtils.toPascalCase("")).isEqualTo("");
+ assertThat(CaseUtils.toPascalCase(" ")).isEqualTo("");
+ assertThat(CaseUtils.toPascalCase("a b c @def")).isEqualTo("ABCDef");
+ assertThat(CaseUtils.toPascalCase("a b c @def")).isEqualTo("ABCDef");
+
+ assertThat(CaseUtils.toPascalCase("-+@ ")).isEqualTo("");
+ assertThat(CaseUtils.toPascalCase(" to-CAMEL-cASE")).isEqualTo("ToCamelCase");
+ assertThat(CaseUtils.toPascalCase("@@@@ to+CAMEL@cASE ")).isEqualTo("ToCamelCase");
+ assertThat(CaseUtils.toPascalCase("To+CA+ME L@cASE")).isEqualTo("ToCaMeLCase");
+
+ assertThat(CaseUtils.toPascalCase("To.Camel.Case")).isEqualTo("ToCamelCase");
+ assertThat(CaseUtils.toPascalCase("To.Camel-Case")).isEqualTo("ToCamelCase");
+ assertThat(CaseUtils.toPascalCase(" to @ Camel case")).isEqualTo("ToCamelCase");
+ assertThat(CaseUtils.toPascalCase(" @to @ Camel case_")).isEqualTo("ToCamelCase");
+
+ assertThat(CaseUtils.toPascalCase("TO CAMEL CASE")).isEqualTo("ToCamelCase");
+ assertThat(CaseUtils.toPascalCase("tocamelcase")).isEqualTo("Tocamelcase");
+
+ assertThat(CaseUtils.toPascalCase("\uD800\uDF00\uD800\uDF01\uD800\uDF14\uD800\uDF02\uD800\uDF03"))
+ .isEqualTo("");
+
+ assertThat(CaseUtils.toPascalCase("The café\u2019s piñata gave me déjà vu."))
+ .isEqualTo("TheCafesPinataGaveMeDejaVu");
+ assertThat(CaseUtils.toPascalCase("\u1E70\u01EB \u010C\u0227\u1E41\u0113\u0142 \u010D\u1E01\u0219\u1E1B"))
+ .isEqualTo("ToCamelCase");
}
+
+ @Test
+ public void testToSnakeCase() {
+ assertThat(CaseUtils.toSnakeCase(null)).isNull();
+ assertThat(CaseUtils.toSnakeCase("")).isEqualTo("");
+ assertThat(CaseUtils.toSnakeCase(" ")).isEqualTo("");
+ assertThat(CaseUtils.toSnakeCase("a b c @def")).isEqualTo("a_b_c_def");
+ assertThat(CaseUtils.toSnakeCase("a b c @def")).isEqualTo("a_b_c_def");
+
+ assertThat(CaseUtils.toSnakeCase("-+@ ")).isEqualTo("");
+ assertThat(CaseUtils.toSnakeCase(" to-SNAKE-cASE")).isEqualTo("to_snake_case");
+ assertThat(CaseUtils.toSnakeCase("@@@@ to+SNAKE@cASE ")).isEqualTo("to_snake_case");
+ assertThat(CaseUtils.toSnakeCase("To+SN+AK E@cASE")).isEqualTo("to_sn_ak_e_case");
+
+ assertThat(CaseUtils.toSnakeCase("To.Snake.Case")).isEqualTo("to_snake_case");
+ assertThat(CaseUtils.toSnakeCase("To.Snake-Case")).isEqualTo("to_snake_case");
+ assertThat(CaseUtils.toSnakeCase(" to @ Snake case")).isEqualTo("to_snake_case");
+ assertThat(CaseUtils.toSnakeCase(" @to @ Snake case_")).isEqualTo("to_snake_case");
+
+ assertThat(CaseUtils.toSnakeCase("TO SNAKE CASE")).isEqualTo("to_snake_case");
+ assertThat(CaseUtils.toSnakeCase("tosnakecase")).isEqualTo("tosnakecase");
+
+ assertThat(CaseUtils.toSnakeCase("\uD800\uDF00\uD800\uDF01\uD800\uDF14\uD800\uDF02\uD800\uDF03"))
+ .isEqualTo("");
+
+ assertThat(CaseUtils.toSnakeCase("The café\u2019s piñata gave me déjà vu."))
+ .isEqualTo("the_cafes_pinata_gave_me_deja_vu");
+ assertThat(CaseUtils.toSnakeCase("\u1E70\u01EB \u1E61\u1E47\u1EA3\u1E31\u1EB9 \u010D\u1E01\u0219\u1E1B"))
+ .isEqualTo("to_snake_case");
+ }
+
+ @Test
+ public void testSeparatedWordFormats() {
+ assertThat(CaseUtils.toCamelCase("Çàmè\u0142 çásé")).isEqualTo("camelCase");
+ assertThat(CaseUtils.toCamelCase("Çàmè\u0142 çásé", false, ' '))
+ .isEqualTo("çàmè\u0142Çásé");
+ assertThat(CaseUtils.toDelimitedCase("Camel snake", false, '_'))
+ .isEqualTo("camel_Snake");
+ assertThat(CaseUtils.toPascalCase("FLAT CASE").toLowerCase()).isEqualTo("flatcase");
+ assertThat(CaseUtils.toKebabCase("Kebab Case")).isEqualTo("kebab-case");
+ assertThat(CaseUtils.toPascalCase("pâsçã\u0142 çäsê")).isEqualTo("PascalCase");
+ assertThat(CaseUtils.toCamelCase("pâsçã\u0142 çäsê", true, ' '))
+ .isEqualTo("Pâsçã\u0142Çäsê");
+ assertThat(CaseUtils.toPascalCase("screaming case").toUpperCase()).isEqualTo("SCREAMINGCASE");
+ assertThat(CaseUtils.toDelimitedCase("screaming KEBAB-CASE", '-').toUpperCase())
+ .isEqualTo("SCREAMING-KEBAB-CASE");
+ assertThat(CaseUtils.toDelimitedCase("SCREAMING snake_case", '_').toUpperCase())
+ .isEqualTo("SCREAMING_SNAKE_CASE");
+ assertThat(CaseUtils.toDelimitedCase("Snake Case", '_').toLowerCase())
+ .isEqualTo("snake_case");
+ assertThat(CaseUtils.toDelimitedCase("title case", true, '_'))
+ .isEqualTo("Title_Case");
+ assertThat(CaseUtils.toDelimitedCase("train case", true, '-'))
+ .isEqualTo("Train-Case");
+ }
+
}