use of org.apache.jackrabbit.spi.commons.query.QueryNode in project jackrabbit by apache.
the class XPathQueryBuilder method visit.
//---------------------< XPathVisitor >-------------------------------------
/**
* Implements the generic visit method for this <code>XPathVisitor</code>.
*
* @param node the current node as created by the XPath parser.
* @param data the current <code>QueryNode</code> created by this
* <code>XPathVisitor</code>.
* @return the current <code>QueryNode</code>. Can be different from
* <code>data</code>.
*/
public Object visit(SimpleNode node, Object data) {
QueryNode queryNode = (QueryNode) data;
switch(node.getId()) {
case JJTXPATH2:
queryNode = createPathQueryNode(node);
break;
case JJTROOT:
case JJTROOTDESCENDANTS:
if (queryNode instanceof PathQueryNode) {
((PathQueryNode) queryNode).setAbsolute(true);
} else {
exceptions.add(new InvalidQueryException("Unsupported root level query node: " + queryNode));
}
break;
case JJTSTEPEXPR:
if (isAttributeAxis(node)) {
if (queryNode.getType() == QueryNode.TYPE_RELATION || (queryNode.getType() == QueryNode.TYPE_DEREF && ((DerefQueryNode) queryNode).getRefProperty() == null) || queryNode.getType() == QueryNode.TYPE_ORDER || queryNode.getType() == QueryNode.TYPE_PATH || queryNode.getType() == QueryNode.TYPE_TEXTSEARCH) {
// traverse
node.childrenAccept(this, queryNode);
} else if (queryNode.getType() == QueryNode.TYPE_NOT) {
// is null expression
RelationQueryNode isNull = factory.createRelationQueryNode(queryNode, RelationQueryNode.OPERATION_NULL);
applyRelativePath(isNull);
node.childrenAccept(this, isNull);
NotQueryNode notNode = (NotQueryNode) queryNode;
NAryQueryNode parent = (NAryQueryNode) notNode.getParent();
parent.removeOperand(notNode);
parent.addOperand(isNull);
} else {
// not null expression
RelationQueryNode notNull = factory.createRelationQueryNode(queryNode, RelationQueryNode.OPERATION_NOT_NULL);
applyRelativePath(notNull);
node.childrenAccept(this, notNull);
((NAryQueryNode) queryNode).addOperand(notNull);
}
} else {
if (queryNode.getType() == QueryNode.TYPE_PATH) {
createLocationStep(node, (NAryQueryNode) queryNode);
} else if (queryNode.getType() == QueryNode.TYPE_TEXTSEARCH || queryNode.getType() == QueryNode.TYPE_RELATION) {
node.childrenAccept(this, queryNode);
} else {
// step within a predicate
RelationQueryNode tmp = factory.createRelationQueryNode(null, RelationQueryNode.OPERATION_NOT_NULL);
node.childrenAccept(this, tmp);
if (tmpRelPath == null) {
tmpRelPath = new PathBuilder();
}
PathQueryNode relPath = tmp.getRelativePath();
LocationStepQueryNode[] steps = relPath.getPathSteps();
Name nameTest = steps[steps.length - 1].getNameTest();
if (nameTest == null) {
// see LocationStepQueryNode javadoc on when getNameTest()==null: when it was a star (asterisk)
nameTest = RelationQueryNode.STAR_NAME_TEST;
}
tmpRelPath.addLast(nameTest);
}
}
break;
case JJTNAMETEST:
if (queryNode.getType() == QueryNode.TYPE_LOCATION || queryNode.getType() == QueryNode.TYPE_DEREF || queryNode.getType() == QueryNode.TYPE_RELATION || queryNode.getType() == QueryNode.TYPE_TEXTSEARCH || queryNode.getType() == QueryNode.TYPE_PATH) {
createNodeTest(node, queryNode);
} else if (queryNode.getType() == QueryNode.TYPE_ORDER) {
setOrderSpecPath(node, (OrderQueryNode) queryNode);
} else {
// traverse
node.childrenAccept(this, queryNode);
}
break;
case JJTELEMENTNAMEORWILDCARD:
if (queryNode.getType() == QueryNode.TYPE_LOCATION) {
SimpleNode child = (SimpleNode) node.jjtGetChild(0);
if (child.getId() != JJTANYNAME) {
createNodeTest(child, queryNode);
}
}
break;
case JJTTEXTTEST:
if (queryNode.getType() == QueryNode.TYPE_LOCATION) {
LocationStepQueryNode loc = (LocationStepQueryNode) queryNode;
loc.setNameTest(JCR_XMLTEXT);
}
break;
case JJTTYPENAME:
if (queryNode.getType() == QueryNode.TYPE_LOCATION) {
LocationStepQueryNode loc = (LocationStepQueryNode) queryNode;
String ntName = ((SimpleNode) node.jjtGetChild(0)).getValue();
try {
Name nt = resolver.getQName(ntName);
NodeTypeQueryNode nodeType = factory.createNodeTypeQueryNode(loc, nt);
loc.addPredicate(nodeType);
} catch (NameException e) {
exceptions.add(new InvalidQueryException("Not a valid name: " + ntName));
} catch (NamespaceException e) {
exceptions.add(new InvalidQueryException("Not a valid name: " + ntName));
}
}
break;
case JJTOREXPR:
NAryQueryNode parent = (NAryQueryNode) queryNode;
QueryNode orQueryNode = factory.createOrQueryNode(parent);
parent.addOperand(orQueryNode);
// traverse
node.childrenAccept(this, orQueryNode);
break;
case JJTANDEXPR:
parent = (NAryQueryNode) queryNode;
QueryNode andQueryNode = factory.createAndQueryNode(parent);
parent.addOperand(andQueryNode);
// traverse
node.childrenAccept(this, andQueryNode);
break;
case JJTCOMPARISONEXPR:
createExpression(node, (NAryQueryNode) queryNode);
break;
case JJTSTRINGLITERAL:
case JJTDECIMALLITERAL:
case JJTDOUBLELITERAL:
case JJTINTEGERLITERAL:
if (queryNode.getType() == QueryNode.TYPE_RELATION) {
assignValue(node, (RelationQueryNode) queryNode);
} else if (queryNode.getType() == QueryNode.TYPE_LOCATION) {
if (node.getId() == JJTINTEGERLITERAL) {
int index = Integer.parseInt(node.getValue());
((LocationStepQueryNode) queryNode).setIndex(index);
} else {
exceptions.add(new InvalidQueryException("LocationStep only allows integer literal as position index"));
}
} else {
exceptions.add(new InvalidQueryException("Parse error: data is not a RelationQueryNode"));
}
break;
case JJTUNARYMINUS:
if (queryNode.getType() == QueryNode.TYPE_RELATION) {
((RelationQueryNode) queryNode).setUnaryMinus(true);
} else {
exceptions.add(new InvalidQueryException("Parse error: data is not a RelationQueryNode"));
}
break;
case JJTFUNCTIONCALL:
queryNode = createFunction(node, queryNode);
break;
case JJTORDERBYCLAUSE:
root.setOrderNode(factory.createOrderQueryNode(root));
queryNode = root.getOrderNode();
node.childrenAccept(this, queryNode);
break;
case JJTORDERSPEC:
OrderQueryNode orderQueryNode = (OrderQueryNode) queryNode;
orderQueryNode.newOrderSpec();
node.childrenAccept(this, queryNode);
if (!orderQueryNode.isValid()) {
exceptions.add(new InvalidQueryException("Invalid order specification. (Missing @?)"));
}
break;
case JJTORDERMODIFIER:
if (node.jjtGetNumChildren() > 0 && ((SimpleNode) node.jjtGetChild(0)).getId() == JJTDESCENDING) {
((OrderQueryNode) queryNode).setAscending(false);
}
break;
case JJTPREDICATELIST:
if (queryNode.getType() == QueryNode.TYPE_PATH) {
// switch to last location
QueryNode[] operands = ((PathQueryNode) queryNode).getOperands();
queryNode = operands[operands.length - 1];
}
node.childrenAccept(this, queryNode);
break;
case JJTPREDICATE:
if (queryNode.getType() == QueryNode.TYPE_LOCATION || queryNode.getType() == QueryNode.TYPE_DEREF) {
node.childrenAccept(this, queryNode);
} else {
// predicate not allowed here
exceptions.add(new InvalidQueryException("Unsupported location for predicate"));
}
break;
case JJTDOTDOT:
if (queryNode instanceof LocationStepQueryNode) {
((LocationStepQueryNode) queryNode).setNameTest(PATH_FACTORY.getParentElement().getName());
} else {
((RelationQueryNode) queryNode).addPathElement(PATH_FACTORY.getParentElement());
}
break;
default:
// per default traverse
node.childrenAccept(this, queryNode);
}
return queryNode;
}
use of org.apache.jackrabbit.spi.commons.query.QueryNode in project jackrabbit by apache.
the class XPathQueryBuilder method createDerefQueryNode.
private DerefQueryNode createDerefQueryNode(SimpleNode node, boolean descendant, QueryNode pathNode) throws NamespaceException {
DerefQueryNode derefNode = factory.createDerefQueryNode(pathNode, null, false);
// assign property name
node.jjtGetChild(1).jjtAccept(this, derefNode);
// check property name
if (derefNode.getRefProperty() == null) {
exceptions.add(new InvalidQueryException("Wrong first argument type for jcr:deref"));
}
SimpleNode literal = (SimpleNode) node.jjtGetChild(2).jjtGetChild(0);
if (literal.getId() == JJTSTRINGLITERAL) {
String value = literal.getValue();
// strip quotes
value = value.substring(1, value.length() - 1);
if (!value.equals("*")) {
Name name = null;
try {
name = decode(resolver.getQName(value));
} catch (NameException e) {
exceptions.add(new InvalidQueryException("Illegal name: " + value));
}
derefNode.setNameTest(name);
}
} else {
exceptions.add(new InvalidQueryException("Second argument for jcr:deref must be a String"));
}
// check if descendant
if (!descendant) {
Node p = node.jjtGetParent();
for (int i = 0; i < p.jjtGetNumChildren(); i++) {
SimpleNode c = (SimpleNode) p.jjtGetChild(i);
if (c == node) {
break;
}
descendant = (c.getId() == JJTSLASHSLASH || c.getId() == JJTROOTDESCENDANTS);
}
}
derefNode.setIncludeDescendants(descendant);
return derefNode;
}
use of org.apache.jackrabbit.spi.commons.query.QueryNode in project jackrabbit by apache.
the class QueryFormat method visit.
public Object visit(LocationStepQueryNode node, Object data) throws RepositoryException {
StringBuffer sb = (StringBuffer) data;
if (node.getIncludeDescendants()) {
sb.append('/');
}
final Name[] nodeType = new Name[1];
node.acceptOperands(new DefaultQueryNodeVisitor() {
public Object visit(NodeTypeQueryNode node, Object data) {
nodeType[0] = node.getValue();
return data;
}
}, null);
if (nodeType[0] != null) {
sb.append("element(");
}
if (node.getNameTest() == null) {
sb.append("*");
} else {
try {
if (node.getNameTest().getLocalName().length() == 0) {
sb.append(resolver.getJCRName(XPathQueryBuilder.JCR_ROOT));
} else {
sb.append(resolver.getJCRName(encode(node.getNameTest())));
}
} catch (NamespaceException e) {
exceptions.add(e);
}
}
if (nodeType[0] != null) {
sb.append(", ");
try {
sb.append(resolver.getJCRName(encode(nodeType[0])));
} catch (NamespaceException e) {
exceptions.add(e);
}
sb.append(")");
}
if (node.getIndex() != LocationStepQueryNode.NONE) {
sb.append('[').append(node.getIndex()).append(']');
}
QueryNode[] predicates = node.getPredicates();
for (int i = 0; i < predicates.length; i++) {
// ignore node type query nodes
if (predicates[i].getType() == QueryNode.TYPE_NODETYPE) {
continue;
}
sb.append('[');
predicates[i].accept(this, sb);
sb.append(']');
}
return sb;
}
use of org.apache.jackrabbit.spi.commons.query.QueryNode in project jackrabbit by apache.
the class LuceneQueryBuilder method visit.
public Object visit(LocationStepQueryNode node, Object data) throws RepositoryException {
Query context = (Query) data;
BooleanQuery andQuery = new BooleanQuery();
if (context == null) {
exceptions.add(new IllegalArgumentException("Unsupported query"));
}
// predicate on step?
Object[] predicates = node.acceptOperands(this, data);
for (Object predicate : predicates) {
andQuery.add((Query) predicate, Occur.MUST);
}
// check for position predicate
QueryNode[] pred = node.getPredicates();
for (QueryNode aPred : pred) {
if (aPred.getType() == QueryNode.TYPE_RELATION) {
RelationQueryNode pos = (RelationQueryNode) aPred;
if (pos.getValueType() == QueryConstants.TYPE_POSITION) {
node.setIndex(pos.getPositionValue());
}
}
}
NameQuery nameTest = null;
if (node.getNameTest() != null) {
if (node.getNameTest().equals(PARENT_ELEMENT_NAME)) {
andQuery.add(new ParentAxisQuery(context, null, indexFormatVersion, nsMappings), Occur.MUST);
return andQuery;
}
nameTest = new NameQuery(node.getNameTest(), indexFormatVersion, nsMappings);
}
if (node.getIncludeDescendants()) {
if (nameTest != null) {
andQuery.add(new DescendantSelfAxisQuery(context, nameTest, false), Occur.MUST);
} else {
// descendant-or-self with nametest=*
if (predicates.length > 0) {
// if we have a predicate attached, the condition acts as
// the sub query.
// only use descendant axis if path is not //*
// otherwise the query for the predicate can be used itself
PathQueryNode pathNode = (PathQueryNode) node.getParent();
if (pathNode.getPathSteps()[0] != node) {
Query subQuery = new DescendantSelfAxisQuery(context, andQuery, false);
andQuery = new BooleanQuery();
andQuery.add(subQuery, Occur.MUST);
}
} else {
// todo this will traverse the whole index, optimize!
// only use descendant axis if path is not //*
PathQueryNode pathNode = (PathQueryNode) node.getParent();
if (pathNode.getPathSteps()[0] != node) {
if (node.getIndex() == LocationStepQueryNode.NONE) {
context = new DescendantSelfAxisQuery(context, false);
andQuery.add(context, Occur.MUST);
} else {
context = new DescendantSelfAxisQuery(context, true);
andQuery.add(new ChildAxisQuery(sharedItemMgr, context, null, node.getIndex(), indexFormatVersion, nsMappings), Occur.MUST);
}
} else {
andQuery.add(new MatchAllDocsQuery(), Occur.MUST);
}
}
}
} else {
// name test
if (nameTest != null) {
andQuery.add(new ChildAxisQuery(sharedItemMgr, context, nameTest.getName(), node.getIndex(), indexFormatVersion, nsMappings), Occur.MUST);
} else {
// select child nodes
andQuery.add(new ChildAxisQuery(sharedItemMgr, context, null, node.getIndex(), indexFormatVersion, nsMappings), Occur.MUST);
}
}
return andQuery;
}
use of org.apache.jackrabbit.spi.commons.query.QueryNode in project jackrabbit by apache.
the class XPathQueryBuilder method createLocationStep.
/**
* Creates a <code>LocationStepQueryNode</code> at the current position
* in parent.
*
* @param node the current node in the xpath syntax tree.
* @param parent the parent <code>PathQueryNode</code>.
* @return the created <code>LocationStepQueryNode</code>.
*/
private LocationStepQueryNode createLocationStep(SimpleNode node, NAryQueryNode parent) {
LocationStepQueryNode queryNode = null;
boolean descendant = false;
Node p = node.jjtGetParent();
for (int i = 0; i < p.jjtGetNumChildren(); i++) {
SimpleNode c = (SimpleNode) p.jjtGetChild(i);
if (c == node) {
queryNode = factory.createLocationStepQueryNode(parent);
queryNode.setNameTest(null);
queryNode.setIncludeDescendants(descendant);
parent.addOperand(queryNode);
break;
}
descendant = (c.getId() == JJTSLASHSLASH || c.getId() == JJTROOTDESCENDANTS);
}
node.childrenAccept(this, queryNode);
return queryNode;
}
Aggregations