Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java (revision 1039888)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java (revision )
@@ -16,18 +16,6 @@
*/
package org.apache.jackrabbit.core.query.lucene;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import javax.jcr.RepositoryException;
-import javax.jcr.Value;
-import javax.jcr.Workspace;
-import javax.jcr.nodetype.PropertyDefinition;
-import javax.jcr.query.InvalidQueryException;
-import javax.jcr.query.QueryResult;
-import javax.jcr.query.qom.QueryObjectModelFactory;
-
import org.apache.jackrabbit.core.SessionImpl;
import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
import org.apache.jackrabbit.core.query.PropertyTypeRegistry;
@@ -51,6 +39,15 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.jcr.RepositoryException;
+import javax.jcr.Workspace;
+import javax.jcr.nodetype.PropertyDefinition;
+import javax.jcr.query.InvalidQueryException;
+import javax.jcr.query.QueryResult;
+import javax.jcr.query.qom.QueryObjectModelFactory;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
/**
* Implements the {@link org.apache.jackrabbit.core.query.ExecutableQuery}
* interface.
@@ -126,15 +123,17 @@
}
Path[] orderProperties = new Path[orderSpecs.length];
boolean[] ascSpecs = new boolean[orderSpecs.length];
+ String[] orderFuncs = new String[orderSpecs.length];
for (int i = 0; i < orderSpecs.length; i++) {
orderProperties[i] = orderSpecs[i].getPropertyPath();
ascSpecs[i] = orderSpecs[i].isAscending();
+ orderFuncs[i] = orderSpecs[i].getFunction();
}
return new SingleColumnQueryResult(
index, sessionContext, this, query,
new SpellSuggestion(index.getSpellChecker(), root),
- getColumns(), orderProperties, ascSpecs,
+ getColumns(), orderProperties, ascSpecs, orderFuncs,
orderProperties.length == 0 && getRespectDocumentOrder(),
offset, limit);
}
Index: jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/xpath/XPathQueryBuilder.java
===================================================================
--- jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/xpath/XPathQueryBuilder.java (revision 995787)
+++ jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/xpath/XPathQueryBuilder.java (revision )
@@ -16,16 +16,6 @@
*/
package org.apache.jackrabbit.spi.commons.query.xpath;
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.List;
-import java.util.Map;
-
-import javax.jcr.NamespaceException;
-import javax.jcr.RepositoryException;
-import javax.jcr.query.InvalidQueryException;
-
import org.apache.commons.collections.map.ReferenceMap;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.NameFactory;
@@ -57,6 +47,15 @@
import org.apache.jackrabbit.util.ISO8601;
import org.apache.jackrabbit.util.ISO9075;
+import javax.jcr.NamespaceException;
+import javax.jcr.RepositoryException;
+import javax.jcr.query.InvalidQueryException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Map;
+
/**
* Query builder that translates a XPath statement into a query tree structure.
*/
@@ -439,7 +438,7 @@
|| queryNode.getType() == QueryNode.TYPE_PATH) {
createNodeTest(node, queryNode);
} else if (queryNode.getType() == QueryNode.TYPE_ORDER) {
- createOrderSpec(node, (OrderQueryNode) queryNode);
+ setOrderSpecPath(node, (OrderQueryNode) queryNode);
} else {
// traverse
node.childrenAccept(this, queryNode);
@@ -523,11 +522,15 @@
queryNode = root.getOrderNode();
node.childrenAccept(this, queryNode);
break;
+ case JJTORDERSPECLIST:
+ OrderQueryNode orderQueryNode = (OrderQueryNode) queryNode;
+ orderQueryNode.newOrderSpec();
+ node.childrenAccept(this, queryNode);
+ break;
case JJTORDERMODIFIER:
if (node.jjtGetNumChildren() > 0
&& ((SimpleNode) node.jjtGetChild(0)).getId() == JJTDESCENDING) {
- OrderQueryNode.OrderSpec[] specs = ((OrderQueryNode) queryNode).getOrderSpecs();
- specs[specs.length - 1].setAscending(false);
+ ((OrderQueryNode) queryNode).setAscending(false);
}
break;
case JJTPREDICATELIST:
@@ -962,7 +965,7 @@
}
} else if (JCR_SCORE.equals(funName)) {
if (queryNode.getType() == QueryNode.TYPE_ORDER) {
- createOrderSpec(node, (OrderQueryNode) queryNode);
+ setOrderSpecPath(node, (OrderQueryNode) queryNode);
} else {
exceptions.add(new InvalidQueryException("Unsupported location for jcr:score()"));
}
@@ -974,6 +977,9 @@
relNode, PropertyFunctionQueryNode.LOWER_CASE));
// get property name
node.jjtGetChild(1).jjtAccept(this, relNode);
+ } else if (queryNode.getType() == QueryNode.TYPE_ORDER) {
+ ((OrderQueryNode) queryNode).setFunction(FN_LOWER_CASE.getLocalName());
+ node.childrenAccept(this, queryNode);
} else {
exceptions.add(new InvalidQueryException("Unsupported location for fn:lower-case()"));
}
@@ -988,6 +994,9 @@
relNode, PropertyFunctionQueryNode.UPPER_CASE));
// get property name
node.jjtGetChild(1).jjtAccept(this, relNode);
+ } else if (queryNode.getType() == QueryNode.TYPE_ORDER) {
+ ((OrderQueryNode) queryNode).setFunction(FN_UPPER_CASE.getLocalName());
+ node.childrenAccept(this, queryNode);
} else {
exceptions.add(new InvalidQueryException("Unsupported location for fn:upper-case()"));
}
@@ -1120,10 +1129,8 @@
return derefNode;
}
- private OrderQueryNode.OrderSpec createOrderSpec(SimpleNode node,
- OrderQueryNode queryNode) {
+ private void setOrderSpecPath(SimpleNode node, OrderQueryNode queryNode) {
SimpleNode child = (SimpleNode) node.jjtGetChild(0);
- OrderQueryNode.OrderSpec spec = null;
try {
String propName = child.getValue();
if (child.getId() == JJTQNAMELPAR) {
@@ -1139,14 +1146,12 @@
} else {
path = PathFactoryImpl.getInstance().create(element);
}
- spec = new OrderQueryNode.OrderSpec(path, true);
- queryNode.addOrderSpec(spec);
+ queryNode.setPath(path);
} catch (NameException e) {
exceptions.add(new InvalidQueryException("Illegal name: " + child.getValue()));
} catch (NamespaceException e) {
exceptions.add(new InvalidQueryException("Illegal name: " + child.getValue()));
}
- return spec;
}
/**
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SingleColumnQueryResult.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SingleColumnQueryResult.java (revision 983708)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SingleColumnQueryResult.java (revision )
@@ -16,15 +16,14 @@
*/
package org.apache.jackrabbit.core.query.lucene;
-import java.io.IOException;
-
-import javax.jcr.RepositoryException;
-
import org.apache.jackrabbit.core.session.SessionContext;
import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.spi.commons.query.qom.ColumnImpl;
import org.apache.lucene.search.Query;
+import javax.jcr.RepositoryException;
+import java.io.IOException;
+
/**
* SingleColumnQueryResult implements a query result that returns
* a single column. That is, executes a lucene query.
@@ -45,18 +44,20 @@
* The order specifier for each of the order properties.
*/
protected final boolean[] orderSpecs;
+ private String[] orderFuncs;
public SingleColumnQueryResult(
SearchIndex index, SessionContext sessionContext,
AbstractQueryImpl queryImpl, Query query,
SpellSuggestion spellSuggestion, ColumnImpl[] columns,
- Path[] orderProps, boolean[] orderSpecs, boolean documentOrder,
+ Path[] orderProps, boolean[] orderSpecs, String[] orderFuncs, boolean documentOrder,
long offset, long limit) throws RepositoryException {
super(index, sessionContext, queryImpl, spellSuggestion,
columns, documentOrder, offset, limit);
this.query = query;
this.orderProps = orderProps;
this.orderSpecs = orderSpecs;
+ this.orderFuncs = orderFuncs;
// if document order is requested get all results right away
getResults(docOrder ? Integer.MAX_VALUE : index.getResultFetchSize());
}
@@ -68,7 +69,7 @@
throws IOException {
return index.executeQuery(
sessionContext.getSessionImpl(), queryImpl, query,
- orderProps, orderSpecs, resultFetchHint);
+ orderProps, orderSpecs, orderFuncs, resultFetchHint);
}
/**
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java (revision 1039888)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java (revision )
@@ -769,8 +769,8 @@
* @param orderSpecs the order specs for the sort order properties.
* true indicates ascending order,
* false indicates descending.
- * @param resultFetchHint a hint on how many results should be fetched.
- * @return the query hits.
+ * @param orderFuncs
+ *@param resultFetchHint a hint on how many results should be fetched. @return the query hits.
* @throws IOException if an error occurs while searching the index.
*/
public MultiColumnQueryHits executeQuery(SessionImpl session,
@@ -778,11 +778,11 @@
Query query,
Path[] orderProps,
boolean[] orderSpecs,
- long resultFetchHint)
+ String[] orderFuncs, long resultFetchHint)
throws IOException {
checkOpen();
- Sort sort = new Sort(createSortFields(orderProps, orderSpecs));
+ Sort sort = new Sort(createSortFields(orderProps, orderSpecs, orderFuncs));
final IndexReader reader = getIndexReader(queryImpl.needsSystemTree());
JackrabbitIndexSearcher searcher = new JackrabbitIndexSearcher(
@@ -1016,10 +1016,11 @@
*
* @param orderProps the order properties.
* @param orderSpecs the order specs for the properties.
+ * @param orderFuncs
* @return an array of sort fields
*/
protected SortField[] createSortFields(Path[] orderProps,
- boolean[] orderSpecs) {
+ boolean[] orderSpecs, String[] orderFuncs) {
List sortFields = new ArrayList();
for (int i = 0; i < orderProps.length; i++) {
if (orderProps[i].getLength() == 1
@@ -1030,9 +1031,15 @@
// are first.
sortFields.add(new SortField(null, SortField.SCORE, orderSpecs[i]));
} else {
+ if ("upper-case".equals(orderFuncs[i])) {
+ sortFields.add(new SortField(orderProps[i].getString(), new UpperCaseSortComparator(scs), !orderSpecs[i]));
+ } else if ("lower-case".equals(orderFuncs[i])) {
+ sortFields.add(new SortField(orderProps[i].getString(), new LowerCaseSortComparator(scs), !orderSpecs[i]));
+ } else {
- sortFields.add(new SortField(orderProps[i].getString(), scs, !orderSpecs[i]));
- }
- }
+ sortFields.add(new SortField(orderProps[i].getString(), scs, !orderSpecs[i]));
+ }
+ }
+ }
return sortFields.toArray(new SortField[sortFields.size()]);
}
Index: jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/OrderQueryNode.java
===================================================================
--- jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/OrderQueryNode.java (revision 997303)
+++ jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/OrderQueryNode.java (revision )
@@ -16,16 +16,15 @@
*/
package org.apache.jackrabbit.spi.commons.query;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.jcr.RepositoryException;
-
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.Path;
-import org.apache.jackrabbit.spi.commons.name.PathBuilder;
import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
+import org.apache.jackrabbit.spi.commons.name.PathBuilder;
+import javax.jcr.RepositoryException;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Implements a query node that defines the order of nodes according to the
* values of properties.
@@ -56,6 +55,25 @@
return QueryNode.TYPE_ORDER;
}
+ public void newOrderSpec() {
+ specs.add(new OrderSpec((Path) null, true));
+ }
+
+ public void setAscending(boolean value) {
+ OrderSpec orderSpec = (OrderSpec) specs.get(specs.size() - 1);
+ orderSpec.setAscending(value);
+ }
+
+ public void setPath(Path path) {
+ OrderSpec orderSpec = (OrderSpec) specs.get(specs.size() - 1);
+ orderSpec.setPath(path);
+ }
+
+ public void setFunction(String name) {
+ OrderSpec orderSpec = (OrderSpec) specs.get(specs.size() - 1);
+ orderSpec.setFunction(name);
+ }
+
/**
* Adds an order specification to this query node.
*
@@ -141,12 +159,13 @@
/**
* The relative path to of the property
*/
- private final Path property;
+ private Path property;
/**
* If true this property is orderd ascending
*/
private boolean ascending;
+ private String function;
/**
* Creates a new OrderSpec for property.
@@ -212,6 +231,18 @@
this.ascending = ascending;
}
+ public void setPath(Path path) {
+ this.property = path;
+ }
+
+ public void setFunction(String name) {
+ this.function = name;
+ }
+
+ public String getFunction() {
+ return function;
+ }
+
/**
* Returns true if this order spec is equal
* to obj
@@ -227,6 +258,7 @@
}
return false;
}
+
}
/**