This is an automated email from the ASF dual-hosted git repository.

claude pushed a commit to branch TEXT-217_Add_SnakeCase_Parsing
in repository https://gitbox.apache.org/repos/asf/commons-text.git

commit 7532dcb7bd0f8905391a491d428f195e8d7cbb0e
Author: Claude Warren <cla...@xenei.com>
AuthorDate: Sat May 25 11:42:22 2024 +0200

    initial implementation
---
 .../java/org/apache/commons/text/CasedString.java  | 143 +++++++++++++++++++++
 .../org/apache/commons/text/CasedStringTest.java   |  47 +++++++
 2 files changed, 190 insertions(+)

diff --git a/src/main/java/org/apache/commons/text/CasedString.java 
b/src/main/java/org/apache/commons/text/CasedString.java
new file mode 100644
index 00000000..a89cd862
--- /dev/null
+++ b/src/main/java/org/apache/commons/text/CasedString.java
@@ -0,0 +1,143 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+/**
+ * Handles converting from one string case to another (e.g. camel case to 
snake case).
+ */
+public class CasedString {
+    private String string;
+    private StringCase stringCase;
+
+    /**
+     * A method to join camel string fragments together.
+     */
+    private final static Function<String[],String> camelJoiner = a -> {
+        StringBuilder sb = new StringBuilder(a[0]);
+
+        for (int i=1;i<a.length;i++) {
+            sb.append(WordUtils.capitalize(a[i]));
+        }
+        return sb.toString();
+    };
+
+    /**
+     * An enumeration of supported string cases.
+     */
+    public enum StringCase {
+        /**
+         * Camel case identifies strings like 'CamelCase'.
+         */
+        Camel(Character::isUpperCase, true,  camelJoiner),
+        /**
+         * Snake case identifies strings like 'Snake_Case'
+         */
+        Snake(c -> c =='_', false, a -> String.join("_", a)),
+        /**
+         * Kebab case identifies strings like 'kebab-case'
+         */
+        Kebab(c -> c == '-', false, a -> String.join("-", a)),
+
+        /**
+         * Phrase case identifies phrases of words like 'phrase case'
+         */
+        Phrase(c -> c == ' ', false, a -> String.join(" ", a)),
+
+        /**
+         * Dot case identifies strings of words like 'dot.case'
+         */
+        Dot(c -> c == '.', false, a -> String.join(".", a));
+
+        private final Predicate<Character> splitter;
+        private final boolean preserveSplit;
+        private final Function<String[],String> joiner;
+
+        /**
+         * Defines a String Case
+         * @param splitter The predicate that determines when a new word in 
the cased string begins.
+         * @param preserveSplit if {@code true} the character that the 
splitter detected is preserved as the first character of the new word.
+         * @param joiner The function to merge a list of strings into the 
cased String.
+         */
+        StringCase(final Predicate<Character> splitter, final boolean 
preserveSplit, final Function<String[],String> joiner) {
+            this.splitter = splitter;
+            this.preserveSplit = preserveSplit;
+            this.joiner = joiner;
+        }
+    }
+
+    /**
+     * A representation of a cased string and the identified case of that 
string.
+     * @param stringCase The {@code StringCase} that the {@code string} 
argument is in.
+     * @param string The string.
+     */
+    public CasedString(StringCase stringCase, String string) {
+        this.string = string;
+        this.stringCase = stringCase;
+    }
+
+    private String[] split() {
+        List<String> lst = new ArrayList<>();
+        StringBuilder sb = new StringBuilder();
+        for (char c : string.toCharArray())
+        {
+            if (stringCase.splitter.test(c)) {
+                if (sb.length() > 0) {
+                    lst.add(sb.toString());
+                    sb.setLength(0);
+                }
+                if (stringCase.preserveSplit) {
+                    sb.append(c);
+                }
+            } else {
+                sb.append(c);
+            }
+        }
+        if (sb.length() > 0) {
+            lst.add(sb.toString());
+        }
+        return lst.toArray(new String[0]);
+    }
+
+    /**
+     * Converts this cased string into a {@code String} of another format.
+     * The upper/lower case of the characters within the string are not 
modified.
+     * @param stringCase THe fomrat to convert to.
+     * @return the String current string represented in the new format.
+     */
+    public String toCase(StringCase stringCase) {
+        if (stringCase == this.stringCase) {
+            return string;
+        }
+        return stringCase.joiner.apply(split());
+    }
+
+    /**
+     * Returns the string representation provided in the constructor.
+     * @return the string representation.
+     */
+    @Override
+    public String toString() {
+        return string;
+    }
+}
diff --git a/src/test/java/org/apache/commons/text/CasedStringTest.java 
b/src/test/java/org/apache/commons/text/CasedStringTest.java
new file mode 100644
index 00000000..14ccc781
--- /dev/null
+++ b/src/test/java/org/apache/commons/text/CasedStringTest.java
@@ -0,0 +1,47 @@
+package org.apache.commons.text;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class CasedStringTest {
+
+    private static String expectedValue(CasedString.StringCase stringCase) {
+        switch (stringCase) {
+            case Camel:
+                return "HelloWorld";
+            case Kebab:
+                return "Hello-World";
+            case Phrase:
+                return "Hello World";
+            case Snake:
+                return "Hello_World";
+            case Dot:
+                return "Hello.World";
+            default:
+                throw new RuntimeException("Unsupported StringCase: " + 
stringCase);
+        }
+    }
+
+    @ParameterizedTest
+    @MethodSource("conversionProvider")
+    public void testConversions(CasedString underTest) {
+        for (CasedString.StringCase stringCase : 
CasedString.StringCase.values()) {
+            assertEquals(expectedValue(stringCase), 
underTest.toCase(stringCase), () -> "failed converting to " + stringCase);
+        }
+    }
+
+    private static Stream<Arguments> conversionProvider() {
+        List<Arguments> lst = new ArrayList<>();
+        for (CasedString.StringCase stringCase : 
CasedString.StringCase.values()) {
+            lst.add(Arguments.of(new CasedString(stringCase, 
expectedValue(stringCase))));
+        }
+        return lst.stream();
+    }
+}

Reply via email to