SentenceFormatter.java
// Generated by delombok at Mon Nov 18 07:27:48 UTC 2024
package de.larssh.utils.text;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
/**
* Class to format and parse a list of words.
*
* <p>
* Constants define instances of common formatters. The following is an example
* using the words {@code abc}, {@code def} and {@code ghi}.
* <table>
* <caption>Examples</caption>
* <tr>
* <th>Formatter</th>
* <th>Example</th>
* </tr>
* <tr>
* <td>{@link #LOWER_CAMEL_CASE}</td>
* <td>abcDefGhi</td>
* </tr>
* <tr>
* <td>{@link #LOWER_KEBAB_CASE}</td>
* <td>abc-def-ghi</td>
* </tr>
* <tr>
* <td>{@link #LOWER_SNAKE_CASE}</td>
* <td>abc_def_ghi</td>
* </tr>
* <tr>
* <td>{@link #LOWER_WHITE_SPACE}</td>
* <td>Abc def ghi</td>
* </tr>
* <tr>
* <td>{@link #UPPER_CAMEL_CASE}</td>
* <td>AbcDefGhi</td>
* </tr>
* <tr>
* <td>{@link #UPPER_KEBAB_CASE}</td>
* <td>ABC-DEF-GHI</td>
* </tr>
* <tr>
* <td>{@link #UPPER_SNAKE_CASE}</td>
* <td>ABC_DEF_GHI</td>
* </tr>
* <tr>
* <td>{@link #UPPER_WHITE_SPACE}</td>
* <td>Abc Def Ghi</td>
* </tr>
* </table>
*/
public class SentenceFormatter {
/**
* Word separator for kebab space
*/
private static final String SEPARATOR_KEBAB_CASE = "-";
/**
* Word separator for snake space
*/
private static final String SEPARATOR_SNAKE_CASE = "_";
/**
* Word separator for white space
*/
private static final String SEPARATOR_WHITE_SPACE = " ";
/**
* Lower Camel Case formatter
*
* <p>
* Example: abcDefGhi
*
* <p>
* Words are translated to title case, except the first words, which is
* translated to lower case.
*/
public static final SentenceFormatter LOWER_CAMEL_CASE = new SentenceFormatter(Strings::toLowerCaseNeutral, "", Strings::toTitleCaseNeutral);
/**
* Lower Kebab Case formatter
*
* <p>
* Example: abc-def-ghi
*
* <p>
* Words are translated to lower case and are separated by minus character.
*/
public static final SentenceFormatter LOWER_KEBAB_CASE = new SentenceFormatter(Strings::toLowerCaseNeutral, SEPARATOR_KEBAB_CASE, Strings::toLowerCaseNeutral);
/**
* Lower Snake Case formatter
*
* <p>
* Example: abc_def_ghi
*
* <p>
* Words are translated to lower case and are separated by underscore character.
*/
public static final SentenceFormatter LOWER_SNAKE_CASE = new SentenceFormatter(Strings::toLowerCaseNeutral, SEPARATOR_SNAKE_CASE, Strings::toLowerCaseNeutral);
/**
* Lower White Space formatter
*
* <p>
* Example: Abc def ghi
*
* <p>
* Words are translated to lower case, except the first word, which is
* translated to title case, and are separated by white space character.
*/
public static final SentenceFormatter LOWER_WHITE_SPACE = new SentenceFormatter(Strings::toTitleCaseNeutral, SEPARATOR_WHITE_SPACE, Strings::toLowerCaseNeutral);
/**
* Upper Camel Case formatter
*
* <p>
* Example: AbcDefGhi
*
* <p>
* Words are translated to title case.
*/
public static final SentenceFormatter UPPER_CAMEL_CASE = new SentenceFormatter(Strings::toTitleCaseNeutral, "", Strings::toTitleCaseNeutral);
/**
* Upper Kebab Case formatter
*
* <p>
* Example: ABC-DEF-GHI
*
* <p>
* Words are translated to upper case and are separated by minus character.
*/
public static final SentenceFormatter UPPER_KEBAB_CASE = new SentenceFormatter(Strings::toUpperCaseNeutral, SEPARATOR_KEBAB_CASE, Strings::toUpperCaseNeutral);
/**
* Upper Snake Case formatter
*
* <p>
* Example: ABC_DEF_GHI
*
* <p>
* Words are translated to upper case and are separated by underscore character.
*/
public static final SentenceFormatter UPPER_SNAKE_CASE = new SentenceFormatter(Strings::toUpperCaseNeutral, SEPARATOR_SNAKE_CASE, Strings::toUpperCaseNeutral);
/**
* Upper White Space formatter
*
* <p>
* Example: Abc Def Ghi
*
* <p>
* Words are translated to title case and are separated by white space
* character.
*/
public static final SentenceFormatter UPPER_WHITE_SPACE = new SentenceFormatter(Strings::toTitleCaseNeutral, SEPARATOR_WHITE_SPACE, Strings::toTitleCaseNeutral);
/**
* Function to convert the first word
*/
private final Function<String, String> convertFirstWord;
/**
* Separator character between words
*/
private final String separator;
/**
* Function to convert all words except the first word
*/
private final Function<String, String> convertSubsequentWords;
/**
* Formats the list of given words using the specified converter functions and
* separator.
*
* @param words list of words
* @return formatted sentence
*/
public String format(final String... words) {
return format(asList(words));
}
/**
* Formats the list of given words using the specified converter functions and
* separator.
*
* @param words list of words
* @return formatted sentence
*/
public String format(final List<String> words) {
if (words.isEmpty()) {
return "";
}
final StringBuilder builder = new StringBuilder();
builder.append(getConvertFirstWord().apply(words.get(0)));
final int size = words.size();
for (int index = 1; index < size; index += 1) {
builder.append(getSeparator());
builder.append(getConvertSubsequentWords().apply(words.get(index)));
}
return builder.toString();
}
/**
* Splits the given sentence into words using the separator. If the separator
* string is empty, the sentence is splitted by title characters. A leading
* title character does not generate an empty leading word.
*
* @param sentence the sentence to be splitted
* @return list of splitted words
*/
public List<String> parse(final String sentence) {
if (sentence.isEmpty()) {
return emptyList();
}
if (getSeparator().isEmpty()) {
return splitByTitleCharacters(sentence);
}
return splitBySeparator(sentence);
}
/**
* Splits the given sentence into words using the separator string.
*
* @param sentence the sentence to be splitted
* @return list of splitted words
*/
private List<String> splitBySeparator(final String sentence) {
final int sentenceLength = sentence.length();
final int separatorLength = getSeparator().length();
final int length = sentenceLength - separatorLength;
int beginIndex = 0;
final List<String> words = new ArrayList<>();
for (int index = 0; index < length; index += 1) {
if (sentence.regionMatches(index, getSeparator(), 0, separatorLength)) {
words.add(sentence.substring(beginIndex, index));
beginIndex = index + separatorLength;
}
}
words.add(sentence.substring(beginIndex, sentenceLength));
return words;
}
/**
* Splits the given sentence into words by title characters. A leading title
* character does not generate an empty leading word.
*
* @param sentence the sentence to be splitted
* @return list of splitted words
*/
private List<String> splitByTitleCharacters(final String sentence) {
final int length = sentence.length();
int beginIndex = 0;
final List<String> words = new ArrayList<>();
for (int index = 1; index < length; index += 1) {
if (Character.isUpperCase(sentence.charAt(index))) {
words.add(sentence.substring(beginIndex, index));
beginIndex = index;
}
}
words.add(sentence.substring(beginIndex, length));
return words;
}
/**
* Function to convert the first word
*
* @return convert function for the first word of a sentence
*/
@java.lang.SuppressWarnings("all")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
@lombok.Generated
public Function<String, String> getConvertFirstWord() {
return this.convertFirstWord;
}
/**
* Separator character between words
*
* @return separator
*/
@java.lang.SuppressWarnings("all")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
@lombok.Generated
public String getSeparator() {
return this.separator;
}
/**
* Function to convert all words except the first word
*
* @return convert function for subsequent words
*/
@java.lang.SuppressWarnings("all")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
@lombok.Generated
public Function<String, String> getConvertSubsequentWords() {
return this.convertSubsequentWords;
}
/**
* Creates a new {@code SentenceFormatter} instance.
*
* @param convertFirstWord Function to convert the first word
* @param separator Separator character between words
* @param convertSubsequentWords Function to convert all words except the first word
*/
@java.lang.SuppressWarnings("all")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
@lombok.Generated
public SentenceFormatter(final Function<String, String> convertFirstWord, final String separator, final Function<String, String> convertSubsequentWords) {
this.convertFirstWord = convertFirstWord;
this.separator = separator;
this.convertSubsequentWords = convertSubsequentWords;
}
}