use of org.apache.jackrabbit.spi.commons.query.NAryQueryNode in project jackrabbit by apache.
the class XPathQueryBuilder method createFunction.
/**
* Creates a function based on <code>node</code>.
*
* @param node the function node from the xpath tree.
* @param queryNode the current query node.
* @return the function node
*/
private QueryNode createFunction(SimpleNode node, QueryNode queryNode) {
// find out function name
String tmp = ((SimpleNode) node.jjtGetChild(0)).getValue();
String fName = tmp.substring(0, tmp.length() - 1);
try {
Name funName = resolver.getQName(fName);
if (FN_NOT.equals(funName) || FN_NOT_10.equals(funName)) {
if (queryNode instanceof NAryQueryNode) {
QueryNode not = factory.createNotQueryNode(queryNode);
((NAryQueryNode) queryNode).addOperand(not);
// @todo is this needed?
queryNode = not;
// traverse
if (node.jjtGetNumChildren() == 2) {
node.jjtGetChild(1).jjtAccept(this, queryNode);
} else {
exceptions.add(new InvalidQueryException("fn:not only supports one expression argument"));
}
} else {
exceptions.add(new InvalidQueryException("Unsupported location for function fn:not"));
}
} else if (XS_DATETIME.equals(funName)) {
// check arguments
if (node.jjtGetNumChildren() == 2) {
if (queryNode instanceof RelationQueryNode) {
RelationQueryNode rel = (RelationQueryNode) queryNode;
SimpleNode literal = (SimpleNode) node.jjtGetChild(1).jjtGetChild(0);
if (literal.getId() == JJTSTRINGLITERAL) {
String value = literal.getValue();
// strip quotes
value = value.substring(1, value.length() - 1);
Calendar c = ISO8601.parse(value);
if (c == null) {
exceptions.add(new InvalidQueryException("Unable to parse string literal for xs:dateTime: " + value));
} else {
rel.setDateValue(c.getTime());
}
} else {
exceptions.add(new InvalidQueryException("Wrong argument type for xs:dateTime"));
}
} else {
exceptions.add(new InvalidQueryException("Unsupported location for function xs:dateTime"));
}
} else {
// wrong number of arguments
exceptions.add(new InvalidQueryException("Wrong number of arguments for xs:dateTime"));
}
} else if (JCR_CONTAINS.equals(funName)) {
// check number of arguments
if (node.jjtGetNumChildren() == 3) {
if (queryNode instanceof NAryQueryNode) {
SimpleNode literal = (SimpleNode) node.jjtGetChild(2).jjtGetChild(0);
if (literal.getId() == JJTSTRINGLITERAL) {
TextsearchQueryNode contains = factory.createTextsearchQueryNode(queryNode, unescapeQuotes(literal.getValue()));
// assign property name
SimpleNode path = (SimpleNode) node.jjtGetChild(1);
path.jjtAccept(this, contains);
((NAryQueryNode) queryNode).addOperand(contains);
} else {
exceptions.add(new InvalidQueryException("Wrong argument type for jcr:contains"));
}
}
} else {
// wrong number of arguments
exceptions.add(new InvalidQueryException("Wrong number of arguments for jcr:contains"));
}
} else if (JCR_LIKE.equals(funName)) {
// check number of arguments
if (node.jjtGetNumChildren() == 3) {
if (queryNode instanceof NAryQueryNode) {
RelationQueryNode like = factory.createRelationQueryNode(queryNode, RelationQueryNode.OPERATION_LIKE);
((NAryQueryNode) queryNode).addOperand(like);
// assign property name
node.jjtGetChild(1).jjtAccept(this, like);
// check property name
if (like.getRelativePath() == null) {
exceptions.add(new InvalidQueryException("Wrong first argument type for jcr:like"));
}
SimpleNode literal = (SimpleNode) node.jjtGetChild(2).jjtGetChild(0);
if (literal.getId() == JJTSTRINGLITERAL) {
like.setStringValue(unescapeQuotes(literal.getValue()));
} else {
exceptions.add(new InvalidQueryException("Wrong second argument type for jcr:like"));
}
} else {
exceptions.add(new InvalidQueryException("Unsupported location for function jcr:like"));
}
} else {
// wrong number of arguments
exceptions.add(new InvalidQueryException("Wrong number of arguments for jcr:like"));
}
} else if (FN_TRUE.equals(funName)) {
if (queryNode.getType() == QueryNode.TYPE_RELATION) {
RelationQueryNode rel = (RelationQueryNode) queryNode;
rel.setStringValue("true");
} else {
exceptions.add(new InvalidQueryException("Unsupported location for true()"));
}
} else if (FN_FALSE.equals(funName)) {
if (queryNode.getType() == QueryNode.TYPE_RELATION) {
RelationQueryNode rel = (RelationQueryNode) queryNode;
rel.setStringValue("false");
} else {
exceptions.add(new InvalidQueryException("Unsupported location for false()"));
}
} else if (FN_POSITION.equals(funName)) {
if (queryNode.getType() == QueryNode.TYPE_RELATION) {
RelationQueryNode rel = (RelationQueryNode) queryNode;
if (rel.getOperation() == RelationQueryNode.OPERATION_EQ_GENERAL) {
// set dummy value to set type of relation query node
// will be overwritten when the tree is further parsed.
rel.setPositionValue(1);
rel.addPathElement(PATH_FACTORY.createElement(FN_POSITION_FULL));
} else {
exceptions.add(new InvalidQueryException("Unsupported expression with position(). Only = is supported."));
}
} else {
exceptions.add(new InvalidQueryException("Unsupported location for position()"));
}
} else if (FN_FIRST.equals(funName)) {
if (queryNode.getType() == QueryNode.TYPE_RELATION) {
((RelationQueryNode) queryNode).setPositionValue(1);
} else if (queryNode.getType() == QueryNode.TYPE_LOCATION) {
((LocationStepQueryNode) queryNode).setIndex(1);
} else {
exceptions.add(new InvalidQueryException("Unsupported location for first()"));
}
} else if (FN_LAST.equals(funName)) {
if (queryNode.getType() == QueryNode.TYPE_RELATION) {
((RelationQueryNode) queryNode).setPositionValue(LocationStepQueryNode.LAST);
} else if (queryNode.getType() == QueryNode.TYPE_LOCATION) {
((LocationStepQueryNode) queryNode).setIndex(LocationStepQueryNode.LAST);
} else {
exceptions.add(new InvalidQueryException("Unsupported location for last()"));
}
} else if (JCR_DEREF.equals(funName)) {
// check number of arguments
if (node.jjtGetNumChildren() == 3) {
boolean descendant = false;
if (queryNode.getType() == QueryNode.TYPE_LOCATION) {
LocationStepQueryNode loc = (LocationStepQueryNode) queryNode;
// remember if descendant axis
descendant = loc.getIncludeDescendants();
queryNode = loc.getParent();
((NAryQueryNode) queryNode).removeOperand(loc);
}
if (queryNode.getType() == QueryNode.TYPE_PATH) {
PathQueryNode pathNode = (PathQueryNode) queryNode;
pathNode.addPathStep(createDerefQueryNode(node, descendant, pathNode));
} else if (queryNode.getType() == QueryNode.TYPE_RELATION) {
RelationQueryNode relNode = (RelationQueryNode) queryNode;
DerefQueryNode deref = createDerefQueryNode(node, descendant, relNode.getRelativePath());
relNode.getRelativePath().addPathStep(deref);
} else {
exceptions.add(new InvalidQueryException("Unsupported location for jcr:deref()"));
}
}
} else if (JCR_SCORE.equals(funName)) {
if (queryNode.getType() == QueryNode.TYPE_ORDER) {
setOrderSpecPath(node, (OrderQueryNode) queryNode);
} else {
exceptions.add(new InvalidQueryException("Unsupported location for jcr:score()"));
}
} else if (FN_LOWER_CASE.equals(funName)) {
if (node.jjtGetNumChildren() == 2) {
if (queryNode.getType() == QueryNode.TYPE_RELATION) {
RelationQueryNode relNode = (RelationQueryNode) queryNode;
relNode.addOperand(factory.createPropertyFunctionQueryNode(relNode, PropertyFunctionQueryNode.LOWER_CASE));
// get property name
node.jjtGetChild(1).jjtAccept(this, relNode);
} else if (queryNode.getType() == QueryNode.TYPE_ORDER) {
((OrderQueryNode) queryNode).setFunction(FN_LOWER_CASE.getLocalName());
node.childrenAccept(this, queryNode);
} else {
exceptions.add(new InvalidQueryException("Unsupported location for fn:lower-case()"));
}
} else {
exceptions.add(new InvalidQueryException("Wrong number of argument for fn:lower-case()"));
}
} else if (FN_UPPER_CASE.equals(funName)) {
if (node.jjtGetNumChildren() == 2) {
if (queryNode.getType() == QueryNode.TYPE_RELATION) {
RelationQueryNode relNode = (RelationQueryNode) queryNode;
relNode.addOperand(factory.createPropertyFunctionQueryNode(relNode, PropertyFunctionQueryNode.UPPER_CASE));
// get property name
node.jjtGetChild(1).jjtAccept(this, relNode);
} else if (queryNode.getType() == QueryNode.TYPE_ORDER) {
((OrderQueryNode) queryNode).setFunction(FN_UPPER_CASE.getLocalName());
node.childrenAccept(this, queryNode);
} else {
exceptions.add(new InvalidQueryException("Unsupported location for fn:upper-case()"));
}
} else {
exceptions.add(new InvalidQueryException("Wrong number of argument for fn:upper-case()"));
}
} else if (REP_NORMALIZE.equals(funName)) {
if (node.jjtGetNumChildren() == 2) {
if (queryNode.getType() == QueryNode.TYPE_ORDER) {
((OrderQueryNode) queryNode).setFunction(REP_NORMALIZE.getLocalName());
node.childrenAccept(this, queryNode);
} else {
exceptions.add(new InvalidQueryException("Unsupported location for rep:normalize()"));
}
} else {
exceptions.add(new InvalidQueryException("Wrong number of argument for rep:normalize()"));
}
} else if (REP_SIMILAR.equals(funName)) {
if (node.jjtGetNumChildren() == 3) {
if (queryNode instanceof NAryQueryNode) {
NAryQueryNode parent = (NAryQueryNode) queryNode;
RelationQueryNode rel = factory.createRelationQueryNode(parent, RelationQueryNode.OPERATION_SIMILAR);
parent.addOperand(rel);
// assign path
node.jjtGetChild(1).jjtAccept(this, rel);
// get path string
node.jjtGetChild(2).jjtAccept(this, rel);
// check if string is set
if (rel.getStringValue() == null) {
exceptions.add(new InvalidQueryException("Second argument for rep:similar() must be of type string"));
}
} else {
exceptions.add(new InvalidQueryException("Unsupported location for rep:similar()"));
}
} else {
exceptions.add(new InvalidQueryException("Wrong number of arguments for rep:similar()"));
}
} else if (REP_SPELLCHECK.equals(funName) && queryNode.getType() != QueryNode.TYPE_PATH) {
if (node.jjtGetNumChildren() == 2) {
if (queryNode instanceof NAryQueryNode) {
NAryQueryNode parent = (NAryQueryNode) queryNode;
RelationQueryNode rel = factory.createRelationQueryNode(parent, RelationQueryNode.OPERATION_SPELLCHECK);
parent.addOperand(rel);
// get string to check
node.jjtGetChild(1).jjtAccept(this, rel);
// check if string is set
if (rel.getStringValue() == null) {
exceptions.add(new InvalidQueryException("Argument for rep:spellcheck() must be of type string"));
}
// set a dummy property name
rel.addPathElement(PATH_FACTORY.createElement(NameConstants.JCR_PRIMARYTYPE));
} else {
exceptions.add(new InvalidQueryException("Unsupported location for rep:spellcheck()"));
}
} else {
exceptions.add(new InvalidQueryException("Wrong number of arguments for rep:spellcheck()"));
}
} else if (queryNode.getType() == QueryNode.TYPE_RELATION) {
// use function name as name of a pseudo property in a relation
try {
Name name = resolver.getQName(fName + "()");
Path.Element element = PATH_FACTORY.createElement(name);
RelationQueryNode relNode = (RelationQueryNode) queryNode;
relNode.addPathElement(element);
} catch (NameException e) {
exceptions.add(e);
}
} else if (queryNode.getType() == QueryNode.TYPE_PATH) {
// use function name as name of a pseudo property in select clause
try {
Name name = resolver.getQName(fName + "()");
root.addSelectProperty(name);
} catch (NameException e) {
exceptions.add(e);
}
} else {
exceptions.add(new InvalidQueryException("Unsupported function: " + fName));
}
} catch (NamespaceException e) {
exceptions.add(e);
} catch (IllegalNameException e) {
exceptions.add(e);
}
return queryNode;
}
use of org.apache.jackrabbit.spi.commons.query.NAryQueryNode in project jackrabbit by apache.
the class JCRSQLQueryBuilder method visit.
public Object visit(ASTOrExpression node, Object data) {
NAryQueryNode parent = (NAryQueryNode) data;
OrQueryNode orQuery = factory.createOrQueryNode(parent);
// pass to operands
node.childrenAccept(this, orQuery);
if (orQuery.getNumOperands() > 0) {
parent.addOperand(orQuery);
}
return parent;
}
use of org.apache.jackrabbit.spi.commons.query.NAryQueryNode in project jackrabbit by apache.
the class JCRSQLQueryBuilder method visit.
public Object visit(ASTPredicate node, Object data) {
NAryQueryNode parent = (NAryQueryNode) data;
int type = node.getOperationType();
QueryNode predicateNode;
try {
final Name[] tmp = new Name[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);
Name identifier = tmp[0];
if (identifier != null && identifier.equals(NameConstants.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, NameConstants.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;
}
Aggregations