elharo commented on code in PR #450: URL: https://github.com/apache/commons-text/pull/450#discussion_r1376568237
########## src/main/java/org/apache/commons/text/cases/CasesUtils.java: ########## @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.text.cases; + +/** + * Util methods for the Cases API. + */ +public class CasesUtils { Review Comment: CasesUitls --> Cases "Utild" doesn't add much iof anytihng ########## src/main/java/org/apache/commons/text/cases/CharacterDelimitedCase.java: ########## @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.text.cases; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.CharUtils; + +/** + * DelimitedCase is a case in which the true alphabetic case of the characters is ignored by default + * and tokens themselves are determined by the presence of a delimiter between each token. Review Comment: delete "themselves" This is a good description though. It does make me wonder if "Cases" isn't the right language here since as you point out, it's not always about case. Is there a more generic term that can be used for both case and other-than-case delimited strings? ########## src/main/java/org/apache/commons/text/cases/CharacterDelimitedCase.java: ########## @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.text.cases; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.CharUtils; + +/** + * DelimitedCase is a case in which the true alphabetic case of the characters is ignored by default + * and tokens themselves are determined by the presence of a delimiter between each token. + */ +public class CharacterDelimitedCase implements Case { + + /** Delimiters to be used when parsing. */ + private List<Integer> parseDelimiters; + + /** Delimiter to be used when formatting. */ + private String formatDelimiter; + + /** + * Constructs a new Delimited Case with null delimiters. + */ + CharacterDelimitedCase() { + this(null, null); + } + + /** + * Constructs a new Delimited Case. + * + * @param delimiter the character to use as both the parse and format delimiter + */ + CharacterDelimitedCase(char delimiter) { + this(new char[] { delimiter }, CharUtils.toString(delimiter)); + } + + /** + * Constructs a new delimited case. + * + * @param parseDelimiters the array of delimiters to use when parsing + * @param formatDelimiter the delimiter to use when formatting + */ + CharacterDelimitedCase(char[] parseDelimiters, String formatDelimiter) { + super(); + this.parseDelimiters = generateDelimiterList(parseDelimiters); + this.formatDelimiter = formatDelimiter; + } + + /** + * Formats tokens into Delimited Case. + * <p> + * Tokens are iterated on and appended to an output stream, with an instance of a Review Comment: "iterated on" sounds off; maybe just drop it delete instance of. The delimiter might not even be an object. I guess it is a string but then it might not be a single character ########## src/test/java/org/apache/commons/text/cases/CasesTest.java: ########## @@ -0,0 +1,268 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.text.cases; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class CasesTest { + + @Test + public void testCasesUtils() { + Assertions.assertEquals("testUtils", CasesUtils.convert("test-utils", CasesUtils.KEBAB, CasesUtils.CAMEL)); + Assertions.assertEquals("Test_Utils", CasesUtils.convert("TestUtils", CasesUtils.PASCAL, CasesUtils.SNAKE)); + } + + @Test + public void testCharacterDelimitedCase() { + Assertions.assertThrows(IllegalArgumentException.class, () -> KebabCase.INSTANCE.format(Arrays.asList("a", "-"))); + Assertions.assertThrows(IllegalArgumentException.class, () -> SnakeCase.INSTANCE.format(Arrays.asList("a", "_"))); + CharacterDelimitedCase nullDelimiters = new CharacterDelimitedCase(); + assertFormat(nullDelimiters, "abc", Arrays.asList("a", "b", "c")); + assertParse(nullDelimiters, "abc", Arrays.asList("abc")); + } + + @Test + public void testKebabCase() { + assertFormatAndParse(KebabCase.INSTANCE, "", Arrays.asList()); + assertParse(KebabCase.INSTANCE, null, Arrays.asList()); + assertFormatAndParse(KebabCase.INSTANCE, "my-Tokens-123-a1", Arrays.asList("my", "Tokens", "123", "a1")); + assertFormatAndParse(KebabCase.INSTANCE, "blank--token", Arrays.asList("blank", "", "token")); + } + + @Test + public void testUtf32() { + assertFormatAndParse(KebabCase.INSTANCE, "\uD800\uDF00-\uD800\uDF01\uD800\uDF14-\uD800\uDF02\uD800\uDF03", + Arrays.asList("\uD800\uDF00", "\uD800\uDF01\uD800\uDF14", "\uD800\uDF02\uD800\uDF03")); + assertFormatAndParse(SnakeCase.INSTANCE, "\uD800\uDF00_\uD800\uDF01\uD800\uDF14_\uD800\uDF02\uD800\uDF03", + Arrays.asList("\uD800\uDF00", "\uD800\uDF01\uD800\uDF14", "\uD800\uDF02\uD800\uDF03")); + + assertFormatAndParse(PascalCase.INSTANCE, "A\uD800\uDF00B\uD800\uDF01\uD800\uDF14C\uD800\uDF02\uD800\uDF03", + Arrays.asList("A\uD800\uDF00", "B\uD800\uDF01\uD800\uDF14", "C\uD800\uDF02\uD800\uDF03")); + assertFormatAndParse(CamelCase.INSTANCE, "a\uD800\uDF00B\uD800\uDF01\uD800\uDF14C\uD800\uDF02\uD800\uDF03", + Arrays.asList("a\uD800\uDF00", "B\uD800\uDF01\uD800\uDF14", "C\uD800\uDF02\uD800\uDF03")); + + } + + @Test + public void testSnakeCase() { + assertFormatAndParse(SnakeCase.INSTANCE, "", Arrays.asList()); + assertParse(SnakeCase.INSTANCE, null, Arrays.asList()); + assertFormatAndParse(SnakeCase.INSTANCE, "my_Tokens_123_a1", Arrays.asList("my", "Tokens", "123", "a1")); + assertFormatAndParse(SnakeCase.INSTANCE, "blank__token", Arrays.asList("blank", "", "token")); + } + + @Test + public void testPascalCase() { + + assertFormatAndParse(PascalCase.INSTANCE, "MyVarName", Arrays.asList("My", "Var", "Name")); + assertFormatAndParse(PascalCase.INSTANCE, "MyTokensA1D", Arrays.asList("My", "Tokens", "A1", "D")); + assertFormatAndParse(PascalCase.INSTANCE, "", Arrays.asList()); + assertParse(PascalCase.INSTANCE, "lowerFirst", Arrays.asList("lower", "First")); + assertFormat(PascalCase.INSTANCE, "LowerFirst", Arrays.asList("lower", "First")); + + Assertions.assertThrows(IllegalArgumentException.class, () -> PascalCase.INSTANCE.format(Arrays.asList("1"))); + Assertions.assertThrows(IllegalArgumentException.class, () -> PascalCase.INSTANCE.format(Arrays.asList("a1", "2c"))); + Assertions.assertThrows(IllegalArgumentException.class, () -> PascalCase.INSTANCE.format(Arrays.asList("1a"))); + Assertions.assertThrows(IllegalArgumentException.class, () -> PascalCase.INSTANCE.format(Arrays.asList(""))); + } + + @Test + public void testNumberLetters() { + + // roman numerals - have an upper/lower case but are numbers + + assertFormatAndParse(PascalCase.INSTANCE, "A\u2170\u2160c", Arrays.asList("A\u2170", "\u2160c")); + + assertFormat(PascalCase.INSTANCE, "A\u2170Bc", Arrays.asList("a\u2160", "bc")); + assertParse(PascalCase.INSTANCE, "A\u2170Bc", Arrays.asList("A\u2170", "Bc")); + assertFormat(PascalCase.INSTANCE, "A\u2170", Arrays.asList("a\u2170")); + assertParse(PascalCase.INSTANCE, "A\u2170Bc", Arrays.asList("A\u2170", "Bc")); + + assertFormat(CamelCase.INSTANCE, "a\u2170Bc", Arrays.asList("a\u2160", "bc")); + assertParse(CamelCase.INSTANCE, "\u2160Bc", Arrays.asList("\u2160", "Bc")); + + } + + @Test + public void testCamelCase() { + + assertFormatAndParse(CamelCase.INSTANCE, "", Arrays.asList()); + assertFormatAndParse(CamelCase.INSTANCE, "myTokensAbc123", Arrays.asList("my", "Tokens", "Abc123")); + assertFormatAndParse(CamelCase.INSTANCE, "specChar-Token+", Arrays.asList("spec", "Char-", "Token+")); + + assertParse(CamelCase.INSTANCE, "MyTokens", Arrays.asList("My", "Tokens")); + assertFormat(CamelCase.INSTANCE, "myTokens", Arrays.asList("My", "Tokens")); + + // empty token not supported + Assertions.assertThrows(IllegalArgumentException.class, () -> CamelCase.INSTANCE.format(Arrays.asList("a", "b", ""))); + // must begin with character that can be uppercased + Assertions.assertThrows(IllegalArgumentException.class, () -> CamelCase.INSTANCE.format(Arrays.asList("a", "1b"))); + Assertions.assertThrows(IllegalArgumentException.class, () -> CamelCase.INSTANCE.format(Arrays.asList("1a"))); + } + + @Test + public void testConversionsDelimited() { + + List<String> tokens = Arrays.asList("My", "var", "NAME", "mIXED", "a1", "12", ""); + + String kebabString = "My-var-NAME-mIXED-a1-12-"; + assertFormatAndParse(KebabCase.INSTANCE, kebabString, tokens); + + String snakeString = "My_var_NAME_mIXED_a1_12_"; + assertFormatAndParse(SnakeCase.INSTANCE, snakeString, tokens); + } + + @Test + public void testConversions() { + + List<String> tokens = Arrays.asList("My", "var", "NAME", "mIXED", "a1", "c|=+"); Review Comment: These shiould really be separate test methods for easier debugging ########## src/main/java/org/apache/commons/text/cases/CharacterDelimitedCase.java: ########## @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.text.cases; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.CharUtils; + +/** + * DelimitedCase is a case in which the true alphabetic case of the characters is ignored by default + * and tokens themselves are determined by the presence of a delimiter between each token. + */ +public class CharacterDelimitedCase implements Case { + + /** Delimiters to be used when parsing. */ + private List<Integer> parseDelimiters; + + /** Delimiter to be used when formatting. */ + private String formatDelimiter; + + /** + * Constructs a new Delimited Case with null delimiters. + */ + CharacterDelimitedCase() { + this(null, null); + } + + /** + * Constructs a new Delimited Case. + * + * @param delimiter the character to use as both the parse and format delimiter + */ + CharacterDelimitedCase(char delimiter) { + this(new char[] { delimiter }, CharUtils.toString(delimiter)); + } + + /** + * Constructs a new delimited case. + * + * @param parseDelimiters the array of delimiters to use when parsing + * @param formatDelimiter the delimiter to use when formatting + */ + CharacterDelimitedCase(char[] parseDelimiters, String formatDelimiter) { + super(); + this.parseDelimiters = generateDelimiterList(parseDelimiters); + this.formatDelimiter = formatDelimiter; + } + + /** + * Formats tokens into Delimited Case. + * <p> + * Tokens are iterated on and appended to an output stream, with an instance of a + * delimiter character between them. This method validates that the delimiter character is not + * part of the token. If it is found within the token an exception is thrown.<br> + * No other restrictions are placed on the contents of the tokens. + * Note: This Case does support empty tokens.<br> + * </p> + * + * @param tokens the tokens to be formatted into a delimited string + * @return the delimited string + * @throws IllegalArgumentException if any tokens contain the delimiter character + */ + @Override + public String format(Iterable<String> tokens) { + StringBuilder formattedString = new StringBuilder(); + int i = 0; + for (String token : tokens) { + if (formatDelimiter != null) { + int delimiterFoundIndex = token.indexOf(formatDelimiter); + if (delimiterFoundIndex > -1) { + throw new IllegalArgumentException("Token " + i + " contains delimiter character '" + formatDelimiter + "' at index " + delimiterFoundIndex); + } + if (i > 0) { + formattedString.append(formatDelimiter); + } + } + i++; + formattedString.append(token); + } + return formattedString.toString(); + } + + /** + * Parses delimited string into tokens. + * <p> + * Input string is parsed one character at a time until a delimiter character is reached. Review Comment: delimiter chaarcter or string? ########## src/main/java/org/apache/commons/text/cases/CharacterDelimitedCase.java: ########## @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.text.cases; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.CharUtils; + +/** + * DelimitedCase is a case in which the true alphabetic case of the characters is ignored by default Review Comment: comma after default ########## src/main/java/org/apache/commons/text/cases/Case.java: ########## @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.text.cases; + +import java.util.List; + +/** + * Formats and parses tokens to/from a String. In most implementations tokens returned + * by the parse method abide by any restrictions present in the format method. That is, calling + * format() with the results of a call to parse() on the same Case instance should return a + * matching String. + * + * @since 1.11 + */ +public interface Case { + + /** + * Formats a set of tokens into a string. The tokens do not necessarily have to meet the syntax + * requirements of the Case. The documentation for each implementation should specify what input + * is supported. + * + * @param tokens string tokens to be formatted by this Case + * @return the formatted string + * @throws IllegalArgumentException if tokens cannot be formatted + */ + String format(Iterable<String> tokens); + + /** + * Parses a string into a series of tokens. The string must abide by certain restrictions, + * dependent on each Case implementation. + * + * @param string the string to be parsed by this Case into a list of tokens + * @return the list of parsed tokens + * @throws IllegalArgumentException if the string cannot be parsed Review Comment: cannot be parsed --> cannot be parsed in the specific format (or something likle that; I don't have the exact words yet but I'd like to get the notion of the grammar in there somehow) ########## src/main/java/org/apache/commons/text/cases/CharacterDelimitedCase.java: ########## @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.text.cases; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.CharUtils; + +/** + * DelimitedCase is a case in which the true alphabetic case of the characters is ignored by default + * and tokens themselves are determined by the presence of a delimiter between each token. + */ +public class CharacterDelimitedCase implements Case { + + /** Delimiters to be used when parsing. */ + private List<Integer> parseDelimiters; + + /** Delimiter to be used when formatting. */ + private String formatDelimiter; + + /** + * Constructs a new Delimited Case with null delimiters. + */ + CharacterDelimitedCase() { + this(null, null); + } + + /** + * Constructs a new Delimited Case. + * + * @param delimiter the character to use as both the parse and format delimiter + */ + CharacterDelimitedCase(char delimiter) { + this(new char[] { delimiter }, CharUtils.toString(delimiter)); + } + + /** + * Constructs a new delimited case. + * + * @param parseDelimiters the array of delimiters to use when parsing + * @param formatDelimiter the delimiter to use when formatting + */ + CharacterDelimitedCase(char[] parseDelimiters, String formatDelimiter) { + super(); + this.parseDelimiters = generateDelimiterList(parseDelimiters); + this.formatDelimiter = formatDelimiter; + } + + /** + * Formats tokens into Delimited Case. + * <p> + * Tokens are iterated on and appended to an output stream, with an instance of a + * delimiter character between them. This method validates that the delimiter character is not + * part of the token. If it is found within the token an exception is thrown.<br> + * No other restrictions are placed on the contents of the tokens. + * Note: This Case does support empty tokens.<br> + * </p> + * + * @param tokens the tokens to be formatted into a delimited string + * @return the delimited string + * @throws IllegalArgumentException if any tokens contain the delimiter character + */ + @Override + public String format(Iterable<String> tokens) { + StringBuilder formattedString = new StringBuilder(); + int i = 0; + for (String token : tokens) { + if (formatDelimiter != null) { + int delimiterFoundIndex = token.indexOf(formatDelimiter); + if (delimiterFoundIndex > -1) { + throw new IllegalArgumentException("Token " + i + " contains delimiter character '" + formatDelimiter + "' at index " + delimiterFoundIndex); + } + if (i > 0) { + formattedString.append(formatDelimiter); + } + } + i++; + formattedString.append(token); + } + return formattedString.toString(); + } + + /** + * Parses delimited string into tokens. + * <p> + * Input string is parsed one character at a time until a delimiter character is reached. + * When a delimiter character is reached a new token begins. The delimiter character is + * considered reserved, and is omitted from the returned parsed tokens.<br> + * No other restrictions are placed on the contents of the input string. <br> + * </p> + * + * @param string the delimited string to be parsed + * @return the list of tokens found in the string + */ + @Override + public List<String> parse(String string) { + List<String> tokens = new ArrayList<>(); + if (string == null || string.isEmpty()) { + return tokens; + } + int strLen = string.length(); + int[] tokenCodePoints = new int[strLen]; + int tokenCodePointsOffset = 0; + for (int i = 0; i < string.length();) { + final int codePoint = string.codePointAt(i); + if (parseDelimiters.contains(codePoint)) { + tokens.add(new String(tokenCodePoints, 0, tokenCodePointsOffset)); + tokenCodePoints = new int[strLen]; + tokenCodePointsOffset = 0; + i++; + } else { + tokenCodePoints[tokenCodePointsOffset++] = codePoint; + i += Character.charCount(codePoint); + } + } + tokens.add(new String(tokenCodePoints, 0, tokenCodePointsOffset)); + return tokens; + } + + /** + * Converts an array of delimiters to a hash set of code points. Review Comment: has set or list? ########## src/test/java/org/apache/commons/text/cases/CasesTest.java: ########## @@ -0,0 +1,268 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.text.cases; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class CasesTest { + + @Test + public void testCasesUtils() { + Assertions.assertEquals("testUtils", CasesUtils.convert("test-utils", CasesUtils.KEBAB, CasesUtils.CAMEL)); + Assertions.assertEquals("Test_Utils", CasesUtils.convert("TestUtils", CasesUtils.PASCAL, CasesUtils.SNAKE)); + } + + @Test + public void testCharacterDelimitedCase() { + Assertions.assertThrows(IllegalArgumentException.class, () -> KebabCase.INSTANCE.format(Arrays.asList("a", "-"))); + Assertions.assertThrows(IllegalArgumentException.class, () -> SnakeCase.INSTANCE.format(Arrays.asList("a", "_"))); + CharacterDelimitedCase nullDelimiters = new CharacterDelimitedCase(); + assertFormat(nullDelimiters, "abc", Arrays.asList("a", "b", "c")); + assertParse(nullDelimiters, "abc", Arrays.asList("abc")); + } + + @Test + public void testKebabCase() { + assertFormatAndParse(KebabCase.INSTANCE, "", Arrays.asList()); + assertParse(KebabCase.INSTANCE, null, Arrays.asList()); + assertFormatAndParse(KebabCase.INSTANCE, "my-Tokens-123-a1", Arrays.asList("my", "Tokens", "123", "a1")); + assertFormatAndParse(KebabCase.INSTANCE, "blank--token", Arrays.asList("blank", "", "token")); + } + + @Test + public void testUtf32() { + assertFormatAndParse(KebabCase.INSTANCE, "\uD800\uDF00-\uD800\uDF01\uD800\uDF14-\uD800\uDF02\uD800\uDF03", + Arrays.asList("\uD800\uDF00", "\uD800\uDF01\uD800\uDF14", "\uD800\uDF02\uD800\uDF03")); + assertFormatAndParse(SnakeCase.INSTANCE, "\uD800\uDF00_\uD800\uDF01\uD800\uDF14_\uD800\uDF02\uD800\uDF03", + Arrays.asList("\uD800\uDF00", "\uD800\uDF01\uD800\uDF14", "\uD800\uDF02\uD800\uDF03")); + + assertFormatAndParse(PascalCase.INSTANCE, "A\uD800\uDF00B\uD800\uDF01\uD800\uDF14C\uD800\uDF02\uD800\uDF03", + Arrays.asList("A\uD800\uDF00", "B\uD800\uDF01\uD800\uDF14", "C\uD800\uDF02\uD800\uDF03")); + assertFormatAndParse(CamelCase.INSTANCE, "a\uD800\uDF00B\uD800\uDF01\uD800\uDF14C\uD800\uDF02\uD800\uDF03", + Arrays.asList("a\uD800\uDF00", "B\uD800\uDF01\uD800\uDF14", "C\uD800\uDF02\uD800\uDF03")); + + } + + @Test + public void testSnakeCase() { + assertFormatAndParse(SnakeCase.INSTANCE, "", Arrays.asList()); + assertParse(SnakeCase.INSTANCE, null, Arrays.asList()); + assertFormatAndParse(SnakeCase.INSTANCE, "my_Tokens_123_a1", Arrays.asList("my", "Tokens", "123", "a1")); + assertFormatAndParse(SnakeCase.INSTANCE, "blank__token", Arrays.asList("blank", "", "token")); + } + + @Test + public void testPascalCase() { + + assertFormatAndParse(PascalCase.INSTANCE, "MyVarName", Arrays.asList("My", "Var", "Name")); + assertFormatAndParse(PascalCase.INSTANCE, "MyTokensA1D", Arrays.asList("My", "Tokens", "A1", "D")); + assertFormatAndParse(PascalCase.INSTANCE, "", Arrays.asList()); + assertParse(PascalCase.INSTANCE, "lowerFirst", Arrays.asList("lower", "First")); + assertFormat(PascalCase.INSTANCE, "LowerFirst", Arrays.asList("lower", "First")); + + Assertions.assertThrows(IllegalArgumentException.class, () -> PascalCase.INSTANCE.format(Arrays.asList("1"))); + Assertions.assertThrows(IllegalArgumentException.class, () -> PascalCase.INSTANCE.format(Arrays.asList("a1", "2c"))); + Assertions.assertThrows(IllegalArgumentException.class, () -> PascalCase.INSTANCE.format(Arrays.asList("1a"))); + Assertions.assertThrows(IllegalArgumentException.class, () -> PascalCase.INSTANCE.format(Arrays.asList(""))); + } + + @Test + public void testNumberLetters() { + + // roman numerals - have an upper/lower case but are numbers + + assertFormatAndParse(PascalCase.INSTANCE, "A\u2170\u2160c", Arrays.asList("A\u2170", "\u2160c")); + + assertFormat(PascalCase.INSTANCE, "A\u2170Bc", Arrays.asList("a\u2160", "bc")); + assertParse(PascalCase.INSTANCE, "A\u2170Bc", Arrays.asList("A\u2170", "Bc")); + assertFormat(PascalCase.INSTANCE, "A\u2170", Arrays.asList("a\u2170")); + assertParse(PascalCase.INSTANCE, "A\u2170Bc", Arrays.asList("A\u2170", "Bc")); + + assertFormat(CamelCase.INSTANCE, "a\u2170Bc", Arrays.asList("a\u2160", "bc")); + assertParse(CamelCase.INSTANCE, "\u2160Bc", Arrays.asList("\u2160", "Bc")); + + } + + @Test + public void testCamelCase() { + + assertFormatAndParse(CamelCase.INSTANCE, "", Arrays.asList()); + assertFormatAndParse(CamelCase.INSTANCE, "myTokensAbc123", Arrays.asList("my", "Tokens", "Abc123")); + assertFormatAndParse(CamelCase.INSTANCE, "specChar-Token+", Arrays.asList("spec", "Char-", "Token+")); + + assertParse(CamelCase.INSTANCE, "MyTokens", Arrays.asList("My", "Tokens")); + assertFormat(CamelCase.INSTANCE, "myTokens", Arrays.asList("My", "Tokens")); + + // empty token not supported + Assertions.assertThrows(IllegalArgumentException.class, () -> CamelCase.INSTANCE.format(Arrays.asList("a", "b", ""))); + // must begin with character that can be uppercased + Assertions.assertThrows(IllegalArgumentException.class, () -> CamelCase.INSTANCE.format(Arrays.asList("a", "1b"))); + Assertions.assertThrows(IllegalArgumentException.class, () -> CamelCase.INSTANCE.format(Arrays.asList("1a"))); + } + + @Test + public void testConversionsDelimited() { + + List<String> tokens = Arrays.asList("My", "var", "NAME", "mIXED", "a1", "12", ""); + + String kebabString = "My-var-NAME-mIXED-a1-12-"; Review Comment: These should be separate test methods for easier debugging -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
