in src/main/java/org/apache/maven/xinclude/stax/XPointerParser.java [44:156]
public static void parseXPointer(String xpointerString, XPointer xpointer) throws InvalidXPointerException {
final Tokens tokens = new Tokens(); // tokens
// scan the XPointer expression
int length = xpointerString.length();
boolean success = Scanner.scanExpr(tokens, xpointerString, 0, length);
if (!success) {
throw new InvalidXPointerException("Invalid XPointer expression", xpointerString);
}
while (tokens.hasMore()) {
int token = tokens.nextToken();
switch (token) {
case Tokens.XPTRTOKEN_SHORTHAND: {
// The shorthand name
token = tokens.nextToken();
String shortHandPointerName = tokens.getTokenString(token);
if (shortHandPointerName == null) {
throw new InvalidXPointerException("Invalid Shorthand XPointer", xpointerString);
}
if (!NCName.isValid(shortHandPointerName)) {
throw new InvalidXPointerException(
"Shorthand XPointer is not a valid NCName: " + shortHandPointerName, xpointerString);
}
xpointer.setShorthandPointer(shortHandPointerName);
break;
}
case Tokens.XPTRTOKEN_SCHEMENAME: {
// Retrieve the local name and prefix to form the scheme name
token = tokens.nextToken();
String prefix = tokens.getTokenString(token);
token = tokens.nextToken();
String localName = tokens.getTokenString(token);
String schemeName = prefix + localName;
// The next character should be an open parenthesis
int openParenCount = 0;
int closeParenCount = 0;
token = tokens.nextToken();
String openParen = tokens.getTokenString(token);
if (!Objects.equals(openParen, "XPTRTOKEN_OPEN_PAREN")) {
// can not have more than one ShortHand Pointer
if (token == Tokens.XPTRTOKEN_SHORTHAND) {
throw new InvalidXPointerException("Multiple Shorthand pointers", xpointerString);
} else {
throw new InvalidXPointerException("Invalid XPointer expression", xpointerString);
}
}
openParenCount++;
// followed by zero or more ( and the schemeData
String schemeData = null;
while (tokens.hasMore()) {
token = tokens.nextToken();
schemeData = tokens.getTokenString(token);
if (!Objects.equals(schemeData, "XPTRTOKEN_OPEN_PAREN")) {
break;
}
openParenCount++;
}
token = tokens.nextToken();
schemeData = tokens.getTokenString(token);
// followed by the same number of )
if (tokens.hasMore()) {
token = tokens.nextToken();
String closeParen = tokens.getTokenString(token);
if (!Objects.equals(closeParen, "XPTRTOKEN_CLOSE_PAREN")) {
throw new InvalidXPointerException(
"SchemeData not followed by close parenthesis", xpointerString);
}
} else {
throw new InvalidXPointerException(
"SchemeData not followed by close parenthesis", xpointerString);
}
closeParenCount++;
while (tokens.hasMore()) {
if (!Objects.equals(tokens.getTokenString(tokens.peekToken()), "XPTRTOKEN_OPEN_PAREN")) {
break;
}
closeParenCount++;
}
// check if the number of open parenthesis are equal to the number of close parenthesis
if (openParenCount != closeParenCount) {
throw new InvalidXPointerException(
"Unbalanced parenthesis in XPointer expression", xpointerString);
}
// Perform scheme specific parsing of the pointer part, make this more generic for any pointer part?
if (schemeName.equals(ELEMENT_SCHEME_NAME)) {
PointerPart elementSchemePointer = ElementPointerPart.parseFromString(schemeData);
xpointer.addPointerPart(elementSchemePointer);
} // Else an unknown scheme.
break;
}
default:
throw new InvalidXPointerException("Invalid XPointer expression", xpointerString);
}
}
}