}
return data;
}
}, null);
Path relPath = node.getRelativePath();
String field = "";
try {
field = NameFormat.format(relPath.getNameElement().getName(), nsMappings);
} catch (NoPrefixDeclaredException e) {
// should never happen
exceptions.add(e);
}
switch (node.getOperation()) {
case QueryConstants.OPERATION_EQ_VALUE: // =
case QueryConstants.OPERATION_EQ_GENERAL:
BooleanQuery or = new BooleanQuery();
for (int i = 0; i < stringValues.length; i++) {
Term t = new Term(FieldNames.PROPERTIES,
FieldNames.createNamedValue(field, stringValues[i]));
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 TermQuery(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 (int i = 0; i < stringValues.length; i++) {
Term lower = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, stringValues[i]));
Term upper = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, "\uFFFF"));
or.add(new RangeQuery(lower, upper, true, transform[0]), 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 (int i = 0; i < stringValues.length; i++) {
Term lower = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, stringValues[i]));
Term upper = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, "\uFFFF"));
or.add(new RangeQuery(lower, upper, false, transform[0]), 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 (int i = 0; i < stringValues.length; i++) {
Term lower = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, ""));
Term upper = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, stringValues[i]));
or.add(new RangeQuery(lower, upper, true, transform[0]), Occur.SHOULD);
}
query = or;
if (node.getOperation() == QueryConstants.OPERATION_LE_VALUE) {
query = createSingleValueConstraint(query, field);
}
break;
case QueryConstants.OPERATION_LIKE: // LIKE
// the like operation always has one string value.
// no coercing, see above
if (stringValues[0].equals("%")) {
query = new MatchAllQuery(field);
} else {
query = new WildcardQuery(FieldNames.PROPERTIES, field, stringValues[0], transform[0]);
}
break;
case QueryConstants.OPERATION_LT_VALUE: // <
case QueryConstants.OPERATION_LT_GENERAL:
or = new BooleanQuery();
for (int i = 0; i < stringValues.length; i++) {
Term lower = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, ""));
Term upper = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, stringValues[i]));
or.add(new RangeQuery(lower, upper, false, transform[0]), 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(new MatchAllQuery(field), Occur.SHOULD);
// exclude all nodes where 'field' has the term in question
for (int i = 0; i < stringValues.length; i++) {
Term t = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, stringValues[i]));
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 TermQuery(t);
}
notQuery.add(q, Occur.MUST_NOT);
}
// and exclude all nodes where 'field' is multi valued
notQuery.add(new TermQuery(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(new MatchAllQuery(field), Occur.SHOULD);
for (int i = 0; i < stringValues.length; i++) {
// exclude the nodes that have the term and are single valued
Term t = new Term(FieldNames.PROPERTIES, FieldNames.createNamedValue(field, stringValues[i]));
Query svp = new NotQuery(new TermQuery(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 TermQuery(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(new MatchAllQuery(field));
break;
case QueryConstants.OPERATION_NOT_NULL:
query = new MatchAllQuery(field);
break;
default:
throw new IllegalArgumentException("Unknown relation operation: "
+ node.getOperation());
}
if (relPath.getLength() > 1) {
try {
// child axis in relation
Path.PathElement[] elements = relPath.getElements();
// elements.length - 1 = property name
// elements.length - 2 = last child axis name test
for (int i = elements.length - 2; i >= 0; i--) {
String name = null;
if (!elements[i].getName().equals(RelationQueryNode.STAR_NAME_TEST)) {