From 810d4f07da0aef5bb7733625d1b58de795b79c22 Mon Sep 17 00:00:00 2001 From: Gabriele-Cardosi Date: Thu, 11 Jul 2024 12:20:32 +0200 Subject: [PATCH] [7.67.x-incubator-kie-issues#1382] Backport --- .../org/drools/core/util/StringUtils.java | 22 +++- .../org/drools/core/util/StringUtilsTest.java | 105 ++++++++++++++++++ 2 files changed, 125 insertions(+), 2 deletions(-) diff --git a/drools-core/src/main/java/org/drools/core/util/StringUtils.java b/drools-core/src/main/java/org/drools/core/util/StringUtils.java index 78794ddb1be..f4435231745 100644 --- a/drools-core/src/main/java/org/drools/core/util/StringUtils.java +++ b/drools-core/src/main/java/org/drools/core/util/StringUtils.java @@ -976,8 +976,23 @@ public static String extractFirstIdentifier(String string, int start) { return builder.toString(); } + /** + * Method that tries to extract identifiers from a Srting. + * First, it tries to identify "quoted" part, that should be ignored. + * Then, it tries to extract a String that is valid as java identifier. + * If an identifier is found, returns the last index of the identifier itself, otherwise the length of the string itself + * + * {@link Character#isJavaIdentifierStart} + * {@link Character#isJavaIdentifierPart} + * @param string + * @param builder + * @param start + * @return + */ public static int extractFirstIdentifier(String string, StringBuilder builder, int start) { boolean isQuoted = false; + boolean isDoubleQuoted = false; + boolean isSingleQuoted = false; boolean started = false; int i = start; for (; i < string.length(); i++) { @@ -985,13 +1000,16 @@ public static int extractFirstIdentifier(String string, StringBuilder builder, i if (!isQuoted && Character.isJavaIdentifierStart(ch)) { builder.append(ch); started = true; - } else if (ch == '"' || ch == '\'') { - isQuoted = !isQuoted; + } else if (ch == '"') { + isDoubleQuoted = !isQuoted && !isDoubleQuoted; + } else if (ch == '\'') { + isSingleQuoted = !isQuoted && !isSingleQuoted; } else if (started && Character.isJavaIdentifierPart(ch)) { builder.append(ch); } else if (started) { break; } + isQuoted = isDoubleQuoted || isSingleQuoted; } return i; } diff --git a/drools-core/src/test/java/org/drools/core/util/StringUtilsTest.java b/drools-core/src/test/java/org/drools/core/util/StringUtilsTest.java index 60edd44f677..ebacf27a9ae 100644 --- a/drools-core/src/test/java/org/drools/core/util/StringUtilsTest.java +++ b/drools-core/src/test/java/org/drools/core/util/StringUtilsTest.java @@ -298,6 +298,111 @@ public boolean isSnapshot() { } } + @Test + public void testExtractFirstIdentifierWithStringBuilder() { + // Not-quoted string, interpreted as identifier + String string = "IDENTIFIER"; + String expected = string; + StringBuilder builder = new StringBuilder(); + int start = 0; + int retrieved = StringUtils.extractFirstIdentifier(string, builder, start); + assertThat(retrieved).isEqualTo(string.length()); // retrieved size is equals to the length of given string + assertThat(builder.toString()).isEqualTo(expected); + + // Quoted string, not interpreted as identifier + string = "\"IDENTIFIER\""; + expected = ""; + builder = new StringBuilder(); + retrieved = StringUtils.extractFirstIdentifier(string, builder, start); + assertThat(retrieved).isEqualTo(string.length()); + assertThat(builder.toString()).isEqualTo(expected); + + // Only the not-quoted string, and its size, is returned + string = "IDENTIFIER \""; + expected = "IDENTIFIER"; + builder = new StringBuilder(); + retrieved = StringUtils.extractFirstIdentifier(string, builder, start); + assertThat(retrieved).isEqualTo(expected.length()); // it returns the index where the identifier ends + assertThat(builder.toString()).isEqualTo(expected); + + string = "IDENTIFIER \"the_identifier"; + expected = "IDENTIFIER"; + builder = new StringBuilder(); + retrieved = StringUtils.extractFirstIdentifier(string, builder, start); + assertThat(retrieved).isEqualTo(expected.length()); // it returns the index where the identifier ends + assertThat(builder.toString()).isEqualTo(expected); + + string = "\"the_identifier\" IDENTIFIER"; + expected = "IDENTIFIER"; + builder = new StringBuilder(); + retrieved = StringUtils.extractFirstIdentifier(string, builder, start); + assertThat(retrieved).isEqualTo(string.length()); // it returns the index where the identifier ends + assertThat(builder.toString()).isEqualTo(expected); + + // Quoted string, not interpreted as identifier, starting at arbitrary position + string = "THIS IS BEFORE \"IDENTIFIER\""; + expected = ""; + builder = new StringBuilder(); + start = 14; + retrieved = StringUtils.extractFirstIdentifier(string, builder, start); + assertThat(retrieved).isEqualTo(string.length()); + assertThat(builder.toString()).isEqualTo(expected); + + // Only the not-quoted string, and its size, is returned, starting at arbitrary position + string = "THIS IS BEFORE IDENTIFIER \""; + expected = "IDENTIFIER"; + builder = new StringBuilder(); + retrieved = StringUtils.extractFirstIdentifier(string, builder, start); + assertThat(retrieved).isEqualTo(25); // it returns the index where the identifier ends + assertThat(builder.toString()).isEqualTo(expected); + + string = "IDENTIFIER \"the_identifier"; + expected = ""; + builder = new StringBuilder(); + start = 10; + retrieved = StringUtils.extractFirstIdentifier(string, builder, start); + assertThat(retrieved).isEqualTo(string.length()); // it returns the index where the identifier ends + assertThat(builder.toString()).isEqualTo(expected); + + string = "IDENTIFIER \"the_identifier"; + expected = ""; + builder = new StringBuilder(); + start = 10; + retrieved = StringUtils.extractFirstIdentifier(string, builder, start); + assertThat(retrieved).isEqualTo(string.length()); // it returns the index where the identifier ends + assertThat(builder.toString()).isEqualTo(expected); + + string = "\"not an ' identifier\""; + expected = ""; + builder = new StringBuilder(); + start = 0; + retrieved = StringUtils.extractFirstIdentifier(string, builder, start); + assertThat(retrieved).isEqualTo(string.length()); // it returns the whole string length + assertThat(builder.toString()).isEqualTo(expected); + + string = "'not an \" identifier'"; + expected = ""; + builder = new StringBuilder(); + retrieved = StringUtils.extractFirstIdentifier(string, builder, start); + assertThat(retrieved).isEqualTo(string.length()); // it returns the whole string length + assertThat(builder.toString()).isEqualTo(expected); + + string = "'not an \" identifier\"'"; + expected = ""; + builder = new StringBuilder(); + retrieved = StringUtils.extractFirstIdentifier(string, builder, start); + assertThat(retrieved).isEqualTo(string.length()); // it returns the whole string length + assertThat(builder.toString()).isEqualTo(expected); + + string = "\"an \" IDENTIFIER"; + expected = "IDENTIFIER"; + builder = new StringBuilder(); + retrieved = StringUtils.extractFirstIdentifier(string, builder, start); + assertThat(retrieved).isEqualTo(string.length()); // it returns the index where the identifier ends + assertThat(builder.toString()).isEqualTo(expected); + + } + @Test public void testSplitStatements() { String text =