use of org.apache.jackrabbit.spi.commons.query.LocationStepQueryNode in project jackrabbit by apache.
the class LuceneQueryBuilder method visit.
public Object visit(PathQueryNode node, Object data) throws RepositoryException {
Query context = null;
LocationStepQueryNode[] steps = node.getPathSteps();
if (steps.length > 0) {
if (node.isAbsolute() && !steps[0].getIncludeDescendants()) {
// eat up first step
Name nameTest = steps[0].getNameTest();
if (nameTest == null) {
// this is equivalent to the root node
context = new JackrabbitTermQuery(new Term(FieldNames.PARENT, ""));
} else if (nameTest.getLocalName().length() == 0) {
// root node
context = new JackrabbitTermQuery(new Term(FieldNames.PARENT, ""));
} else {
// then this is a node != the root node
// will never match anything!
BooleanQuery and = new BooleanQuery();
and.add(new JackrabbitTermQuery(new Term(FieldNames.PARENT, "")), Occur.MUST);
and.add(new NameQuery(nameTest, indexFormatVersion, nsMappings), Occur.MUST);
context = and;
}
// apply predicates
Object[] predicates = steps[0].acceptOperands(this, context);
BooleanQuery andQuery = new BooleanQuery();
for (Object predicate : predicates) {
andQuery.add((Query) predicate, Occur.MUST);
}
if (andQuery.clauses().size() > 0) {
andQuery.add(context, Occur.MUST);
context = andQuery;
}
LocationStepQueryNode[] tmp = new LocationStepQueryNode[steps.length - 1];
System.arraycopy(steps, 1, tmp, 0, steps.length - 1);
steps = tmp;
} else {
// path is 1) relative or 2) descendant-or-self
// use root node as context
context = new JackrabbitTermQuery(new Term(FieldNames.PARENT, ""));
}
} else {
exceptions.add(new InvalidQueryException("Number of location steps must be > 0"));
}
// loop over steps
for (LocationStepQueryNode step : steps) {
context = (Query) step.accept(this, context);
}
if (data instanceof BooleanQuery) {
BooleanQuery constraint = (BooleanQuery) data;
if (constraint.getClauses().length > 0) {
constraint.add(context, Occur.MUST);
context = constraint;
}
}
return context;
}
use of org.apache.jackrabbit.spi.commons.query.LocationStepQueryNode 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.LocationStepQueryNode 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.LocationStepQueryNode in project jackrabbit by apache.
the class JCRSQLQueryBuilder method createPathQuery.
/**
* Creates <code>LocationStepQueryNode</code>s from a <code>path</code>.
*
* @param path the path pattern
* @param operation the type of the parent node
*/
private void createPathQuery(String path, int operation) {
MergingPathQueryNode pathNode = new MergingPathQueryNode(operation, factory.createPathQueryNode(null).getValidJcrSystemNodeTypeNames());
pathNode.setAbsolute(true);
if (path.equals("/")) {
pathNode.addPathStep(factory.createLocationStepQueryNode(pathNode));
pathConstraints.add(pathNode);
return;
}
String[] names = path.split("/");
for (int i = 0; i < names.length; i++) {
if (names[i].length() == 0) {
if (i == 0) {
// root
pathNode.addPathStep(factory.createLocationStepQueryNode(pathNode));
} else {
// descendant '//' -> invalid path
// todo throw or ignore?
// we currently do not throw and add location step for an
// empty name (which is basically the root node)
pathNode.addPathStep(factory.createLocationStepQueryNode(pathNode));
}
} else {
int idx = names[i].indexOf('[');
String name;
int index = LocationStepQueryNode.NONE;
if (idx > -1) {
// contains index
name = names[i].substring(0, idx);
String suffix = names[i].substring(idx);
String indexStr = suffix.substring(1, suffix.length() - 1);
if (indexStr.equals("%")) {
// select all same name siblings
index = LocationStepQueryNode.NONE;
} else {
try {
index = Integer.parseInt(indexStr);
} catch (NumberFormatException e) {
log.warn("Unable to parse index for path element: " + names[i]);
}
}
if (name.equals("%")) {
name = null;
}
} else {
// no index specified
// - index defaults to 1 if there is an explicit name test
// - index defaults to NONE if name test is %
name = names[i];
if (name.equals("%")) {
name = null;
} else {
index = 1;
}
}
Name qName = null;
if (name != null) {
try {
qName = resolver.getQName(name);
} catch (NamespaceException e) {
throw new IllegalArgumentException("Illegal name: " + name);
} catch (NameException e) {
throw new IllegalArgumentException("Illegal name: " + name);
}
}
// if name test is % this means also search descendants
boolean descendant = name == null;
LocationStepQueryNode step = factory.createLocationStepQueryNode(pathNode);
step.setNameTest(qName);
step.setIncludeDescendants(descendant);
if (index > 0) {
step.setIndex(index);
}
pathNode.addPathStep(step);
}
}
pathConstraints.add(pathNode);
}
use of org.apache.jackrabbit.spi.commons.query.LocationStepQueryNode 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, "\uFFFF"));
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, "\uFFFF"));
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;
}
Aggregations