Skip to content

Commit

Permalink
[incubator-kie-issues#1382] Fix identifier retrieval for quoted strin…
Browse files Browse the repository at this point in the history
…gs (#6021)

Co-authored-by: Gabriele-Cardosi <[email protected]>
  • Loading branch information
gitgabrio and Gabriele-Cardosi committed Jul 12, 2024
1 parent ddb72c6 commit 77cb730
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ private List<String> getPropertyNamesFromSimpleExpression(String expression) {
private int nextPropertyName(String expression, List<String> names, int cursor) {
StringBuilder propertyNameBuilder = new StringBuilder();
cursor = extractFirstIdentifier(expression, propertyNameBuilder, cursor);
if (propertyNameBuilder.length() == 0) {
if (propertyNameBuilder.isEmpty()) {
return cursor;
}

Expand Down
22 changes: 20 additions & 2 deletions drools-util/src/main/java/org/drools/util/StringUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -964,22 +964,40 @@ public static String extractFirstIdentifier(String string, int start) {
return builder.toString();
}

/**
* Method that tries to extract <b>identifiers</b> 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++) {
char ch = string.charAt(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;
}
Expand Down
105 changes: 105 additions & 0 deletions drools-util/src/test/java/org/drools/util/StringUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,111 @@ public void getPkgUUIDFromGAV() {
assertThat(retrieved).isEqualTo(expected);
}

@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 =
Expand Down

0 comments on commit 77cb730

Please sign in to comment.