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 79b29d109..e87347408 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 PASCAL_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 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 Objects.hash(Arrays.hashCode(getSegments()), stringCase); + } /** - * 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. */ + private static final String[] NULL_SEGMENT; + /** An empty segment marker. */ + private static final String[] EMPTY_SEGMENT; + /** The name of this case */ + private final String name; + /** The predicate that determines if a character is a spliter 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 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 spliter character is preserved as part of the subsequent section otherwise, + * the spliter 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 joiner; + /** A function to provide post-processing on the joined string */ + private final UnaryOperator 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 splitter, final boolean preserveSplit, final Function 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 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 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 splitter, final boolean preserveSplit, final Function joiner) { + public StringCase(final String name, final Predicate splitter, final boolean preserveSplit, final Function joiner, + final UnaryOperator 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 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 lst = new ArrayList<>(); - StringBuilder sb = new StringBuilder(); - for (char c : string.toCharArray()) { - if (splitter.test(c)) { - if (!sb.isEmpty()) { + } else { + List 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.PASCAL_JOINER.andThen(WordUtils::uncapitalize), + x -> (String) StringUtils.defaultIfEmpty(x, (CharSequence) null)); + PASCAL = new StringCase("PASCAL", Character::isUpperCase, true, CasedString.PASCAL_JOINER, + 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 000000000..2d4ff9938 --- /dev/null +++ b/apache-rat-core/src/test/java/org/apache/rat/utils/CasedStringTests.java @@ -0,0 +1,235 @@ +/* + * 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.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; + +public 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 testSegmentationData() { + List 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 testToCaseData() { + List lst = new ArrayList<>(); + + CasedString underTest = new CasedString(CasedString.StringCase.CAMEL, "camelCase"); + lst.add(Arguments.of(underTest, CasedString.StringCase.CAMEL, "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.PASCAL, "CamelCase")); + + underTest = new CasedString(CasedString.StringCase.SNAKE, "snake_case"); + lst.add(Arguments.of(underTest, CasedString.StringCase.CAMEL, "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.PASCAL, "SnakeCase")); + + underTest = new CasedString(CasedString.StringCase.KEBAB, "kebab-case"); + lst.add(Arguments.of(underTest, CasedString.StringCase.CAMEL, "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.PASCAL, "KebabCase")); + + underTest = new CasedString(CasedString.StringCase.PHRASE, "phrase case"); + lst.add(Arguments.of(underTest, CasedString.StringCase.CAMEL, "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.PASCAL, "PhraseCase")); + + underTest = new CasedString(CasedString.StringCase.DOT, "dot.case"); + lst.add(Arguments.of(underTest, CasedString.StringCase.CAMEL, "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.PASCAL, "DotCase")); + + underTest = new CasedString(CasedString.StringCase.PASCAL, "PascalCase"); + lst.add(Arguments.of(underTest, CasedString.StringCase.CAMEL, "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.PASCAL, "PascalCase")); + + underTest = new CasedString(CasedString.StringCase.DOT, "one..two"); + lst.add(Arguments.of(underTest, CasedString.StringCase.CAMEL, "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.PASCAL, "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 testAssembleData() { + List 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.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.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.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 + public 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); + } +}