return node.childrenAccept(this, constraintNode);
}
public Object visit(ASTPredicate node, Object data)
{
NAryQueryNode parent = (NAryQueryNode)data;
int type = node.getOperationType();
QueryNode predicateNode;
try
{
final InternalQName[] tmp = new InternalQName[2];
final ASTLiteral[] value = new ASTLiteral[1];
node.childrenAccept(new DefaultParserVisitor()
{
public Object visit(ASTIdentifier node, Object data)
{
if (tmp[0] == null)
{
tmp[0] = node.getName();
}
else if (tmp[1] == null)
{
tmp[1] = node.getName();
}
return data;
}
public Object visit(ASTLiteral node, Object data)
{
value[0] = node;
return data;
}
public Object visit(ASTLowerFunction node, Object data)
{
getIdentifier(node);
return data;
}
public Object visit(ASTUpperFunction node, Object data)
{
getIdentifier(node);
return data;
}
private void getIdentifier(SimpleNode node)
{
if (node.jjtGetNumChildren() > 0)
{
Node n = node.jjtGetChild(0);
if (n instanceof ASTIdentifier)
{
ASTIdentifier identifier = (ASTIdentifier)n;
if (tmp[0] == null)
{
tmp[0] = identifier.getName();
}
else if (tmp[1] == null)
{
tmp[1] = identifier.getName();
}
}
}
}
}, data);
InternalQName identifier = tmp[0];
if (identifier != null && identifier.equals(Constants.JCR_PATH))
{
if (tmp[1] != null)
{
// simply ignore, this is a join of a mixin node type
}
else
{
createPathQuery(value[0].getValue(), parent.getType());
}
// done
return data;
}
if (type == QueryConstants.OPERATION_BETWEEN)
{
AndQueryNode between = factory.createAndQueryNode(parent);
RelationQueryNode rel =
createRelationQueryNode(between, identifier, QueryConstants.OPERATION_GE_GENERAL,
(ASTLiteral)node.children[1]);
node.childrenAccept(this, rel);
between.addOperand(rel);
rel =
createRelationQueryNode(between, identifier, QueryConstants.OPERATION_LE_GENERAL,
(ASTLiteral)node.children[2]);
node.childrenAccept(this, rel);
between.addOperand(rel);
predicateNode = between;
}
else if (type == QueryConstants.OPERATION_GE_GENERAL || type == QueryConstants.OPERATION_GT_GENERAL
|| type == QueryConstants.OPERATION_LE_GENERAL || type == QueryConstants.OPERATION_LT_GENERAL
|| type == QueryConstants.OPERATION_NE_GENERAL || type == QueryConstants.OPERATION_EQ_GENERAL)
{
predicateNode = createRelationQueryNode(parent, identifier, type, value[0]);
node.childrenAccept(this, predicateNode);
}
else if (type == QueryConstants.OPERATION_LIKE)
{
ASTLiteral pattern = value[0];
if (node.getEscapeString() != null)
{
if (node.getEscapeString().length() == 1)
{
// backslash is the escape character we use internally
pattern.setValue(translateEscaping(pattern.getValue(), node.getEscapeString().charAt(0), '\\'));
}
else
{
throw new IllegalArgumentException("ESCAPE string value must have length 1: '"
+ node.getEscapeString() + "'");
}
}
else
{
// no escape character specified.
// if the pattern contains any backslash characters we need
// to escape them.
pattern.setValue(pattern.getValue().replaceAll("\\\\", "\\\\\\\\"));
}
predicateNode = createRelationQueryNode(parent, identifier, type, pattern);
node.childrenAccept(this, predicateNode);
}
else if (type == QueryConstants.OPERATION_IN)
{
OrQueryNode in = factory.createOrQueryNode(parent);
for (int i = 1; i < node.children.length; i++)
{
RelationQueryNode rel =
createRelationQueryNode(in, identifier, QueryConstants.OPERATION_EQ_VALUE,
(ASTLiteral)node.children[i]);
node.childrenAccept(this, rel);
in.addOperand(rel);
}
predicateNode = in;
}
else if (type == QueryConstants.OPERATION_NULL || type == QueryConstants.OPERATION_NOT_NULL)
{
predicateNode = createRelationQueryNode(parent, identifier, type, null);
}
else if (type == QueryConstants.OPERATION_SIMILAR)
{
ASTLiteral literal;
if (node.children.length == 1)
{
literal = (ASTLiteral)node.children[0];
}
else
{
literal = (ASTLiteral)node.children[1];
}
predicateNode = createRelationQueryNode(parent, identifier, type, literal);
}
else if (type == QueryConstants.OPERATION_SPELLCHECK)
{
predicateNode =
createRelationQueryNode(parent, Constants.JCR_PRIMARYTYPE, type, (ASTLiteral)node.children[0]);
}
else
{
throw new IllegalArgumentException("Unknown operation type: " + type);
}
}
catch (ArrayIndexOutOfBoundsException e)
{
throw new IllegalArgumentException("Too few arguments in predicate");
}
if (predicateNode != null)
{
parent.addOperand(predicateNode);
}
return data;
}