}
return data;
}
}, null);
QPath relPath = node.getRelativePath();
InternalQName propName;
if (node.getOperation() == QueryConstants.OPERATION_SIMILAR)
{
// this is a bit ugly:
// add the name of a dummy property because relPath actually
// references a property. whereas the relPath of the similar
// operation references a node
//relPath = QPath.makeChildPath(relPath, Constants.JCR_PRIMARYTYPE);
propName = Constants.JCR_PRIMARYTYPE;
}
else
{
propName = relPath.getName();
}
String field = "";
try
{
field = resolver.createJCRName(propName).getAsString();
}
catch (NamespaceException e)
{
// should never happen
exceptions.add(e);
}
// support for fn:name()
//InternalQName propName = relPath.getName();
if (propName.getNamespace().equals(NS_FN_URI) && propName.getName().equals("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)
{
exceptions.add(new InvalidQueryException("Name function can "
+ "only be used in conjunction with an equals operator"));
return data;
}
// check if string literal is a valid XML Name
if (XMLChar.isValidName(node.getStringValue()))
{
// parse string literal as JCR Name
try
{
InternalQName n =
session.getLocationFactory().parseJCRName(ISO9075.decode(node.getStringValue())).getInternalName();
query = new NameQuery(n, indexFormatVersion, nsMappings);
}
catch (RepositoryException e)
{
exceptions.add(e);
return data;
}
}
else
{
// will never match -> create dummy query
query = new BooleanQuery();
}
}
else
{
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 JcrTermQuery(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 = Util.createMatchAllQuery(field, indexFormatVersion);
}
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(Util.createMatchAllQuery(field, indexFormatVersion), 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 JcrTermQuery(t);
}
notQuery.add(q, Occur.MUST_NOT);
}
// and exclude all nodes where 'field' is multi valued
notQuery.add(new JcrTermQuery(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), 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 JcrTermQuery(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 JcrTermQuery(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));
break;
case QueryConstants.OPERATION_SIMILAR :
String uuid = "x";
try
{
// throw new UnsupportedOperationException();
QPath path = resolver.parseJCRPath(node.getStringValue()).getInternalPath();
NodeData parent = (NodeData)sharedItemMgr.getItemData(Constants.ROOT_UUID);
if (path.equals(Constants.ROOT_PATH))
{
uuid = Constants.ROOT_UUID;
}
else
{
QPathEntry[] relPathEntries = path.getRelPath(path.getDepth());
ItemData item = parent;
for (int i = 0; i < relPathEntries.length; i++)
{
item = sharedItemMgr.getItemData(parent, relPathEntries[i], ItemType.UNKNOWN);