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 <[email protected]>
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 <[email protected]>
---
.../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);
}
/**