Skip to content

Commit

Permalink
fix for Windows error + commons-text CasedString implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Claudenw committed May 25, 2024
1 parent 85197fa commit 7bb8b02
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 61 deletions.
132 changes: 91 additions & 41 deletions apache-rat-core/src/main/java/org/apache/rat/utils/CasedString.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,65 +22,129 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.function.Function;
import java.util.function.Predicate;

/**
* Handles converting from one string case to another (e.g. camel case to snake case).
* @since 1.13.0
*/
public class CasedString {
private String string;
private StringCase stringCase;
/** the string of the cased format. */
private final String string;
/** the case of the string. */
private final StringCase stringCase;

/**
* A method to join camel string fragments together.
*/
private final static Function<String[],String> camelJoiner = a -> {
StringBuilder sb = new StringBuilder(a[0]);
private static final Function<String[], String> CAMEL_JOINER = a -> {
StringBuilder sb = new StringBuilder(a[0].toLowerCase(Locale.ROOT));

for (int i=1;i<a.length;i++) {
sb.append(WordUtils.capitalize(a[i]));
for (int i = 1; i < a.length; i++) {
sb.append(WordUtils.capitalize(a[i].toLowerCase(Locale.ROOT)));
}
return sb.toString();
};

/**
* An enumeration of supported string cases.
* An enumeration of supported string cases. These cases tag strings as having a specific format.
*/
public enum StringCase {
/**
* Camel case identifies strings like 'CamelCase'.
* Camel case tags strings like 'CamelCase' or 'camelCase'. This conversion forces the first character to
* lower case. If specific capitalization rules are required use {@code WordUtils.capitalize()} to set the first
* character of the string.
*/
Camel(Character::isUpperCase, true, camelJoiner),
CAMEL(Character::isUpperCase, true, CAMEL_JOINER),
/**
* Snake case identifies strings like 'Snake_Case'
* 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 {@code String.upperCase}, {@code String.upperCase},
* {@code WordUtils.capitalize()}, or {@code WordUtils.uncapitalize()} as required.
*/
Snake(c -> c =='_', false, a -> String.join("_", a)),
SNAKE(c -> c == '_', false, a -> String.join("_", a)),
/**
* Kebab case identifies strings like 'kebab-case'
* 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 {@code String.upperCase}, {@code String.upperCase},
* {@code WordUtils.capitalize()}, or {@code WordUtils.uncapitalize()} as required.
*/
Kebab(c -> c == '-', false, a -> String.join("-", a)),
KEBAB(c -> c == '-', false, a -> String.join("-", a)),

/**
* Phrase case identifies phrases of words like 'phrase case'
* 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 {@code String.upperCase}, {@code String.upperCase},
* {@code WordUtils.capitalize()}, or {@code WordUtils.uncapitalize()} as required.
*/
Phrase(c -> c == ' ', false, a -> String.join(" ", a));
PHRASE(Character::isWhitespace, false, a -> String.join(" ", a)),

/**
* 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 {@code String.upperCase}, {@code String.upperCase},
* {@code WordUtils.capitalize()}, or {@code WordUtils.uncapitalize()} as required.
*/
DOT(c -> c == '.', false, a -> String.join(".", a));

/** 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;
private final Function<String[],String> joiner;
/** a function to joining the segments into this case type. */
private final Function<String[], String> joiner;

/**
* Defines a String Case
* Defines a String Case.
* @param splitter The predicate that determines when a new word in the cased string begins.
* @param preserveSplit if {@code true} the character that the splitter detected is preserved as the first character of the new word.
* @param joiner The function to merge a list of strings into the cased String.
*/
StringCase(final Predicate<Character> splitter, final boolean preserveSplit, final Function<String[],String> joiner) {
StringCase(final Predicate<Character> splitter, final boolean preserveSplit, final Function<String[], String> joiner) {
this.splitter = splitter;
this.preserveSplit = preserveSplit;
this.joiner = joiner;
}

/**
* Creates a cased string from a collection of segments.
* @param segments the segments to create the CasedString from.
* @return a CasedString
*/
public String assemble(String[] segments) {
return segments.length == 0 ? null : 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.
*/
public String[] getSegments(String string) {
if (string == null) {
return new String[0];
}
if (string.isEmpty()) {
return new String[]{""};
}
List<String> lst = new ArrayList<>();
StringBuilder sb = new StringBuilder();
for (char c : string.toCharArray()) {
if (splitter.test(c)) {
if (sb.length() > 0) {
lst.add(sb.toString());
sb.setLength(0);
}
if (preserveSplit) {
sb.append(c);
}
} else {
sb.append(c);
}
}
if (sb.length() > 0) {
lst.add(sb.toString());
}
return lst.toArray(new String[0]);
}
}

/**
Expand All @@ -89,31 +153,17 @@ public enum StringCase {
* @param string The string.
*/
public CasedString(StringCase stringCase, String string) {
this.string = string;
this.string = string == null ? null : stringCase.assemble(stringCase.getSegments(string.trim()));
this.stringCase = stringCase;
}

private String[] split() {
List<String> lst = new ArrayList<>();
StringBuilder sb = new StringBuilder();
for (char c : string.toCharArray())
{
if (stringCase.splitter.test(c)) {
if (sb.length() > 0) {
lst.add(sb.toString());
sb.setLength(0);
}
if (stringCase.preserveSplit) {
sb.append(c);
}
} else {
sb.append(c);
}
}
if (sb.length() > 0) {
lst.add(sb.toString());
}
return lst.toArray(new String[0]);
/**
* 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);
}

/**
Expand All @@ -126,7 +176,7 @@ public String toCase(StringCase stringCase) {
if (stringCase == this.stringCase) {
return string;
}
return stringCase.joiner.apply(split());
return string == null ? null : stringCase.joiner.apply(getSegments());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,13 +273,13 @@ public void setCopyrightMessage(String copyrightMessage) {
public void setAddLicenseHeaders(AddLicenseHeaders setting) {
switch (setting.getNative()) {
case TRUE:
setAddLicense(true);
setAddlicense(true);
break;
case FALSE:
setAddLicense(false);
setAddlicense(false);
break;
case FORCED:
setAddLicense(true);
setAddlicense(true);
setForce(true);
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ private ReportConfiguration generateConfig(Option option, String... args) {
}

private String antName(Option option) {
CasedString name = new CasedString(CasedString.StringCase.Kebab, option.getLongOpt());
return WordUtils.uncapitalize(name.toCase(CasedString.StringCase.Camel));
CasedString name = new CasedString(CasedString.StringCase.KEBAB, option.getLongOpt());
return WordUtils.uncapitalize(name.toCase(CasedString.StringCase.CAMEL));
}

@Override
Expand Down Expand Up @@ -354,10 +354,10 @@ public void setUp() {
StringBuilder childElements = new StringBuilder();
StringBuilder attributes = new StringBuilder();
for (Pair<String,String> pair : lst) {
CasedString name = new CasedString(CasedString.StringCase.Camel, pair.getKey());
CasedString name = new CasedString(CasedString.StringCase.CAMEL, pair.getKey());
AntOption workingOption = option;
if (!name.toString().equals(option.name)) {
String optionName = name.toCase(CasedString.StringCase.Kebab).toLowerCase();
String optionName = name.toCase(CasedString.StringCase.KEBAB).toLowerCase();
Optional<Option> opt = testMap.keySet().stream().filter(o -> o.getLongOpt().equals(optionName)).findFirst();
if (opt.isPresent()) {
workingOption = new AntOption(opt.get(), optionName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ private static void writeMethods(FileWriter writer, List<AntOption> options, Wri

private static String getAttributeBody(AntOption option) throws IOException {
return option.hasArg() ? format(" setArg(%s, %s);%n", option.keyValue(), option.name)
: format(" if (%s) {%n setArg(%s, null);%n }%n", option.name, option.keyValue());
: format(" if (%1$s) { setArg(%2$s, null); } else { removeArg(%2$s); }", option.name, option.keyValue());
}

private static String getElementClass(AntOption option) throws IOException {
Expand All @@ -154,7 +154,7 @@ private static class AntOption {

AntOption(Option option) {
this.option = option;
name = WordUtils.uncapitalize(new CasedString(StringCase.Kebab, option.getLongOpt()).toCase(StringCase.Camel));
name = new CasedString(StringCase.KEBAB, option.getLongOpt()).toCase(StringCase.CAMEL);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ public static void main(String[] args) throws IOException {
Options options = new Options();

OptionCollection.buildOptions().getOptions().stream().filter(MAVEN_FILTER).forEach(options::addOption);

File file = new File(new File(new File(destDir), packageName.replaceAll("\\.", File.separator)),className+".java");
String pkgName = String.join(File.separator,new CasedString(StringCase.DOT, packageName).getSegments());
File file = new File(new File(new File(destDir), pkgName),className+".java");
System.out.println("Creating "+file);
file.getParentFile().mkdirs();
try (InputStream template = MavenGenerator.class.getResourceAsStream("/Maven.tpl");
Expand Down Expand Up @@ -109,7 +109,7 @@ public static void main(String[] args) throws IOException {
private static void writeMethods(FileWriter writer, Options options) throws IOException {
for (Option option : options.getOptions()) {
if (option.getLongOpt() != null) {
String name = WordUtils.uncapitalize(new CasedString(StringCase.Kebab, option.getLongOpt()).toCase(StringCase.Camel));
String name = new CasedString(StringCase.KEBAB, option.getLongOpt()).toCase(StringCase.CAMEL);
String desc = option.getDescription().replace("<","&lt;").replace(">","&gt;");
writer.append(format(" /**%n * %s%n * @param %s the argument.%n", desc, name));
if (option.isDeprecated()) {
Expand Down
14 changes: 6 additions & 8 deletions apache-rat-tools/src/main/java/org/apache/rat/tools/Naming.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,8 @@
import org.apache.commons.text.WordUtils;
import org.apache.commons.csv.CSVPrinter;

import java.io.File;
import java.io.IOException;
import java.io.FileWriter;
import java.util.List;
import java.util.function.Predicate;

import org.apache.rat.OptionCollection;
Expand Down Expand Up @@ -59,7 +57,7 @@ public static void main(String[] args) throws IOException {
printer.printRecord("CLI", "Maven", "Ant", "Description");
for (Option option : options.getOptions()) {
if (option.getLongOpt() != null) {
CasedString opt = new CasedString(StringCase.Kebab, option.getLongOpt());
CasedString opt = new CasedString(StringCase.KEBAB, option.getLongOpt());
String mavenCell = mavenFilter.test(option) ? mavenFunctionName(option, opt) : "-- not supported --";
String antCell = antFilter.test(option) ? antFunctionName(option, opt) : "-- not supported --";
printer.printRecord(opt, mavenCell, antCell, option.getDescription());
Expand All @@ -73,13 +71,13 @@ public static String mavenFunctionName(Option option, CasedString name) {
if (option.isDeprecated()) {
sb.append("@Deprecated").append(System.lineSeparator());
}
sb.append(format("@Parameter(property = 'rat.%s'", WordUtils.uncapitalize(name.toCase(StringCase.Camel))));
sb.append(format("@Parameter(property = 'rat.%s'", name.toCase(StringCase.CAMEL)));
if (option.isRequired()) {
sb.append(" required = true");
}
sb.append(format(")%n public void %s%s(%s %s)", option.hasArgs() ? "add" : "set",
WordUtils.capitalize(name.toCase(StringCase.Camel)), option.hasArg() ? "String " : "boolean ",
WordUtils.uncapitalize(name.toCase(StringCase.Camel))));
WordUtils.capitalize(name.toCase(StringCase.CAMEL)), option.hasArg() ? "String " : "boolean ",
name.toCase(StringCase.CAMEL)));
return sb.toString();
}

Expand All @@ -89,9 +87,9 @@ private static String antFunctionName(Option option, CasedString name) {
sb.append("@Deprecated").append(System.lineSeparator());
}
if (option.hasArgs()) {
sb.append(format("<rat:report>%n <%1$s>text</%1$s>%n</rat:report>", WordUtils.uncapitalize(name.toCase(StringCase.Camel))));
sb.append(format("<rat:report>%n <%1$s>text</%1$s>%n</rat:report>", name.toCase(StringCase.CAMEL)));
} else {
sb.append(format("<rat:report %s = 'text'/>", WordUtils.uncapitalize(name.toCase(StringCase.Camel))));
sb.append(format("<rat:report %s = 'text'/>", name.toCase(StringCase.CAMEL)));
}
return sb.toString();
}
Expand Down
8 changes: 8 additions & 0 deletions apache-rat-tools/src/main/resources/Ant.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@ ${constructor}
}
}

/**
* remove a key from the argument list.
* @param key the key to remvoe from the map.
*/
protected void removeArg(String key) {
args.remove(key);
}

/**
* A child element.
*/
Expand Down

0 comments on commit 7bb8b02

Please sign in to comment.