use of org.apache.jackrabbit.spi.commons.query.PathQueryNode in project jackrabbit by apache.
the class QueryFormat method visit.
public Object visit(RelationQueryNode node, Object data) throws RepositoryException {
StringBuffer sb = (StringBuffer) data;
try {
StringBuffer propName = new StringBuffer();
PathQueryNode relPath = node.getRelativePath();
if (relPath == null) {
propName.append(".");
} else if (relPath.getPathSteps().length > 1) {
exceptions.add(new InvalidQueryException("Child axis not supported in SQL"));
return data;
} else {
visit(relPath, data);
}
// surround name with property function
node.acceptOperands(this, propName);
if (node.getOperation() == OPERATION_EQ_VALUE || node.getOperation() == OPERATION_EQ_GENERAL) {
sb.append(propName);
sb.append(" = ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_GE_VALUE || node.getOperation() == OPERATION_GE_GENERAL) {
sb.append(propName);
sb.append(" >= ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_GT_VALUE || node.getOperation() == OPERATION_GT_GENERAL) {
sb.append(propName);
sb.append(" > ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_LE_VALUE || node.getOperation() == OPERATION_LE_GENERAL) {
sb.append(propName);
sb.append(" <= ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_LIKE) {
sb.append(propName);
sb.append(" LIKE ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_LT_VALUE || node.getOperation() == OPERATION_LT_GENERAL) {
sb.append(propName);
sb.append(" < ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_NE_VALUE || node.getOperation() == OPERATION_NE_GENERAL) {
sb.append(propName);
sb.append(" <> ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_NULL) {
sb.append(propName);
sb.append(" IS NULL");
} else if (node.getOperation() == OPERATION_NOT_NULL) {
sb.append(propName);
sb.append(" IS NOT NULL");
} else if (node.getOperation() == OPERATION_SIMILAR) {
sb.append("SIMILAR(");
sb.append(propName);
sb.append(", ");
appendValue(node, sb);
sb.append(")");
} else if (node.getOperation() == OPERATION_SPELLCHECK) {
sb.append("SPELLCHECK(");
appendValue(node, sb);
sb.append(")");
} else {
exceptions.add(new InvalidQueryException("Invalid operation: " + node.getOperation()));
}
if (node.getOperation() == OPERATION_LIKE && node.getStringValue().indexOf('\\') > -1) {
sb.append(" ESCAPE '\\'");
}
} catch (NamespaceException e) {
exceptions.add(e);
}
return sb;
}
use of org.apache.jackrabbit.spi.commons.query.PathQueryNode 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.PathQueryNode in project jackrabbit by apache.
the class QueryFormat method visit.
public Object visit(RelationQueryNode node, Object data) throws RepositoryException {
StringBuffer sb = (StringBuffer) data;
try {
StringBuffer propPath = new StringBuffer();
// only encode if not position function
PathQueryNode relPath = node.getRelativePath();
if (relPath == null) {
propPath.append(".");
} else if (relPath.getNumOperands() > 0 && XPathQueryBuilder.FN_POSITION_FULL.equals(relPath.getPathSteps()[0].getNameTest())) {
propPath.append(resolver.getJCRName(XPathQueryBuilder.FN_POSITION_FULL));
} else {
LocationStepQueryNode[] steps = relPath.getPathSteps();
String slash = "";
for (int i = 0; i < steps.length; i++) {
propPath.append(slash);
slash = "/";
if (i == steps.length - 1 && node.getOperation() != OPERATION_SIMILAR) {
// last step
propPath.append("@");
}
visit(steps[i], propPath);
}
}
// surround name with property function
node.acceptOperands(this, propPath);
if (node.getOperation() == OPERATION_EQ_VALUE) {
sb.append(propPath).append(" eq ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_EQ_GENERAL) {
sb.append(propPath).append(" = ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_GE_GENERAL) {
sb.append(propPath).append(" >= ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_GE_VALUE) {
sb.append(propPath).append(" ge ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_GT_GENERAL) {
sb.append(propPath).append(" > ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_GT_VALUE) {
sb.append(propPath).append(" gt ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_LE_GENERAL) {
sb.append(propPath).append(" <= ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_LE_VALUE) {
sb.append(propPath).append(" le ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_LIKE) {
sb.append(resolver.getJCRName(XPathQueryBuilder.JCR_LIKE));
sb.append("(").append(propPath).append(", ");
appendValue(node, sb);
sb.append(")");
} else if (node.getOperation() == OPERATION_LT_GENERAL) {
sb.append(propPath).append(" < ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_LT_VALUE) {
sb.append(propPath).append(" lt ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_NE_GENERAL) {
sb.append(propPath).append(" != ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_NE_VALUE) {
sb.append(propPath).append(" ne ");
appendValue(node, sb);
} else if (node.getOperation() == OPERATION_NULL) {
sb.append(resolver.getJCRName(XPathQueryBuilder.FN_NOT));
sb.append("(").append(propPath).append(")");
} else if (node.getOperation() == OPERATION_NOT_NULL) {
sb.append(propPath);
} else if (node.getOperation() == OPERATION_SIMILAR) {
sb.append(resolver.getJCRName(XPathQueryBuilder.REP_SIMILAR));
sb.append("(").append(propPath).append(", ");
appendValue(node, sb);
sb.append(")");
} else if (node.getOperation() == OPERATION_SPELLCHECK) {
sb.append(resolver.getJCRName(XPathQueryBuilder.REP_SPELLCHECK));
sb.append("(");
appendValue(node, sb);
sb.append(")");
} else {
exceptions.add(new InvalidQueryException("Invalid operation: " + node.getOperation()));
}
} catch (NamespaceException e) {
exceptions.add(e);
}
return sb;
}
use of org.apache.jackrabbit.spi.commons.query.PathQueryNode in project jackrabbit by apache.
the class LuceneQueryBuilder method visit.
public Object visit(RelationQueryNode node, Object data) throws RepositoryException {
PathQueryNode relPath = node.getRelativePath();
if (relPath == null && node.getOperation() != QueryConstants.OPERATION_SIMILAR && node.getOperation() != QueryConstants.OPERATION_SPELLCHECK) {
exceptions.add(new InvalidQueryException("@* not supported in predicate"));
return data;
}
LocationStepQueryNode[] steps = relPath.getPathSteps();
Name propertyName;
if (node.getOperation() == QueryConstants.OPERATION_SIMILAR) {
// this is a bit ugly:
// use the name of a dummy property because relPath actually
// references a property. whereas the relPath of the similar
// operation references a node
propertyName = NameConstants.JCR_PRIMARYTYPE;
} else {
propertyName = steps[steps.length - 1].getNameTest();
}
Query query;
String[] stringValues = new String[1];
switch(node.getValueType()) {
case 0:
// not set: either IS NULL or IS NOT NULL
break;
case QueryConstants.TYPE_DATE:
stringValues[0] = DateField.dateToString(node.getDateValue());
break;
case QueryConstants.TYPE_DOUBLE:
stringValues[0] = DoubleField.doubleToString(node.getDoubleValue());
break;
case QueryConstants.TYPE_LONG:
stringValues[0] = LongField.longToString(node.getLongValue());
break;
case QueryConstants.TYPE_STRING:
if (node.getOperation() == QueryConstants.OPERATION_EQ_GENERAL || node.getOperation() == QueryConstants.OPERATION_EQ_VALUE || node.getOperation() == QueryConstants.OPERATION_NE_GENERAL || node.getOperation() == QueryConstants.OPERATION_NE_VALUE) {
// only use coercing on non-range operations
stringValues = getStringValues(propertyName, node.getStringValue());
} else {
stringValues[0] = node.getStringValue();
}
break;
case QueryConstants.TYPE_POSITION:
// ignore position. is handled in the location step
return null;
default:
throw new IllegalArgumentException("Unknown relation type: " + node.getValueType());
}
// get property transformation
final int[] transform = new int[] { TransformConstants.TRANSFORM_NONE };
node.acceptOperands(new DefaultQueryNodeVisitor() {
public Object visit(PropertyFunctionQueryNode node, Object data) {
if (node.getFunctionName().equals(PropertyFunctionQueryNode.LOWER_CASE)) {
transform[0] = TransformConstants.TRANSFORM_LOWER_CASE;
} else if (node.getFunctionName().equals(PropertyFunctionQueryNode.UPPER_CASE)) {
transform[0] = TransformConstants.TRANSFORM_UPPER_CASE;
}
return data;
}
}, null);
String field = "";
try {
field = resolver.getJCRName(propertyName);
} catch (NamespaceException e) {
// should never happen
exceptions.add(e);
}
// support for fn:name()
if (propertyName.equals(FN_NAME)) {
if (node.getValueType() != QueryConstants.TYPE_STRING) {
exceptions.add(new InvalidQueryException("Name function can " + "only be used in conjunction with a string literal"));
return data;
}
if (node.getOperation() == QueryConstants.OPERATION_EQ_VALUE || node.getOperation() == QueryConstants.OPERATION_EQ_GENERAL) {
// check if string literal is a valid XML Name
if (XMLChar.isValidName(node.getStringValue())) {
// parse string literal as JCR Name
try {
Name n = session.getQName(ISO9075.decode(node.getStringValue()));
query = new NameQuery(n, indexFormatVersion, nsMappings);
} catch (NameException e) {
exceptions.add(e);
return data;
} catch (NamespaceException e) {
exceptions.add(e);
return data;
}
} else {
// will never match -> create dummy query
query = new BooleanQuery();
}
} else if (node.getOperation() == QueryConstants.OPERATION_LIKE) {
// no coercing, see above
if (stringValues[0].equals("%")) {
query = new org.apache.lucene.search.MatchAllDocsQuery();
} else {
query = new WildcardNameQuery(stringValues[0], transform[0], session, nsMappings, cache);
}
} else {
exceptions.add(new InvalidQueryException("Name function can " + "only be used in conjunction with the following operators: equals, like"));
return data;
}
} else {
switch(node.getOperation()) {
// =
case QueryConstants.OPERATION_EQ_VALUE:
case QueryConstants.OPERATION_EQ_GENERAL:
BooleanQuery or = new BooleanQuery();
for (String value : stringValues) {
Term t = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
Query q;
if (transform[0] == TransformConstants.TRANSFORM_UPPER_CASE) {
q = new CaseTermQuery.Upper(t);
} else if (transform[0] == TransformConstants.TRANSFORM_LOWER_CASE) {
q = new CaseTermQuery.Lower(t);
} else {
q = new JackrabbitTermQuery(t);
}
or.add(q, Occur.SHOULD);
}
query = or;
if (node.getOperation() == QueryConstants.OPERATION_EQ_VALUE) {
query = createSingleValueConstraint(or, field);
}
break;
// >=
case QueryConstants.OPERATION_GE_VALUE:
case QueryConstants.OPERATION_GE_GENERAL:
or = new BooleanQuery();
for (String value : stringValues) {
Term lower = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
Term upper = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, ""));
or.add(new RangeQuery(lower, upper, true, transform[0], cache), Occur.SHOULD);
}
query = or;
if (node.getOperation() == QueryConstants.OPERATION_GE_VALUE) {
query = createSingleValueConstraint(or, field);
}
break;
// >
case QueryConstants.OPERATION_GT_VALUE:
case QueryConstants.OPERATION_GT_GENERAL:
or = new BooleanQuery();
for (String value : stringValues) {
Term lower = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
Term upper = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, ""));
or.add(new RangeQuery(lower, upper, false, transform[0], cache), Occur.SHOULD);
}
query = or;
if (node.getOperation() == QueryConstants.OPERATION_GT_VALUE) {
query = createSingleValueConstraint(or, field);
}
break;
// <=
case QueryConstants.OPERATION_LE_VALUE:
case // <=
QueryConstants.OPERATION_LE_GENERAL:
or = new BooleanQuery();
for (String value : stringValues) {
Term lower = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, ""));
Term upper = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
or.add(new RangeQuery(lower, upper, true, transform[0], cache), Occur.SHOULD);
}
query = or;
if (node.getOperation() == QueryConstants.OPERATION_LE_VALUE) {
query = createSingleValueConstraint(query, field);
}
break;
case // LIKE
QueryConstants.OPERATION_LIKE:
// no coercing, see above
if (stringValues[0].equals("%")) {
query = Util.createMatchAllQuery(field, indexFormatVersion, cache);
} else {
query = new WildcardQuery(FieldNames.PROPERTIES, field, stringValues[0], transform[0], cache);
}
break;
// <
case QueryConstants.OPERATION_LT_VALUE:
case QueryConstants.OPERATION_LT_GENERAL:
or = new BooleanQuery();
for (String value : stringValues) {
Term lower = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, ""));
Term upper = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
or.add(new RangeQuery(lower, upper, false, transform[0], cache), Occur.SHOULD);
}
query = or;
if (node.getOperation() == QueryConstants.OPERATION_LT_VALUE) {
query = createSingleValueConstraint(or, field);
}
break;
case // !=
QueryConstants.OPERATION_NE_VALUE:
// match nodes with property 'field' that includes svp and mvp
BooleanQuery notQuery = new BooleanQuery();
notQuery.add(Util.createMatchAllQuery(field, indexFormatVersion, cache), Occur.SHOULD);
// exclude all nodes where 'field' has the term in question
for (String value : stringValues) {
Term t = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
Query q;
if (transform[0] == TransformConstants.TRANSFORM_UPPER_CASE) {
q = new CaseTermQuery.Upper(t);
} else if (transform[0] == TransformConstants.TRANSFORM_LOWER_CASE) {
q = new CaseTermQuery.Lower(t);
} else {
q = new JackrabbitTermQuery(t);
}
notQuery.add(q, Occur.MUST_NOT);
}
// and exclude all nodes where 'field' is multi valued
notQuery.add(new JackrabbitTermQuery(new Term(FieldNames.MVP, field)), Occur.MUST_NOT);
query = notQuery;
break;
case // !=
QueryConstants.OPERATION_NE_GENERAL:
// that's:
// all nodes with property 'field'
// minus the nodes that have a single property 'field' that is
// not equal to term in question
// minus the nodes that have a multi-valued property 'field' and
// all values are equal to term in question
notQuery = new BooleanQuery();
notQuery.add(Util.createMatchAllQuery(field, indexFormatVersion, cache), Occur.SHOULD);
for (String value : stringValues) {
// exclude the nodes that have the term and are single valued
Term t = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, value));
Query svp = new NotQuery(new JackrabbitTermQuery(new Term(FieldNames.MVP, field)));
BooleanQuery and = new BooleanQuery();
Query q;
if (transform[0] == TransformConstants.TRANSFORM_UPPER_CASE) {
q = new CaseTermQuery.Upper(t);
} else if (transform[0] == TransformConstants.TRANSFORM_LOWER_CASE) {
q = new CaseTermQuery.Lower(t);
} else {
q = new JackrabbitTermQuery(t);
}
and.add(q, Occur.MUST);
and.add(svp, Occur.MUST);
notQuery.add(and, Occur.MUST_NOT);
}
// todo above also excludes multi-valued properties that contain
// multiple instances of only stringValues. e.g. text={foo, foo}
query = notQuery;
break;
case QueryConstants.OPERATION_NULL:
query = new NotQuery(Util.createMatchAllQuery(field, indexFormatVersion, cache));
break;
case QueryConstants.OPERATION_SIMILAR:
try {
NodeId id = hmgr.resolveNodePath(session.getQPath(node.getStringValue()));
if (id != null) {
query = new SimilarityQuery(id.toString(), analyzer);
} else {
query = new BooleanQuery();
}
} catch (Exception e) {
exceptions.add(e);
query = new BooleanQuery();
}
break;
case QueryConstants.OPERATION_NOT_NULL:
query = Util.createMatchAllQuery(field, indexFormatVersion, cache);
break;
case QueryConstants.OPERATION_SPELLCHECK:
query = Util.createMatchAllQuery(field, indexFormatVersion, cache);
break;
default:
throw new IllegalArgumentException("Unknown relation operation: " + node.getOperation());
}
}
if (steps.length > 1) {
// child axis in relation
// elements.length - 1 = property name
// elements.length - 2 = last child axis name test
boolean selectParent = true;
for (int i = steps.length - 2; i >= 0; i--) {
LocationStepQueryNode step = steps[i];
Name name = steps[i].getNameTest();
if (i == steps.length - 2) {
if (step instanceof DerefQueryNode) {
query = createPredicateDeref(query, (DerefQueryNode) step, data);
if (steps.length == 2) {
selectParent = false;
}
} else if (step != null) {
// join name test with property query if there is one
if (name != null) {
if (!name.equals(PARENT_ELEMENT_NAME)) {
Query nameTest = new NameQuery(name, indexFormatVersion, nsMappings);
BooleanQuery and = new BooleanQuery();
and.add(query, Occur.MUST);
and.add(nameTest, Occur.MUST);
query = and;
} else {
// If we're searching the parent, we want to return the child axis,
// not the parent because this is part of the predicate. For instance,
// if the query is //child[../base], this part of the code is operating
// on the "../base" portion. So we want to return all the child nodes
// of "base", which will then be matched against the non predicate part.
query = new ChildAxisQuery(sharedItemMgr, query, null, indexFormatVersion, nsMappings);
selectParent = false;
}
} else {
// otherwise the query can be used as is
}
}
} else if (name != null && name.equals(PARENT_ELEMENT_NAME)) {
// We need to select one of the properties if we haven't already.
if (selectParent) {
query = new ParentAxisQuery(query, null, indexFormatVersion, nsMappings);
selectParent = false;
}
// See the note above on searching parents
query = new ChildAxisQuery(sharedItemMgr, query, null, indexFormatVersion, nsMappings);
} else {
if (step != null) {
query = new ParentAxisQuery(query, name, indexFormatVersion, nsMappings);
} else {
throw new UnsupportedOperationException();
}
}
}
// finally select the parent of the selected nodes
if (selectParent) {
query = new ParentAxisQuery(query, null, indexFormatVersion, nsMappings);
}
}
return query;
}
use of org.apache.jackrabbit.spi.commons.query.PathQueryNode 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;
}
Aggregations