protected Constraint parseConstraint( TokenStream tokens,
TypeSystem typeSystem,
Source source ) {
Constraint constraint = null;
Position pos = tokens.nextPosition();
if (tokens.canConsume("(")) {
constraint = parseConstraint(tokens, typeSystem, source);
tokens.consume(")");
} else if (tokens.canConsume("NOT")) {
tokens.canConsume('(');
constraint = new Not(parseConstraint(tokens, typeSystem, source));
tokens.canConsume(')');
} else if (tokens.canConsume("CONTAINS", "(")) {
// Either 'selectorName.propertyName', or 'selectorName.*' or 'propertyName' ...
String first = tokens.consume();
SelectorName selectorName = null;
String propertyName = null;
if (tokens.canConsume(".", "*")) {
selectorName = new SelectorName(removeBracketsAndQuotes(first));
} else if (tokens.canConsume('.')) {
selectorName = new SelectorName(removeBracketsAndQuotes(first));
propertyName = parseName(tokens, typeSystem);
} else {
if (!(source instanceof Selector)) {
String msg = GraphI18n.functionIsAmbiguous.text("CONTAINS()", pos.getLine(), pos.getColumn());
throw new ParsingException(pos, msg);
}
selectorName = ((Selector)source).getName();
propertyName = first;
}
tokens.consume(',');
// Followed by the full text search expression ...
String expression = removeBracketsAndQuotes(tokens.consume());
Term term = parseFullTextSearchExpression(expression, tokens.previousPosition());
tokens.consume(")");
constraint = new FullTextSearch(selectorName, propertyName, expression, term);
} else if (tokens.canConsume("ISSAMENODE", "(")) {
SelectorName selectorName = null;
if (tokens.matches(ANY_VALUE, ")")) {
if (!(source instanceof Selector)) {
String msg = GraphI18n.functionIsAmbiguous.text("ISSAMENODE()", pos.getLine(), pos.getColumn());
throw new ParsingException(pos, msg);
}
selectorName = ((Selector)source).getName();
} else {
selectorName = parseSelectorName(tokens);
tokens.consume(',');
}
String path = parsePath(tokens, typeSystem);
tokens.consume(')');
constraint = new SameNode(selectorName, path);
} else if (tokens.canConsume("ISCHILDNODE", "(")) {
SelectorName selectorName = null;
if (tokens.matches(ANY_VALUE, ")")) {
if (!(source instanceof Selector)) {
String msg = GraphI18n.functionIsAmbiguous.text("ISCHILDNODE()", pos.getLine(), pos.getColumn());
throw new ParsingException(pos, msg);
}
selectorName = ((Selector)source).getName();
} else {
selectorName = parseSelectorName(tokens);
tokens.consume(',');
}
String path = parsePath(tokens, typeSystem);
tokens.consume(')');
constraint = new ChildNode(selectorName, path);
} else if (tokens.canConsume("ISDESCENDANTNODE", "(")) {
SelectorName selectorName = null;
if (tokens.matches(ANY_VALUE, ")")) {
if (!(source instanceof Selector)) {
String msg = GraphI18n.functionIsAmbiguous.text("ISDESCENDANTNODE()", pos.getLine(), pos.getColumn());
throw new ParsingException(pos, msg);
}
selectorName = ((Selector)source).getName();
} else {
selectorName = parseSelectorName(tokens);
tokens.consume(',');
}
String path = parsePath(tokens, typeSystem);
tokens.consume(')');
constraint = new DescendantNode(selectorName, path);
} else {
// First try a property existance ...
Position pos2 = tokens.nextPosition();
constraint = parsePropertyExistance(tokens, typeSystem, source);
if (constraint == null) {
// Try to parse as a dynamic operand ...
DynamicOperand left = parseDynamicOperand(tokens, typeSystem, source);
if (left != null) {
if (tokens.matches('(') && left instanceof PropertyValue) {
// This was probably a bad function that we parsed as the start of a dynamic operation ...
String name = ((PropertyValue)left).getPropertyName(); // this may be the function name
String msg = GraphI18n.expectingConstraintCondition.text(name, pos2.getLine(), pos2.getColumn());
throw new ParsingException(pos, msg);
}
if (tokens.matches("IN", "(") || tokens.matches("NOT", "IN", "(")) {
boolean not = tokens.canConsume("NOT");
Collection<StaticOperand> staticOperands = parseInClause(tokens, typeSystem);