in drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/lang/XpathAnalysis.java [132:286]
public static XpathAnalysis analyze(String xpath) {
List<XpathPart> parts = new ArrayList<>();
boolean lazyPath = false;
int i = 0;
if (xpath.length() >= 1 && xpath.charAt(0) == '/') {
i = 1;
} else if (xpath.length() >= 2 && xpath.charAt(0) == '?' && xpath.charAt(1) == '/') {
lazyPath = true;
i = 2;
} else {
return new XpathAnalysis(parts, "An oopath expression has to start with '/' or '?/'");
}
List<String> constraints = new ArrayList<>();
String inlineCast = null;
int index = -1;
int lastStart = i;
int nestedParam = 0;
int nestedSquare = 0;
boolean iterate = true;
boolean isQuoted = false;
boolean isDoubleQuoted = false;
boolean isInlineCast = false;
String field = null;
String error = null;
int partStart = 0;
for (; i < xpath.length() && error == null; i++) {
switch (xpath.charAt(i)) {
case '/':
case '.':
if (!isQuoted && nestedParam == 0 && nestedSquare == 0) {
if (field == null) {
field = xpath.substring(lastStart, xpath.charAt(i-1) == '?' ? i-1 : i).trim();
} else if (isInlineCast) {
inlineCast = xpath.substring(lastStart, xpath.charAt(i-1) == '?' ? i-1 : i).trim();
isInlineCast = false;
}
parts.add(new XpathPart(field, iterate, lazyPath, constraints, inlineCast, index, partStart));
partStart = i;
iterate = xpath.charAt(i) == '/';
if (xpath.charAt(i-1) == '?') {
if (lazyPath) {
error = "It is not possible to have 2 non-reactive parts in the same oopath";
break;
} else {
lazyPath = true;
}
}
constraints = new ArrayList<>();
inlineCast = null;
index = -1;
lastStart = i + 1;
field = null;
}
break;
case '(':
if (!isQuoted) {
nestedParam++;
}
break;
case ')':
if (!isQuoted) {
nestedParam--;
if (nestedParam < 0) {
error = "Unbalanced parenthesis";
}
}
break;
case '#':
if (!isQuoted && nestedParam == 0 && nestedSquare == 0) {
if (field == null) {
field = xpath.substring( lastStart, i ).trim();
}
lastStart = i+1;
isInlineCast = true;
}
break;
case '[':
if (!isQuoted && nestedParam == 0) {
if (nestedSquare == 0) {
if (field == null) {
field = xpath.substring( lastStart, i ).trim();
} else if (isInlineCast) {
inlineCast = xpath.substring( lastStart, i ).trim();
isInlineCast = false;
}
lastStart = i+1;
}
nestedSquare++;
}
break;
case ']':
if (!isQuoted && nestedParam == 0) {
nestedSquare--;
if (nestedSquare == 0) {
String constraint = xpath.substring( lastStart, i ).trim();
if ( Character.isDigit(constraint.charAt( 0 )) ) {
try {
index = Integer.parseInt( constraint );
} catch (Exception e) {
constraints.add( constraint );
}
} else {
constraints.add( constraint );
}
} else if (nestedSquare < 0) {
error = "Unbalanced square brackets";
}
}
break;
case ',':
if (!isQuoted && nestedParam == 0 && nestedSquare == 1) {
String constraint = xpath.substring(lastStart, i).trim();
constraints.add(constraint);
lastStart = i+1;
}
break;
case '"':
if (isQuoted) {
if (isDoubleQuoted) {
isQuoted = false;
isDoubleQuoted = false;
}
} else {
isQuoted = true;
isDoubleQuoted = true;
}
break;
case '\'':
if (isQuoted) {
if (!isDoubleQuoted) {
isQuoted = false;
}
} else {
isQuoted = true;
}
break;
}
}
if (field == null) {
field = xpath.substring(lastStart).trim();
} else if (isInlineCast) {
inlineCast = xpath.substring(lastStart).trim();
isInlineCast = false;
}
parts.add(new XpathPart(field, iterate, lazyPath, constraints, inlineCast, index, partStart));
return new XpathAnalysis(parts, error);
}