diff --git a/src/main/java/rife/tools/StringUtils.java b/src/main/java/rife/tools/StringUtils.java index e9f08da..716bdc5 100644 --- a/src/main/java/rife/tools/StringUtils.java +++ b/src/main/java/rife/tools/StringUtils.java @@ -2481,6 +2481,46 @@ public static boolean filter(String name, Pattern[] included, Pattern[] excluded return accepted; } + /** + * Filters the given string by removing any characters that are not valid in a Java identifier. + *
+ * If a valid identifier can't be generated, {@code null} will be returned. + * + * @param value the string to be filtered + * @return the filtered string as a valid Java identifier; or + *
{@code null} if a valid Java identifier couldn't be generated + * @since 1.8.0 + */ + public static String filterAsIdentifier(String value) { + if (null == value || value.isEmpty()) { + return null; + } + + StringBuilder identifier = null; + for (int i = 0; i < value.length(); i++) { + var c = value.charAt(i); + if (identifier == null) { + if (!Character.isJavaIdentifierStart(c)) { + identifier = new StringBuilder(value.substring(0, i)); + } + } + else if ((identifier.isEmpty() && Character.isJavaIdentifierStart(c)) || + (!identifier.isEmpty() && Character.isJavaIdentifierPart(c))) { + identifier.append(c); + } + } + + if (identifier == null) { + return value; + } + + if (identifier.isEmpty()) { + return null; + } + + return identifier.toString(); + } + /** * Ensure that the first character of the provided string is upper case. * diff --git a/src/test/java/rife/tools/TestStringUtils.java b/src/test/java/rife/tools/TestStringUtils.java index 26aa09f..d56e235 100644 --- a/src/test/java/rife/tools/TestStringUtils.java +++ b/src/test/java/rife/tools/TestStringUtils.java @@ -637,6 +637,35 @@ void testFilterMultipleNonMatching() { assertFalse(StringUtils.filter("test", new Pattern[]{Pattern.compile("x"), Pattern.compile("b")}, new Pattern[]{Pattern.compile("a"), Pattern.compile("t")}, false)); } + @Test void testFilterAsIdentifierWithValidString() { + var validIdentifier = "validIdentifier"; + assertEquals(validIdentifier, StringUtils.filterAsIdentifier(validIdentifier)); + } + + @Test void testFilterAsIdentifierWithInvalidString() { + var invalidIdentifier = "1nvalidIdentifier"; + assertEquals("nvalidIdentifier", StringUtils.filterAsIdentifier(invalidIdentifier)); + } + + @Test void testFilterAsIdentifierWithEmptyString() { + var emptyString = ""; + assertNull(StringUtils.filterAsIdentifier(emptyString)); + } + + @Test void testFilterAsIdentifierWithNullValue() { + assertNull(StringUtils.filterAsIdentifier(null)); + } + + @Test void testFilterAsIdentifierWithInvalidCharacters() { + var stringWithInvalidChars = "some@string)with%invalid^chars"; + assertEquals("somestringwithinvalidchars", StringUtils.filterAsIdentifier(stringWithInvalidChars)); + } + + @Test void testFilterAsIdentifierWithAllInvalidCharacters() { + var stringWithInvalidChars = "12987@)%^"; + assertNull(StringUtils.filterAsIdentifier(stringWithInvalidChars)); + } + @Test void testCapitalize() { assertNull(StringUtils.capitalize(null));