You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@creadur.apache.org by cl...@apache.org on 2026/03/25 20:50:39 UTC
(creadur-rat) branch master updated: RAT-538: Update CasedString for efficency (#626)
This is an automated email from the ASF dual-hosted git repository.
claude pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/creadur-rat.git
The following commit(s) were added to refs/heads/master by this push:
new 25f95abc RAT-538: Update CasedString for efficency (#626)
25f95abc is described below
commit 25f95abc0f9a574441db16160525ed7e154cf08b
Author: Claude Warren <cl...@apache.org>
AuthorDate: Wed Mar 25 21:50:33 2026 +0100
RAT-538: Update CasedString for efficency (#626)
* Switched to cased string preserving the parts from the parsing
* fixed pascal/camel confusion in tests
* fixed Pascal/Camel case useage confusion
* fixed Camel/Pascal case confusion in Maven and Ant UI
---------
Co-authored-by: P. Ottlinger <po...@apache.org>
---
.../org/apache/rat/report/xml/XmlElements.java | 2 +-
.../java/org/apache/rat/utils/CasedString.java | 295 ++++++++++++--------
.../org/apache/rat/utils/CasedStringTests.java | 296 +++++++++++++++++++++
.../rat/documentation/options/AntOption.java | 2 +-
apache-rat-tools/src/main/resources/Ant.tpl | 2 +-
apache-rat-tools/src/main/resources/Maven.tpl | 2 +-
6 files changed, 481 insertions(+), 118 deletions(-)
diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlElements.java b/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlElements.java
index e8301aa8..35d14b10 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlElements.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlElements.java
@@ -43,7 +43,7 @@ public class XmlElements {
*/
private static String normalizeName(final String name) {
CasedString casedName = new CasedString(CasedString.StringCase.SNAKE, name.toLowerCase(Locale.ROOT));
- return casedName.toCase(CasedString.StringCase.CAMEL);
+ return casedName.toCase(CasedString.StringCase.PASCAL);
}
/**
diff --git a/apache-rat-core/src/main/java/org/apache/rat/utils/CasedString.java b/apache-rat-core/src/main/java/org/apache/rat/utils/CasedString.java
index 79b29d10..6751ad17 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/utils/CasedString.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/utils/CasedString.java
@@ -19,177 +19,244 @@
package org.apache.rat.utils;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
import java.util.function.Function;
import java.util.function.Predicate;
+import java.util.function.UnaryOperator;
+import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.WordUtils;
/**
* Handles converting from one string case to another (e.g. camel case to snake case).
* @since 0.17
*/
-public class CasedString {
- /** the string of the cased format. */
- private final String string;
- /** the case of the string. */
+public final class CasedString {
+ /** The segments of the cased string */
+ private final String[] segments;
+ /** The case of the string as parsed */
private final StringCase stringCase;
+ /** A joiner used for the pascal and camel cases. */
+ private static final Function<String[], String> CAMEL_JOINER = strings -> {
+ StringBuilder sb = new StringBuilder();
+ Arrays.stream(strings).map(s -> s == null ? "" : s).forEach(token -> sb.append(WordUtils.capitalize(token.toLowerCase(Locale.ROOT))));
+ return sb.toString();
+ };
/**
- * A method to join camel string fragments together.
+ * Creates a cased string by parsing the string argument for the specific case.
+ * @param stringCase the case of the string being parsed.
+ * @param string the string to parse.
*/
- private static final Function<String[], String> CAMEL_JOINER = a -> {
- StringBuilder sb = new StringBuilder(a[0].toLowerCase(Locale.ROOT));
+ public CasedString(final StringCase stringCase, final String string) {
+ this.segments = string == null ? CasedString.StringCase.NULL_SEGMENT : stringCase.getSegments(string.trim());
+ this.stringCase = stringCase;
+ }
- for (int i = 1; i < a.length; i++) {
- sb.append(WordUtils.capitalize(a[i].toLowerCase(Locale.ROOT)));
+ /**
+ * Creates a cased string of the specified case and segments.
+ * @param stringCase the case of the string.
+ * @param segments the segments of the string.
+ */
+ public CasedString(final StringCase stringCase, final String[] segments) {
+ this.segments = segments;
+ this.stringCase = stringCase;
+ }
+
+ /**
+ * Converts this cased string into another format.
+ * @param stringCase the desired format.
+ * @return the new CasedString.
+ */
+ public CasedString as(final StringCase stringCase) {
+ return stringCase.name.equals(this.stringCase.name) ? this : new CasedString(stringCase, (String[]) Arrays.copyOf(this.segments, this.segments.length));
+ }
+
+ /**
+ * Gets the segments of this cased string.
+ * @return the segments of this cased string.
+ */
+ public String[] getSegments() {
+ return this.segments;
+ }
+
+ /**
+ * Generates a string from this cased string but with the desired case.
+ * @param stringCase the desired case.
+ * @return this cased string in the desired case.
+ */
+ public String toCase(final StringCase stringCase) {
+ return this.segments == CasedString.StringCase.NULL_SEGMENT ? null : stringCase.assemble(this.getSegments());
+ }
+
+ @Override
+ public String toString() {
+ return this.toCase(this.stringCase);
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == null || getClass() != o.getClass()) {
+ return false;
}
- return sb.toString();
- };
+ CasedString that = (CasedString) o;
+ return Objects.deepEquals(getSegments(), that.getSegments()) && Objects.equals(stringCase, that.stringCase);
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(getSegments());
+ }
/**
- * An enumeration of supported string cases. These cases tag strings as having a specific format.
+ * The definition of a string case.
*/
- public enum StringCase {
- /**
- * Camel case tags strings like 'CamelCase' or 'camelCase'. This conversion forces the first character to
- * lower case. If specific capitalization rules are required use {@link WordUtils#capitalize(String)} to set the first
- * character of the string.
+ public static final class StringCase {
+ /** The camel case. Example: "HelloWorld"*/
+ public static final StringCase CAMEL;
+ /** The pascal case. Example: "helloWorld" */
+ public static final StringCase PASCAL;
+ /** The Snake case. Example: "hello_world" */
+ public static final StringCase SNAKE;
+ /** The Kebab case. Example: "hello-world" */
+ public static final StringCase KEBAB;
+ /** The phrase case. Example: "hello world" */
+ public static final StringCase PHRASE;
+ /** The dot case. Example: "hello.world" */
+ public static final StringCase DOT;
+ /** The slash case. Example: "hello/world" */
+ public static final StringCase SLASH;
+ /** A marker for the parsing of a NULL string. */
+ static final String[] NULL_SEGMENT;
+ /** An empty segment marker. */
+ static final String[] EMPTY_SEGMENT;
+ /** The name of this case */
+ private final String name;
+ /** The predicate that determines if a character is a splitter character. A splitter character
+ * is the character that signals the start of a new segment.
*/
- CAMEL(Character::isUpperCase, true, CAMEL_JOINER),
- /**
- * Snake case tags strings like 'Snake_Case'. This conversion does not change the capitalization of any characters
- * in the string. If specific capitalization is required use {@link String#toUpperCase()}, {@link String#toLowerCase()},
- * or the commons-text methods {@link WordUtils#capitalize(String)}, or {@link WordUtils#uncapitalize(String)} as required.
- */
- SNAKE(c -> c == '_', false, a -> String.join("_", a)),
+ private final Predicate<Character> splitter;
/**
- * Kebab case tags strings like 'kebab-case'. This conversion does not change the capitalization of any characters
- * in the string. If specific capitalization is required use {@link String#toUpperCase()}, {@link String#toLowerCase()},
- * * or the commons-text methods {@link WordUtils#capitalize(String)}, or {@link WordUtils#uncapitalize(String)} as required.
+ * If {@code true}, the splitter character is preserved as part of the subsequent section otherwise,
+ * the splitter character is discarded.
*/
- KEBAB(c -> c == '-', false, a -> String.join("-", a)),
+ private final boolean preserveSplit;
+ /** The function that converts segments into the String representation */
+ private final Function<String[], String> joiner;
+ /** A function to provide post-processing on the joined string */
+ private final UnaryOperator<String> postProcess;
/**
- * Phrase case tags phrases of words like 'phrase case'. This conversion does not change the capitalization of any characters
- * in the string. If specific capitalization is required use {@link String#toUpperCase()}, {@link String#toLowerCase()},
- * * or the commons-text methods {@link WordUtils#capitalize(String)}, or {@link WordUtils#uncapitalize(String)} as required.
+ * Constructs a StringCase
+ * @param name the name of the case.
+ * @param splitter the splitter to determine when to split a string.
+ * @param preserveSplit the preserveSplit flag.
+ * @param joiner the joiner to assemble the String from the segments.
*/
- PHRASE(Character::isWhitespace, false, a -> String.join(" ", a)),
+ public StringCase(final String name, final Predicate<Character> splitter, final boolean preserveSplit, final Function<String[], String> joiner) {
+ this(name, splitter, preserveSplit, joiner, UnaryOperator.identity());
+ }
/**
- * Dot case tags phrases of words like 'phrase.case'. This conversion does not change the capitalization of any characters
- * in the string. If specific capitalization is required use {@link String#toUpperCase()}, {@link String#toLowerCase()},
- * * or the commons-text methods {@link WordUtils#capitalize(String)}, or {@link WordUtils#uncapitalize(String)} as required.
+ * Constructs a String case for the common cases where the delimiter is not preserved in the segments.
+ * @param name the name of the case.
+ * @param delimiter the delimter between segments.
*/
- DOT(c -> c == '.', false, a -> String.join(".", a));
-
- /** The segment value for a null string */
- private static final String[] NULL_SEGMENT = new String[0];
- /** The segment value for an empty string */
- private static final String[] EMPTY_SEGMENT = {""};
-
- /** test for split position character. */
- private final Predicate<Character> splitter;
- /** if {@code true} split position character will be preserved in following segment. */
- private final boolean preserveSplit;
- /** a function to joining the segments into this case type. */
- private final Function<String[], String> joiner;
+ public StringCase(final String name, final char delimiter) {
+ this(name, c -> c == delimiter, false, simpleJoiner(delimiter));
+ }
/**
- * 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.
+ * Constructs a StingCase.
+ * @param name the name of the string case.
+ * @param splitter the splitter to detect segments.
+ * @param preserveSplit the flag to preserve the splitter character.
+ * @param joiner the joiner to assemble a String from segments.
+ * @param postProcess the post-process applied to the segments after the splitter has created them.
*/
- StringCase(final Predicate<Character> splitter, final boolean preserveSplit, final Function<String[], String> joiner) {
+ public StringCase(final String name, final Predicate<Character> splitter, final boolean preserveSplit, final Function<String[], String> joiner,
+ final UnaryOperator<String> postProcess) {
+ this.name = name;
this.splitter = splitter;
this.preserveSplit = preserveSplit;
this.joiner = joiner;
+ this.postProcess = postProcess;
}
/**
- * Creates a cased string from a collection of segments.
- * @param segments the segments to create the CasedString from.
- * @return a CasedString
+ * A simple joiner that assembles a String from a collection of segments.
+ * Correctly handles the case where there are zero length segments.
+ * @param delimiter the delimiter to use between the segments.
+ * @return the assembled string.
+ */
+ public static Function<String[], String> simpleJoiner(final char delimiter) {
+ return s -> String.join(String.valueOf(delimiter), (CharSequence[]) Arrays.stream(s).filter(Objects::nonNull).toArray(String[]::new));
+ }
+
+ @Override
+ public String toString() {
+ return this.name;
+ }
+
+ /**
+ * Assembles segments into a String.
+ * @param segments the segments to assemble.
+ * @return the complete String.
*/
public String assemble(final String[] segments) {
- return segments.length == 0 ? null : this.joiner.apply(segments);
+ return this.joiner.apply(segments);
}
/**
- * Returns an array of each of the segments in this CasedString. Segments are defined as the strings between
- * the separators in the CasedString. For the CAMEL case the segments are determined by the presence of a capital letter.
- * @return the array of Strings that are segments of the cased string.
+ * Parses a String into segments.
+ * @param string the string to parse
+ * @return the segments from the string.
*/
public String[] getSegments(final String string) {
if (string == null) {
return NULL_SEGMENT;
- }
- if (string.isEmpty()) {
+ } else if (string.isEmpty()) {
return EMPTY_SEGMENT;
- }
- List<String> lst = new ArrayList<>();
- StringBuilder sb = new StringBuilder();
- for (char c : string.toCharArray()) {
- if (splitter.test(c)) {
- if (!sb.isEmpty()) {
+ } else {
+ List<String> lst = new ArrayList<>();
+ StringBuilder sb = new StringBuilder();
+
+ for (char c : string.toCharArray()) {
+ if (this.splitter.test(c)) {
lst.add(sb.toString());
sb.setLength(0);
- }
- if (preserveSplit) {
+ if (this.preserveSplit) {
+ sb.append(c);
+ }
+ } else {
sb.append(c);
}
- } else {
- sb.append(c);
}
+
+ if (!sb.isEmpty()) {
+ lst.add(sb.toString());
+ }
+
+ return lst.stream().map(this.postProcess).filter(Objects::nonNull).toArray(String[]::new);
}
- if (!sb.isEmpty()) {
- lst.add(sb.toString());
- }
- return lst.toArray(new String[0]);
}
- }
-
- /**
- * 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(final StringCase stringCase, final String string) {
- this.string = string == null ? null : stringCase.assemble(stringCase.getSegments(string.trim()));
- this.stringCase = stringCase;
- }
- /**
- * Returns an array of each of the segments in this CasedString. Segments are defined as the strings between
- * the separators in the CasedString. For the CAMEL case the segments are determined by the presence of a capital letter.
- * @return the array of Strings that are segments of the cased string.
- */
- public String[] getSegments() {
- return stringCase.getSegments(string);
- }
- /**
- * 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 format to convert to.
- * @return the String current string represented in the new format.
- */
- public String toCase(final StringCase stringCase) {
- if (stringCase == this.stringCase) {
- return string;
+ static {
+ CAMEL = new StringCase("CAMEL", Character::isUpperCase, true, CasedString.CAMEL_JOINER,
+ x -> (String) StringUtils.defaultIfEmpty(x, (CharSequence) null));
+ PASCAL = new StringCase("PASCAL", Character::isUpperCase, true, CasedString.CAMEL_JOINER.andThen(WordUtils::uncapitalize),
+ x -> (String) StringUtils.defaultIfEmpty(x, (CharSequence) null));
+ SNAKE = new StringCase("SNAKE", '_');
+ KEBAB = new StringCase("KEBAB", '-');
+ PHRASE = new StringCase("PHRASE", Character::isWhitespace, false, simpleJoiner(' '));
+ DOT = new StringCase("DOT", '.');
+ SLASH = new StringCase("SLASH", '/');
+ NULL_SEGMENT = new String[0];
+ EMPTY_SEGMENT = new String[]{""};
}
- return string == null ? null : stringCase.joiner.apply(getSegments());
- }
-
- /**
- * Returns the string representation provided in the constructor.
- * @return the string representation.
- */
- @Override
- public String toString() {
- return string;
}
}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/utils/CasedStringTests.java b/apache-rat-core/src/test/java/org/apache/rat/utils/CasedStringTests.java
new file mode 100644
index 00000000..f69c1160
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/utils/CasedStringTests.java
@@ -0,0 +1,296 @@
+/*
+ * 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.rat.utils;
+
+import org.junit.jupiter.api.Test;
+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.assertj.core.api.Assertions.assertThat;
+
+class CasedStringTests {
+
+ @MethodSource("testSegmentationData")
+ @ParameterizedTest
+ void testSegmentation(String pattern, CasedString.StringCase stringCase, String[] expected) {
+ CasedString casedString = new CasedString(stringCase, pattern);
+ assertThat(casedString.getSegments()).isEqualTo(expected);
+ }
+
+ static Stream<Arguments> testSegmentationData() {
+ List<Arguments> lst = new ArrayList<>();
+ lst.add(Arguments.of("CamelCase", CasedString.StringCase.CAMEL, new String[]{"Camel", "Case"}));
+ lst.add(Arguments.of("CamelPMDCase", CasedString.StringCase.CAMEL,
+ new String[]{"Camel", "P", "M", "D", "Case"}));
+ lst.add(Arguments.of("camelCase", CasedString.StringCase.CAMEL, new String[]{"camel", "Case"}));
+ lst.add(Arguments.of("camelPMDCase", CasedString.StringCase.CAMEL,
+ new String[]{"camel", "P", "M", "D", "Case"}));
+ lst.add(Arguments.of("PascalCase", CasedString.StringCase.PASCAL, new String[]{"Pascal", "Case"}));
+ lst.add(Arguments.of("PascalPMDCase", CasedString.StringCase.PASCAL,
+ new String[]{"Pascal", "P", "M", "D", "Case"}));
+ lst.add(Arguments.of("pascalCase", CasedString.StringCase.PASCAL, new String[]{"pascal", "Case"}));
+ lst.add(Arguments.of("pascalPMDCase", CasedString.StringCase.PASCAL,
+ new String[]{"pascal", "P", "M", "D", "Case"}));
+ lst.add(Arguments.of("snake_case", CasedString.StringCase.SNAKE, new String[]{"snake", "case"}));
+ lst.add(Arguments.of("snake_Case", CasedString.StringCase.SNAKE, new String[]{"snake", "Case"}));
+ lst.add(Arguments.of("snake__Case", CasedString.StringCase.SNAKE, new String[]{"snake", "", "Case"}));
+ lst.add(Arguments.of("kebab-case", CasedString.StringCase.KEBAB, new String[]{"kebab", "case"}));
+ lst.add(Arguments.of("kebab-Case", CasedString.StringCase.KEBAB, new String[]{"kebab", "Case"}));
+ lst.add(Arguments.of("kebab--case", CasedString.StringCase.KEBAB, new String[]{"kebab", "", "case"}));
+ lst.add(Arguments.of("phrase case", CasedString.StringCase.PHRASE, new String[]{"phrase", "case"}));
+ lst.add(Arguments.of("phrase Case", CasedString.StringCase.PHRASE, new String[]{"phrase", "Case"}));
+ lst.add(Arguments.of("phrase case", CasedString.StringCase.PHRASE, new String[]{"phrase", "", "case"}));
+ lst.add(Arguments.of("dot.case", CasedString.StringCase.DOT, new String[]{"dot", "case"}));
+ lst.add(Arguments.of("dot..case", CasedString.StringCase.DOT, new String[]{"dot", "", "case"}));
+ lst.add(Arguments.of("dot.Case", CasedString.StringCase.DOT, new String[]{"dot", "Case"}));
+ return lst.stream();
+ }
+
+ @MethodSource("testToCaseData")
+ @ParameterizedTest(name = "{index} {0} {1}")
+ void testToCase(CasedString casedString, CasedString.StringCase stringCase, String expected) {
+ assertThat(casedString.toCase(stringCase)).isEqualTo(expected);
+ }
+
+ static Stream<Arguments> testToCaseData() {
+ List<Arguments> lst = new ArrayList<>();
+
+ CasedString underTest = new CasedString(CasedString.StringCase.PASCAL, "camelCase");
+ lst.add(Arguments.of(underTest, CasedString.StringCase.PASCAL, "camelCase"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.SNAKE, "camel_Case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.KEBAB, "camel-Case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.PHRASE, "camel Case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.DOT, "camel.Case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.CAMEL, "CamelCase"));
+
+ underTest = new CasedString(CasedString.StringCase.SNAKE, "snake_case");
+ lst.add(Arguments.of(underTest, CasedString.StringCase.PASCAL, "snakeCase"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.SNAKE, "snake_case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.KEBAB, "snake-case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.PHRASE, "snake case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.DOT, "snake.case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.CAMEL, "SnakeCase"));
+
+ underTest = new CasedString(CasedString.StringCase.KEBAB, "kebab-case");
+ lst.add(Arguments.of(underTest, CasedString.StringCase.PASCAL, "kebabCase"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.SNAKE, "kebab_case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.KEBAB, "kebab-case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.PHRASE, "kebab case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.DOT, "kebab.case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.CAMEL, "KebabCase"));
+
+ underTest = new CasedString(CasedString.StringCase.PHRASE, "phrase case");
+ lst.add(Arguments.of(underTest, CasedString.StringCase.PASCAL, "phraseCase"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.SNAKE, "phrase_case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.KEBAB, "phrase-case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.PHRASE, "phrase case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.DOT, "phrase.case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.CAMEL, "PhraseCase"));
+
+ underTest = new CasedString(CasedString.StringCase.DOT, "dot.case");
+ lst.add(Arguments.of(underTest, CasedString.StringCase.PASCAL, "dotCase"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.SNAKE, "dot_case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.KEBAB, "dot-case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.PHRASE, "dot case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.DOT, "dot.case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.CAMEL, "DotCase"));
+
+ underTest = new CasedString(CasedString.StringCase.PASCAL, "pascalCase");
+ lst.add(Arguments.of(underTest, CasedString.StringCase.PASCAL, "pascalCase"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.SNAKE, "pascal_Case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.KEBAB, "pascal-Case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.PHRASE, "pascal Case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.DOT, "pascal.Case"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.CAMEL, "PascalCase"));
+
+ underTest = new CasedString(CasedString.StringCase.DOT, "one..two");
+ lst.add(Arguments.of(underTest, CasedString.StringCase.PASCAL, "oneTwo"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.SNAKE, "one__two"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.KEBAB, "one--two"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.PHRASE, "one two"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.DOT, "one..two"));
+ lst.add(Arguments.of(underTest, CasedString.StringCase.CAMEL, "OneTwo"));
+
+ return lst.stream();
+ }
+
+ @MethodSource("testAssembleData")
+ @ParameterizedTest(name = "{index} {0} {1}")
+ void testAssemble(CasedString.StringCase underTest, String[] data, String expected) {
+ assertThat(underTest.assemble(data)).isEqualTo(expected);
+ }
+
+ static Stream<Arguments> testAssembleData() {
+ List<Arguments> lst = new ArrayList<>();
+ String[] emptyFirst = {"", "one", "two"};
+ String[] emptyMiddle = {"one", "", "two"};
+ String[] emptyEnd = {"one", "two", ""};
+ String[] nullFirst = {null, "one", "two"};
+ String[] nullMiddle = {"one", null, "two"};
+ String[] nullEnd = {"one", "two", null};
+ String[] doubleEmpty = {"one", "", "", "two"};
+ String[] doubleNull = {"one", null, null, "two"};
+
+ CasedString.StringCase underTest = CasedString.StringCase.PASCAL;
+ lst.add(Arguments.of(underTest, emptyFirst, "oneTwo"));
+ lst.add(Arguments.of(underTest, emptyMiddle, "oneTwo"));
+ lst.add(Arguments.of(underTest, emptyEnd, "oneTwo"));
+ lst.add(Arguments.of(underTest, nullFirst, "oneTwo"));
+ lst.add(Arguments.of(underTest, nullMiddle, "oneTwo"));
+ lst.add(Arguments.of(underTest, nullEnd, "oneTwo"));
+ lst.add(Arguments.of(underTest, doubleEmpty, "oneTwo"));
+ lst.add(Arguments.of(underTest, doubleNull, "oneTwo"));
+
+ underTest = CasedString.StringCase.CAMEL;
+ lst.add(Arguments.of(underTest, emptyFirst, "OneTwo"));
+ lst.add(Arguments.of(underTest, emptyMiddle, "OneTwo"));
+ lst.add(Arguments.of(underTest, emptyEnd, "OneTwo"));
+ lst.add(Arguments.of(underTest, nullFirst, "OneTwo"));
+ lst.add(Arguments.of(underTest, nullMiddle, "OneTwo"));
+ lst.add(Arguments.of(underTest, nullEnd, "OneTwo"));
+ lst.add(Arguments.of(underTest, doubleEmpty, "OneTwo"));
+ lst.add(Arguments.of(underTest, doubleNull, "OneTwo"));
+
+ underTest = CasedString.StringCase.SNAKE;
+ lst.add(Arguments.of(underTest, emptyFirst, "_one_two"));
+ lst.add(Arguments.of(underTest, emptyMiddle, "one__two"));
+ lst.add(Arguments.of(underTest, emptyEnd, "one_two_"));
+ lst.add(Arguments.of(underTest, nullFirst, "one_two"));
+ lst.add(Arguments.of(underTest, nullMiddle, "one_two"));
+ lst.add(Arguments.of(underTest, nullEnd, "one_two"));
+ lst.add(Arguments.of(underTest, doubleEmpty, "one___two"));
+ lst.add(Arguments.of(underTest, doubleNull, "one_two"));
+
+ underTest = CasedString.StringCase.KEBAB;
+ lst.add(Arguments.of(underTest, emptyFirst, "-one-two"));
+ lst.add(Arguments.of(underTest, emptyMiddle, "one--two"));
+ lst.add(Arguments.of(underTest, emptyEnd, "one-two-"));
+ lst.add(Arguments.of(underTest, nullFirst, "one-two"));
+ lst.add(Arguments.of(underTest, nullMiddle, "one-two"));
+ lst.add(Arguments.of(underTest, nullEnd, "one-two"));
+ lst.add(Arguments.of(underTest, doubleEmpty, "one---two"));
+ lst.add(Arguments.of(underTest, doubleNull, "one-two"));
+
+ underTest = CasedString.StringCase.PHRASE;
+ lst.add(Arguments.of(underTest, emptyFirst, " one two"));
+ lst.add(Arguments.of(underTest, emptyMiddle, "one two"));
+ lst.add(Arguments.of(underTest, emptyEnd, "one two "));
+ lst.add(Arguments.of(underTest, nullFirst, "one two"));
+ lst.add(Arguments.of(underTest, nullMiddle, "one two"));
+ lst.add(Arguments.of(underTest, nullEnd, "one two"));
+ lst.add(Arguments.of(underTest, doubleEmpty, "one two"));
+ lst.add(Arguments.of(underTest, doubleNull, "one two"));
+
+ underTest = CasedString.StringCase.DOT;
+ lst.add(Arguments.of(underTest, emptyFirst, ".one.two"));
+ lst.add(Arguments.of(underTest, emptyMiddle, "one..two"));
+ lst.add(Arguments.of(underTest, emptyEnd, "one.two."));
+ lst.add(Arguments.of(underTest, nullFirst, "one.two"));
+ lst.add(Arguments.of(underTest, nullMiddle, "one.two"));
+ lst.add(Arguments.of(underTest, nullEnd, "one.two"));
+ lst.add(Arguments.of(underTest, doubleEmpty, "one...two"));
+ lst.add(Arguments.of(underTest, doubleNull, "one.two"));
+
+ underTest = CasedString.StringCase.SLASH;
+ lst.add(Arguments.of(underTest, emptyFirst, "/one/two"));
+ lst.add(Arguments.of(underTest, emptyMiddle, "one//two"));
+ lst.add(Arguments.of(underTest, emptyEnd, "one/two/"));
+ lst.add(Arguments.of(underTest, nullFirst, "one/two"));
+ lst.add(Arguments.of(underTest, nullMiddle, "one/two"));
+ lst.add(Arguments.of(underTest, nullEnd, "one/two"));
+ lst.add(Arguments.of(underTest, doubleEmpty, "one///two"));
+ lst.add(Arguments.of(underTest, doubleNull, "one/two"));
+
+ return lst.stream();
+ }
+
+ @Test
+ void asTest() {
+ CasedString underTest = new CasedString(CasedString.StringCase.CAMEL, "camelCase");
+ assertThat(underTest.as(CasedString.StringCase.CAMEL)).isEqualTo(underTest);
+ CasedString expected = new CasedString(CasedString.StringCase.KEBAB, "camel-Case");
+ assertThat(underTest.as(CasedString.StringCase.KEBAB)).isEqualTo(expected);
+ underTest.getSegments()[0] = "Cow";
+ assertThat(expected.getSegments()[0]).as("verify segments not shared").isEqualTo("camel");
+ }
+
+ @Test
+ void testHashCode() {
+ CasedString s1 = new CasedString(CasedString.StringCase.KEBAB, "the-test-string");
+ CasedString s2 = new CasedString(CasedString.StringCase.DOT, "the.test.string");
+ CasedString s3 = new CasedString(CasedString.StringCase.SLASH, "the/test/String");
+ assertThat(s1).hasSameHashCodeAs(s2);
+ assertThat(s1.hashCode()).isNotEqualTo(s3.hashCode());
+ }
+
+ @Test
+ void testSegmentConstructor() {
+ CasedString s1 = new CasedString(CasedString.StringCase.KEBAB, new String[]{"the", "test", "string"});
+ CasedString s2 = new CasedString(CasedString.StringCase.KEBAB, "the-test-string");
+ assertThat(s1).isEqualTo(s2);
+ CasedString s3 = new CasedString(CasedString.StringCase.DOT, new String[]{"the", "test", "string"});
+ assertThat(s1).isNotEqualTo(s3);
+ }
+
+ @Test
+ void testNullValue() {
+ CasedString nullValue = new CasedString(CasedString.StringCase.CAMEL, (String) null);
+ assertThat(nullValue.getSegments()).isEqualTo(CasedString.StringCase.NULL_SEGMENT);
+ assertThat(nullValue.toString()).isNull();
+ assertThat(nullValue.as(CasedString.StringCase.DOT).getSegments()).isEqualTo(CasedString.StringCase.NULL_SEGMENT);
+ assertThat(nullValue.toCase(CasedString.StringCase.DOT)).isNull();
+ assertThat(nullValue).isEqualTo(new CasedString(CasedString.StringCase.CAMEL, (String) null))
+ .isNotEqualTo(new CasedString(CasedString.StringCase.CAMEL, ""));
+ }
+
+ @Test
+ void testEmptyString() {
+ CasedString emptyValue = new CasedString(CasedString.StringCase.CAMEL, "");
+ assertThat(emptyValue.getSegments()).isEqualTo(CasedString.StringCase.EMPTY_SEGMENT);
+ assertThat(emptyValue.toString()).isEmpty();
+ assertThat(emptyValue.as(CasedString.StringCase.DOT).getSegments()).isEqualTo(CasedString.StringCase.EMPTY_SEGMENT);
+ assertThat(emptyValue.toCase(CasedString.StringCase.DOT)).isEmpty();
+ assertThat(emptyValue).isEqualTo(new CasedString(CasedString.StringCase.CAMEL, ""))
+ .isNotEqualTo(new CasedString(CasedString.StringCase.CAMEL, (String)null));
+ }
+
+ @Test
+ void testCamel() {
+ CasedString underTest = new CasedString(CasedString.StringCase.CAMEL, "camelCase");
+ assertThat(underTest).hasToString("CamelCase");
+ assertThat(underTest.getSegments()).isEqualTo(new String[]{"camel", "Case"});
+ underTest = new CasedString(CasedString.StringCase.CAMEL, new String[]{"camel", "case"});
+ assertThat(underTest).hasToString("CamelCase");
+
+ }
+
+ @Test
+ void testPascal() {
+ CasedString underTest = new CasedString(CasedString.StringCase.PASCAL, "PascalCase");
+ assertThat(underTest).hasToString("pascalCase");
+ assertThat(underTest.getSegments()).isEqualTo(new String[]{"Pascal", "Case"});
+ underTest = new CasedString(CasedString.StringCase.PASCAL, new String[]{"pascal", "case"});
+ assertThat(underTest).hasToString("pascalCase");
+ }
+}
diff --git a/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/AntOption.java b/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/AntOption.java
index 7cbfa16c..38e88ba2 100644
--- a/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/AntOption.java
+++ b/apache-rat-tools/src/main/java/org/apache/rat/documentation/options/AntOption.java
@@ -210,7 +210,7 @@ public class AntOption extends AbstractOption {
public static String createName(final Option option) {
String name = option.getLongOpt();
name = StringUtils.defaultIfEmpty(RENAME_MAP.get(name), name).toLowerCase(Locale.ROOT);
- return new CasedString(CasedString.StringCase.KEBAB, name).toCase(CasedString.StringCase.CAMEL);
+ return new CasedString(CasedString.StringCase.KEBAB, name).toCase(CasedString.StringCase.PASCAL);
}
/**
diff --git a/apache-rat-tools/src/main/resources/Ant.tpl b/apache-rat-tools/src/main/resources/Ant.tpl
index 952f4551..cc43adfb 100644
--- a/apache-rat-tools/src/main/resources/Ant.tpl
+++ b/apache-rat-tools/src/main/resources/Ant.tpl
@@ -58,7 +58,7 @@ ${static}
public static String createName(String longOpt) {
String name = StringUtils.defaultIfEmpty(xlateName.get(longOpt), longOpt).toLowerCase(Locale.ROOT);
- return new CasedString(CasedString.StringCase.KEBAB, name).toCase(CasedString.StringCase.CAMEL);
+ return new CasedString(CasedString.StringCase.KEBAB, name).toCase(CasedString.StringCase.PASCAL);
}
public static List<String> unsupportedArgs() {
diff --git a/apache-rat-tools/src/main/resources/Maven.tpl b/apache-rat-tools/src/main/resources/Maven.tpl
index c1bc2c19..0c6cc9a7 100644
--- a/apache-rat-tools/src/main/resources/Maven.tpl
+++ b/apache-rat-tools/src/main/resources/Maven.tpl
@@ -62,7 +62,7 @@ ${static}
*/
public static String createName(String longOpt) {
String name = xlateName.get(longOpt);
- return name != null ? name : new CasedString(CasedString.StringCase.KEBAB, longOpt).toCase(CasedString.StringCase.CAMEL);
+ return name != null ? name : new CasedString(CasedString.StringCase.KEBAB, longOpt).toCase(CasedString.StringCase.PASCAL);
}
/**