Return-Path: Delivered-To: apmail-jackrabbit-commits-archive@www.apache.org Received: (qmail 26276 invoked from network); 8 Jun 2009 14:25:46 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 8 Jun 2009 14:25:46 -0000 Received: (qmail 45226 invoked by uid 500); 8 Jun 2009 14:25:57 -0000 Delivered-To: apmail-jackrabbit-commits-archive@jackrabbit.apache.org Received: (qmail 45150 invoked by uid 500); 8 Jun 2009 14:25:57 -0000 Mailing-List: contact commits-help@jackrabbit.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@jackrabbit.apache.org Delivered-To: mailing list commits@jackrabbit.apache.org Received: (qmail 45141 invoked by uid 99); 8 Jun 2009 14:25:57 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 08 Jun 2009 14:25:57 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 08 Jun 2009 14:25:48 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 18F742388872; Mon, 8 Jun 2009 14:25:28 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r782644 - in /jackrabbit/trunk: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/constraint/ jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbi... Date: Mon, 08 Jun 2009 14:25:27 -0000 To: commits@jackrabbit.apache.org From: mreutegg@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090608142528.18F742388872@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: mreutegg Date: Mon Jun 8 14:25:26 2009 New Revision: 782644 URL: http://svn.apache.org/viewvc?rev=782644&view=rev Log: JCR-2076: JSR 283: Joins - orderings (work in progress) Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractScoreDocComparator.java (with props) jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LengthSortComparator.java (with props) jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LowerCaseSortComparator.java (with props) jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/UpperCaseSortComparator.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/Order.java (with props) Removed: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ComparableBoolean.java Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/FilterMultiColumnQuery.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiColumnQueryResult.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryObjectModelImpl.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SharedFieldCache.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SharedFieldSortComparator.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SingleColumnQueryResult.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SortedLuceneQueryHits.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/Util.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/constraint/ConstraintBuilder.java jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/query/AbstractOrderByTest.java jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/OrderingImpl.java Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java?rev=782644&r1=782643&r2=782644&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java Mon Jun 8 14:25:26 2009 @@ -24,6 +24,8 @@ import javax.jcr.Value; import javax.jcr.RepositoryException; +import javax.jcr.query.qom.QueryObjectModelFactory; + import java.util.Set; import java.util.HashSet; import java.util.Map; @@ -65,12 +67,12 @@ /** * Set<Name>, where Name is a variable name in the query statement. */ - private final Set variableNames = new HashSet(); + private final Set variableNames = new HashSet(); /** * Binding of variable name to value. Maps {@link Name} to {@link Value}. */ - private final Map bindValues = new HashMap(); + private final Map bindValues = new HashMap(); /** @@ -150,11 +152,20 @@ * @return an unmodifieable map, which contains the variable names and their * respective value. */ - protected Map getBindVariableValues() { + protected Map getBindVariableValues() { return Collections.unmodifiableMap(bindValues); } /** + * @return the query object model factory. + * @throws RepositoryException if an error occurs. + */ + protected QueryObjectModelFactory getQOMFactory() + throws RepositoryException { + return session.getWorkspace().getQueryManager().getQOMFactory(); + } + + /** * Returns true if this query node needs items under * /jcr:system to be queried. * Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractScoreDocComparator.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractScoreDocComparator.java?rev=782644&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractScoreDocComparator.java (added) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractScoreDocComparator.java Mon Jun 8 14:25:26 2009 @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.core.query.lucene; + +import java.util.List; +import java.util.ArrayList; +import java.io.IOException; + +import org.apache.lucene.search.ScoreDocComparator; +import org.apache.lucene.search.ScoreDoc; +import org.apache.lucene.search.SortField; +import org.apache.lucene.index.IndexReader; + +/** + * Abstract base class of {@link ScoreDocComparator} implementations. + */ +abstract class AbstractScoreDocComparator implements ScoreDocComparator { + + /** + * The index readers. + */ + protected final List readers = new ArrayList(); + + /** + * The document number starts for the {@link #readers}. + */ + protected final int[] starts; + + public AbstractScoreDocComparator(IndexReader reader) + throws IOException { + getIndexReaders(readers, reader); + + int maxDoc = 0; + this.starts = new int[readers.size() + 1]; + + for (int i = 0; i < readers.size(); i++) { + IndexReader r = readers.get(i); + starts[i] = maxDoc; + maxDoc += r.maxDoc(); + } + starts[readers.size()] = maxDoc; + } + + /** + * Compares sort values of i and j. If the + * sort values have differing types, then the sort order is defined on + * the type itself by calling compareTo() on the respective + * type class names. + * + * @param i first score doc. + * @param j second score doc. + * @return a negative integer if i should come before + * j
a positive integer if i + * should come after j
0 if they + * are equal + */ + public int compare(ScoreDoc i, ScoreDoc j) { + return Util.compare(sortValue(i), sortValue(j)); + } + + public int sortType() { + return SortField.CUSTOM; + } + + /** + * Returns the reader index for document n. + * + * @param n document number. + * @return the reader index. + */ + protected int readerIndex(int n) { + int lo = 0; + int hi = readers.size() - 1; + + while (hi >= lo) { + int mid = (lo + hi) >> 1; + int midValue = starts[mid]; + if (n < midValue) { + hi = mid - 1; + } else if (n > midValue) { + lo = mid + 1; + } else { + while (mid + 1 < readers.size() && starts[mid + 1] == midValue) { + mid++; + } + return mid; + } + } + return hi; + } + + /** + * Checks if reader is of type {@link MultiIndexReader} and if + * that's the case calls this method recursively for each reader within the + * multi index reader; otherwise the reader is simply added to the list. + * + * @param readers the list of index readers. + * @param reader the reader to check. + */ + private static void getIndexReaders(List readers, + IndexReader reader) { + if (reader instanceof MultiIndexReader) { + for (IndexReader r : ((MultiIndexReader) reader).getIndexReaders()) { + getIndexReaders(readers, r); + } + } else { + readers.add(reader); + } + } +} Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractScoreDocComparator.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/FilterMultiColumnQuery.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/FilterMultiColumnQuery.java?rev=782644&r1=782643&r2=782644&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/FilterMultiColumnQuery.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/FilterMultiColumnQuery.java Mon Jun 8 14:25:26 2009 @@ -84,6 +84,16 @@ } while (next != null && !constraint.evaluate(next, getSelectorNames(), searcher)); return next; } + + public int getSize() { + return -1; + } + + public void skip(int n) throws IOException { + while (n-- > 0) { + nextScoreNodes(); + } + } }; } } Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LengthSortComparator.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LengthSortComparator.java?rev=782644&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LengthSortComparator.java (added) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LengthSortComparator.java Mon Jun 8 14:25:26 2009 @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.core.query.lucene; + +import java.io.IOException; + +import org.apache.lucene.search.SortComparatorSource; +import org.apache.lucene.search.ScoreDocComparator; +import org.apache.lucene.search.ScoreDoc; +import org.apache.lucene.index.IndexReader; + +/** + * LengthSortComparator implements a sort comparator source that + * sorts on the length of property values. + */ +public class LengthSortComparator implements SortComparatorSource { + + private static final long serialVersionUID = 2513564768671391632L; + + /** + * Creates a new comparator. + * + * @param reader the current index reader. + * @param fieldname the name of the property to sort on. This is the string + * representation of {@link org.apache.jackrabbit.spi.Name + * Name}. + * @return the score doc comparator. + * @throws IOException if an error occurs while reading from the index. + */ + public ScoreDocComparator newComparator(IndexReader reader, + String fieldname) + throws IOException { + return new Comparator(reader, fieldname); + } + + private final class Comparator extends AbstractScoreDocComparator { + + /** + * The term look ups of the index segments. + */ + protected final SharedFieldCache.ValueIndex[] indexes; + + public Comparator(IndexReader reader, + String propertyName) throws IOException { + super(reader); + this.indexes = new SharedFieldCache.ValueIndex[readers.size()]; + + String namedLength = FieldNames.createNamedLength(propertyName, 0); + for (int i = 0; i < readers.size(); i++) { + IndexReader r = readers.get(i); + indexes[i] = SharedFieldCache.INSTANCE.getValueIndex( + r, FieldNames.PROPERTY_LENGTHS, + namedLength, LengthSortComparator.this); + } + } + + public Comparable sortValue(ScoreDoc i) { + int idx = readerIndex(i.doc); + return indexes[idx].getValue(i.doc - starts[idx]); + } + } +} Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LengthSortComparator.java ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LowerCaseSortComparator.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LowerCaseSortComparator.java?rev=782644&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LowerCaseSortComparator.java (added) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LowerCaseSortComparator.java Mon Jun 8 14:25:26 2009 @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.core.query.lucene; + +import java.io.IOException; + +import org.apache.lucene.search.ScoreDocComparator; +import org.apache.lucene.search.ScoreDoc; +import org.apache.lucene.search.SortField; +import org.apache.lucene.search.SortComparatorSource; +import org.apache.lucene.index.IndexReader; + +/** + * LowerCaseSortComparator implements a sort comparator that + * compares the lower-cased string values of a base sort comparator. + */ +public class LowerCaseSortComparator implements SortComparatorSource { + + private static final long serialVersionUID = 5396206509020979445L; + + /** + * The base sort comparator. + */ + private final SortComparatorSource base; + + /** + * Creates a new lower case sort comparator. + * + * @param base the base sort comparator source. + */ + public LowerCaseSortComparator(SortComparatorSource base) { + this.base = base; + } + + /** + * {@inheritDoc} + */ + public ScoreDocComparator newComparator(IndexReader reader, + String fieldname) + throws IOException { + return new Comparator(base.newComparator(reader, fieldname)); + } + + private static final class Comparator implements ScoreDocComparator { + + private ScoreDocComparator base; + + private Comparator(ScoreDocComparator base) { + this.base = base; + } + + /** + * @see Util#compare(Comparable, Comparable) + */ + public int compare(ScoreDoc i, ScoreDoc j) { + return Util.compare(sortValue(i), sortValue(j)); + } + + public Comparable sortValue(ScoreDoc i) { + Comparable c = base.sortValue(i); + if (c != null) { + return c.toString().toLowerCase(); + } else { + return null; + } + } + + public int sortType() { + return SortField.CUSTOM; + } + } +} Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LowerCaseSortComparator.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiColumnQueryResult.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiColumnQueryResult.java?rev=782644&r1=782643&r2=782644&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiColumnQueryResult.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiColumnQueryResult.java Mon Jun 8 14:25:26 2009 @@ -23,8 +23,8 @@ import org.apache.jackrabbit.core.ItemManager; import org.apache.jackrabbit.core.SessionImpl; import org.apache.jackrabbit.core.security.AccessManager; -import org.apache.jackrabbit.spi.Path; import org.apache.jackrabbit.spi.commons.query.qom.ColumnImpl; +import org.apache.jackrabbit.spi.commons.query.qom.OrderingImpl; /** * MultiColumnQueryResult implements a query result that executes @@ -37,6 +37,11 @@ */ private final MultiColumnQuery query; + /** + * The order specifier for each of the order properties. + */ + protected final OrderingImpl[] orderings; + public MultiColumnQueryResult(SearchIndex index, ItemManager itemMgr, SessionImpl session, @@ -45,14 +50,14 @@ MultiColumnQuery query, SpellSuggestion spellSuggestion, ColumnImpl[] columns, - Path[] orderProps, - boolean[] orderSpecs, + OrderingImpl[] orderings, boolean documentOrder, long offset, long limit) throws RepositoryException { super(index, itemMgr, session, accessMgr, queryImpl, spellSuggestion, - columns, orderProps, orderSpecs, documentOrder, offset, limit); + columns, documentOrder, offset, limit); this.query = query; + this.orderings = orderings; // if document order is requested get all results right away getResults(docOrder ? Integer.MAX_VALUE : index.getResultFetchSize()); } @@ -62,8 +67,7 @@ */ protected MultiColumnQueryHits executeQuery(long resultFetchHint) throws IOException { - return index.executeQuery(session, query, orderProps, - orderSpecs, resultFetchHint); + return index.executeQuery(session, query, orderings, resultFetchHint); } /** Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java?rev=782644&r1=782643&r2=782644&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java Mon Jun 8 14:25:26 2009 @@ -133,7 +133,8 @@ session, session.getAccessManager(), this, query, new SpellSuggestion(index.getSpellChecker(), root), getColumns(), orderProperties, ascSpecs, - getRespectDocumentOrder(), offset, limit); + orderProperties.length == 0 && getRespectDocumentOrder(), + offset, limit); } /** Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryObjectModelImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryObjectModelImpl.java?rev=782644&r1=782643&r2=782644&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryObjectModelImpl.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryObjectModelImpl.java Mon Jun 8 14:25:26 2009 @@ -20,11 +20,8 @@ import java.util.ArrayList; import javax.jcr.RepositoryException; -import javax.jcr.UnsupportedRepositoryOperationException; import javax.jcr.nodetype.PropertyDefinition; import javax.jcr.query.QueryResult; -import javax.jcr.query.qom.PropertyValue; -import javax.jcr.query.qom.QueryObjectModelConstants; import javax.jcr.query.qom.QueryObjectModelFactory; import org.apache.jackrabbit.core.ItemManager; @@ -35,14 +32,12 @@ import org.apache.jackrabbit.core.query.PropertyTypeRegistry; import org.apache.jackrabbit.core.query.lucene.constraint.Constraint; import org.apache.jackrabbit.core.query.lucene.constraint.ConstraintBuilder; -import org.apache.jackrabbit.spi.Path; -import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl; import org.apache.jackrabbit.spi.commons.query.qom.BindVariableValueImpl; import org.apache.jackrabbit.spi.commons.query.qom.ColumnImpl; import org.apache.jackrabbit.spi.commons.query.qom.DefaultTraversingQOMTreeVisitor; -import org.apache.jackrabbit.spi.commons.query.qom.OrderingImpl; import org.apache.jackrabbit.spi.commons.query.qom.QueryObjectModelTree; import org.apache.jackrabbit.spi.commons.query.qom.SelectorImpl; +import org.apache.jackrabbit.spi.commons.query.qom.OrderingImpl; /** * QueryObjectModelImpl... @@ -118,7 +113,7 @@ // expand columns without name for (ColumnImpl column : qomTree.getColumns()) { if (column.getColumnName() == null) { - QueryObjectModelFactory qomFactory = session.getWorkspace().getQueryManager().getQOMFactory(); + QueryObjectModelFactory qomFactory = getQOMFactory(); NodeTypeManagerImpl ntMgr = session.getNodeTypeManager(); SelectorImpl selector = qomTree.getSelector(column.getSelectorQName()); NodeTypeImpl nt = ntMgr.getNodeType(selector.getNodeTypeQName()); @@ -135,27 +130,12 @@ } } OrderingImpl[] orderings = qomTree.getOrderings(); - // TODO: there are many kinds of DynamicOperand that can be ordered by - Path[] orderProps = new Path[orderings.length]; - boolean[] orderSpecs = new boolean[orderings.length]; - for (int i = 0; i < orderings.length; i++) { - orderSpecs[i] = - QueryObjectModelConstants.JCR_ORDER_ASCENDING.equals( - orderings[i].getOrder()); - if (orderings[i].getOperand() instanceof PropertyValue) { - PropertyValue pv = (PropertyValue) orderings[i].getOperand(); - orderProps[i] = PathFactoryImpl.getInstance().create(pv.getPropertyName()); - } else { - throw new UnsupportedRepositoryOperationException("order by with" + - orderings[i].getOperand() + " not yet implemented"); - } - } return new MultiColumnQueryResult(index, itemMgr, session, session.getAccessManager(), // TODO: spell suggestion missing this, query, null, columns.toArray(new ColumnImpl[columns.size()]), - orderProps, orderSpecs, - getRespectDocumentOrder(), offset, limit); + orderings, orderings.length == 0 && getRespectDocumentOrder(), + offset, limit); } //--------------------------< internal >------------------------------------ Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java?rev=782644&r1=782643&r2=782644&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java Mon Jun 8 14:25:26 2009 @@ -20,7 +20,6 @@ import org.apache.jackrabbit.core.SessionImpl; import org.apache.jackrabbit.core.security.AccessManager; import org.apache.jackrabbit.spi.Name; -import org.apache.jackrabbit.spi.Path; import org.apache.jackrabbit.spi.commons.query.qom.ColumnImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -83,16 +82,6 @@ protected final Map columns = new LinkedHashMap(); /** - * The relative paths of properties to use for ordering the result set. - */ - protected final Path[] orderProps; - - /** - * The order specifier for each of the order properties. - */ - protected final boolean[] orderSpecs; - - /** * The result nodes including their score. This list is populated on a lazy * basis while a client iterates through the results. *

@@ -154,9 +143,6 @@ * @param spellSuggestion the spell suggestion or null if none * is available. * @param columns the select properties of the query. - * @param orderProps the relative paths of the order properties. - * @param orderSpecs the order specs, one for each order property - * name. * @param documentOrder if true the result is returned in * document order. * @param limit the maximum result size @@ -173,8 +159,6 @@ AbstractQueryImpl queryImpl, SpellSuggestion spellSuggestion, ColumnImpl[] columns, - Path[] orderProps, - boolean[] orderSpecs, boolean documentOrder, long offset, long limit) throws RepositoryException { @@ -184,9 +168,7 @@ this.accessMgr = accessMgr; this.queryImpl = queryImpl; this.spellSuggestion = spellSuggestion; - this.orderProps = orderProps; - this.orderSpecs = orderSpecs; - this.docOrder = orderProps.length == 0 && documentOrder; + this.docOrder = documentOrder; this.offset = offset; this.limit = limit; for (ColumnImpl column : columns) { @@ -196,7 +178,6 @@ throw new IllegalArgumentException(msg); } this.columns.put(cn, column); - } } Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java?rev=782644&r1=782643&r2=782644&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java Mon Jun 8 14:25:26 2009 @@ -45,6 +45,17 @@ import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl; import org.apache.jackrabbit.spi.commons.query.DefaultQueryNodeFactory; import org.apache.jackrabbit.spi.commons.query.qom.QueryObjectModelTree; +import org.apache.jackrabbit.spi.commons.query.qom.OrderingImpl; +import org.apache.jackrabbit.spi.commons.query.qom.QOMTreeVisitor; +import org.apache.jackrabbit.spi.commons.query.qom.DefaultTraversingQOMTreeVisitor; +import org.apache.jackrabbit.spi.commons.query.qom.LengthImpl; +import org.apache.jackrabbit.spi.commons.query.qom.LowerCaseImpl; +import org.apache.jackrabbit.spi.commons.query.qom.UpperCaseImpl; +import org.apache.jackrabbit.spi.commons.query.qom.FullTextSearchScoreImpl; +import org.apache.jackrabbit.spi.commons.query.qom.NodeLocalNameImpl; +import org.apache.jackrabbit.spi.commons.query.qom.NodeNameImpl; +import org.apache.jackrabbit.spi.commons.query.qom.PropertyValueImpl; +import org.apache.jackrabbit.spi.commons.query.qom.DynamicOperandImpl; import org.apache.jackrabbit.uuid.UUID; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -542,7 +553,7 @@ if (!index.getIndexFormatVersion().equals(getIndexFormatVersion())) { log.warn("Using Version {} for reading. Please re-index version " + "storage for optimal performance.", - new Integer(getIndexFormatVersion().getVersion())); + getIndexFormatVersion().getVersion()); } } @@ -773,23 +784,19 @@ * * @param session the session that executes the query. * @param query the query. - * @param orderProps name of the properties for sort order. - * @param orderSpecs the order specs for the sort order properties. - * true indicates ascending order, - * false indicates descending. + * @param orderings the order specs for the sort order. * @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, MultiColumnQuery query, - Path[] orderProps, - boolean[] orderSpecs, + OrderingImpl[] orderings, long resultFetchHint) throws IOException { checkOpen(); - Sort sort = new Sort(createSortFields(orderProps, orderSpecs)); + Sort sort = new Sort(createSortFields(orderings)); final IndexReader reader = getIndexReader(); JackrabbitIndexSearcher searcher = new JackrabbitIndexSearcher( @@ -991,6 +998,77 @@ } /** + * Creates sort fields for the ordering specifications. + * + * @param orderings the ordering specifications. + * @return the sort fields. + */ + protected SortField[] createSortFields(OrderingImpl[] orderings) { + List sortFields = new ArrayList(); + for (final OrderingImpl ordering : orderings) { + QOMTreeVisitor visitor = new DefaultTraversingQOMTreeVisitor() { + + public Object visit(LengthImpl node, Object data) throws Exception { + PropertyValueImpl propValue = (PropertyValueImpl) node.getPropertyValue(); + return new SortField(propValue.getPropertyQName().toString(), + new LengthSortComparator(), + !ordering.isAscending()); + } + + public Object visit(LowerCaseImpl node, Object data) + throws Exception { + SortField sf = (SortField) super.visit(node, data); + return new SortField(sf.getField(), + new LowerCaseSortComparator(sf.getFactory()), + sf.getReverse()); + } + + public Object visit(UpperCaseImpl node, Object data) + throws Exception { + SortField sf = (SortField) super.visit(node, data); + return new SortField(sf.getField(), + new UpperCaseSortComparator(sf.getFactory()), + sf.getReverse()); + } + + public Object visit(FullTextSearchScoreImpl node, Object data) + throws Exception { + // TODO: selector ignored + return new SortField(null, SortField.SCORE, + ordering.isAscending()); + } + + public Object visit(NodeLocalNameImpl node, Object data) throws Exception { + return new SortField(FieldNames.LOCAL_NAME, + SortField.STRING, !ordering.isAscending()); + } + + public Object visit(NodeNameImpl node, Object data) throws Exception { + return new SortField(FieldNames.LABEL, + SortField.STRING, !ordering.isAscending()); + } + + public Object visit(PropertyValueImpl node, Object data) + throws Exception { + return new SortField(node.getPropertyQName().toString(), + scs, !ordering.isAscending()); + } + + public Object visit(OrderingImpl node, Object data) + throws Exception { + return ((DynamicOperandImpl) node.getOperand()).accept(this, data); + } + }; + try { + sortFields.add((SortField) ordering.accept(visitor, null)); + } catch (Exception e) { + // TODO + } + } + return sortFields.toArray(new SortField[sortFields.size()]); + } + + /** * Creates a lucene Document for a node state using the * namespace mappings nsMappings. * @@ -1234,44 +1312,36 @@ } try { ItemStateManager ism = getContext().getItemStateManager(); - for (int i = 0; i < aggregateRules.length; i++) { + for (AggregateRule aggregateRule : aggregateRules) { boolean ruleMatched = false; // node includes - NodeState[] aggregates = aggregateRules[i].getAggregatedNodeStates(state); + NodeState[] aggregates = aggregateRule.getAggregatedNodeStates(state); if (aggregates != null) { ruleMatched = true; - for (int j = 0; j < aggregates.length; j++) { - Document aDoc = createDocument(aggregates[j], - getNamespaceMappings(), - index.getIndexFormatVersion()); + for (NodeState aggregate : aggregates) { + Document aDoc = createDocument(aggregate, getNamespaceMappings(), index.getIndexFormatVersion()); // transfer fields to doc if there are any Fieldable[] fulltextFields = aDoc.getFieldables(FieldNames.FULLTEXT); if (fulltextFields != null) { - for (int k = 0; k < fulltextFields.length; k++) { - doc.add(fulltextFields[k]); + for (Fieldable fulltextField : fulltextFields) { + doc.add(fulltextField); } - doc.add(new Field(FieldNames.AGGREGATED_NODE_UUID, - aggregates[j].getNodeId().getUUID().toString(), - Field.Store.NO, - Field.Index.NOT_ANALYZED_NO_NORMS)); + doc.add(new Field(FieldNames.AGGREGATED_NODE_UUID, aggregate.getNodeId().getUUID().toString(), Field.Store.NO, Field.Index.NOT_ANALYZED_NO_NORMS)); } } } // property includes - PropertyState[] propStates = aggregateRules[i].getAggregatedPropertyStates(state); + PropertyState[] propStates = aggregateRule.getAggregatedPropertyStates(state); if (propStates != null) { ruleMatched = true; - for (int j = 0; j < propStates.length; j++) { - PropertyState propState = propStates[j]; - String namePrefix = FieldNames.createNamedValue( - getNamespaceMappings().translateName(propState.getName()), ""); + for (PropertyState propState : propStates) { + String namePrefix = FieldNames.createNamedValue(getNamespaceMappings().translateName(propState.getName()), ""); NodeState parent = (NodeState) ism.getItemState(propState.getParentId()); Document aDoc = createDocument(parent, getNamespaceMappings(), getIndex().getIndexFormatVersion()); // find the right fields to transfer Fieldable[] fields = aDoc.getFieldables(FieldNames.PROPERTIES); Token t = new Token(); - for (int k = 0; k < fields.length; k++) { - Fieldable field = fields[k]; + for (Fieldable field : fields) { // assume properties fields use SingleTokenStream t = field.tokenStreamValue().next(t); String value = new String(t.termBuffer(), 0, t.termLength()); @@ -1284,10 +1354,7 @@ value = FieldNames.createNamedValue(path, value); t.setTermBuffer(value); doc.add(new Field(field.name(), new SingletonTokenStream(t))); - doc.add(new Field(FieldNames.AGGREGATED_NODE_UUID, - parent.getNodeId().getUUID().toString(), - Field.Store.NO, - Field.Index.NOT_ANALYZED_NO_NORMS)); + doc.add(new Field(FieldNames.AGGREGATED_NODE_UUID, parent.getNodeId().getUUID().toString(), Field.Store.NO, Field.Index.NOT_ANALYZED_NO_NORMS)); } } } @@ -1355,8 +1422,8 @@ return; } try { - for (int i = 0; i < aggregateRules.length; i++) { - NodeState root = aggregateRules[i].getAggregateRoot(state); + for (AggregateRule aggregateRule : aggregateRules) { + NodeState root = aggregateRule.getAggregateRoot(state); if (root != null) { map.put(root.getNodeId().getUUID(), root); } @@ -1477,8 +1544,8 @@ * {@inheritDoc} */ public void release() throws IOException { - for (int i = 0; i < subReaders.length; i++) { - subReaders[i].release(); + for (CachingMultiIndexReader subReader : subReaders) { + subReader.release(); } } @@ -1522,8 +1589,8 @@ public int hashCode() { int hash = 0; - for (int i = 0; i < subReaders.length; i++) { - hash = 31 * hash + subReaders[i].hashCode(); + for (CachingMultiIndexReader subReader : subReaders) { + hash = 31 * hash + subReader.hashCode(); } return hash; } @@ -1532,8 +1599,7 @@ * {@inheritDoc} */ public ForeignSegmentDocId createDocId(UUID uuid) throws IOException { - for (int i = 0; i < subReaders.length; i++) { - CachingMultiIndexReader subReader = subReaders[i]; + for (CachingMultiIndexReader subReader : subReaders) { ForeignSegmentDocId doc = subReader.createDocId(uuid); if (doc != null) { return doc; Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SharedFieldCache.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SharedFieldCache.java?rev=782644&r1=782643&r2=782644&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SharedFieldCache.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SharedFieldCache.java Mon Jun 8 14:25:26 2009 @@ -21,7 +21,7 @@ import org.apache.lucene.index.TermEnum; import org.apache.lucene.index.TermPositions; import org.apache.lucene.index.TermDocs; -import org.apache.lucene.search.SortComparator; +import org.apache.lucene.search.SortComparatorSource; import java.io.IOException; import java.util.HashMap; @@ -58,7 +58,7 @@ /** * Values (Comparable) map indexed by document id. */ - public final Map valuesMap; + public final Map valuesMap; /** * Boolean indicating whether the {@link #valuesMap} impl has to be used @@ -86,17 +86,17 @@ public Comparable getValue(int i) { if (sparse) { - return valuesMap == null ? null : (Comparable) valuesMap.get(new Integer(i)); + return valuesMap == null ? null : valuesMap.get(i); } else { return values[i]; } } - private Map getValuesMap(Comparable[] values, int setValues) { - Map map = new HashMap(setValues); + private Map getValuesMap(Comparable[] values, int setValues) { + Map map = new HashMap(setValues); for (int i = 0; i < values.length && setValues > 0; i++) { if (values[i] != null) { - map.put(new Integer(i), values[i]); + map.put(i, values[i]); setValues--; } } @@ -121,7 +121,7 @@ /** * The internal cache. Maps Entry to array of interpreted term values. */ - private final Map cache = new WeakHashMap(); + private final Map> cache = new WeakHashMap>(); /** * Private constructor. @@ -147,7 +147,7 @@ public ValueIndex getValueIndex(IndexReader reader, String field, String prefix, - SortComparator comparator) + SortComparatorSource comparator) throws IOException { if (reader instanceof ReadOnlyIndexReader) { @@ -225,27 +225,27 @@ * See if a ValueIndex object is in the cache. */ ValueIndex lookup(IndexReader reader, String field, - String prefix, SortComparator comparer) { + String prefix, SortComparatorSource comparer) { Key key = new Key(field, prefix, comparer); synchronized (this) { - HashMap readerCache = (HashMap) cache.get(reader); + Map readerCache = cache.get(reader); if (readerCache == null) { return null; } - return (ValueIndex) readerCache.get(key); + return readerCache.get(key); } } /** * Put a ValueIndex value to cache. */ - Object store(IndexReader reader, String field, String prefix, - SortComparator comparer, ValueIndex value) { + ValueIndex store(IndexReader reader, String field, String prefix, + SortComparatorSource comparer, ValueIndex value) { Key key = new Key(field, prefix, comparer); synchronized (this) { - HashMap readerCache = (HashMap) cache.get(reader); + Map readerCache = cache.get(reader); if (readerCache == null) { - readerCache = new HashMap(); + readerCache = new HashMap(); cache.put(reader, readerCache); } return readerCache.put(key, value); @@ -263,13 +263,13 @@ private Comparable getValue(String value, int type) { switch (type) { case PropertyType.BOOLEAN: - return ComparableBoolean.valueOf(Boolean.valueOf(value).booleanValue()); + return Boolean.valueOf(value); case PropertyType.DATE: - return new Long(DateField.stringToTime(value)); + return DateField.stringToTime(value); case PropertyType.LONG: - return new Long(LongField.stringToLong(value)); + return LongField.stringToLong(value); case PropertyType.DOUBLE: - return new Double(DoubleField.stringToDouble(value)); + return DoubleField.stringToDouble(value); case PropertyType.DECIMAL: return DecimalField.stringToDecimal(value); default: @@ -285,12 +285,12 @@ private final String field; private final String prefix; - private final SortComparator comparator; + private final SortComparatorSource comparator; /** * Creates Key for ValueIndex lookup. */ - Key(String field, String prefix, SortComparator comparator) { + Key(String field, String prefix, SortComparatorSource comparator) { this.field = field.intern(); this.prefix = prefix.intern(); this.comparator = comparator; Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SharedFieldSortComparator.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SharedFieldSortComparator.java?rev=782644&r1=782643&r2=782644&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SharedFieldSortComparator.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SharedFieldSortComparator.java Mon Jun 8 14:25:26 2009 @@ -17,14 +17,11 @@ package org.apache.jackrabbit.core.query.lucene; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; import org.apache.lucene.index.IndexReader; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.ScoreDocComparator; import org.apache.lucene.search.SortComparator; -import org.apache.lucene.search.SortField; import org.apache.lucene.document.Document; import org.apache.jackrabbit.core.state.ItemStateManager; import org.apache.jackrabbit.core.state.PropertyState; @@ -45,6 +42,8 @@ */ public class SharedFieldSortComparator extends SortComparator { + private static final long serialVersionUID = 2609351820466200052L; + /** * The name of the shared field in the lucene index. */ @@ -124,104 +123,6 @@ } /** - * Checks if reader is of type {@link MultiIndexReader} and if - * that's the case calls this method recursively for each reader within the - * multi index reader; otherwise the reader is simply added to the list. - * - * @param readers the list of index readers. - * @param reader the reader to check. - */ - private static void getIndexReaders(List readers, IndexReader reader) { - if (reader instanceof MultiIndexReader) { - IndexReader[] r = ((MultiIndexReader) reader).getIndexReaders(); - for (int i = 0; i < r.length; i++) { - getIndexReaders(readers, r[i]); - } - } else { - readers.add(reader); - } - } - - /** - * Abstract base class of {@link ScoreDocComparator} implementations. - */ - abstract class AbstractScoreDocComparator implements ScoreDocComparator { - - /** - * The index readers. - */ - protected final List readers = new ArrayList(); - - /** - * The document number starts for the {@link #readers}. - */ - protected final int[] starts; - - public AbstractScoreDocComparator(IndexReader reader) - throws IOException { - getIndexReaders(readers, reader); - - int maxDoc = 0; - this.starts = new int[readers.size() + 1]; - - for (int i = 0; i < readers.size(); i++) { - IndexReader r = (IndexReader) readers.get(i); - starts[i] = maxDoc; - maxDoc += r.maxDoc(); - } - starts[readers.size()] = maxDoc; - } - - /** - * Compares sort values of i and j. If the - * sort values have differing types, then the sort order is defined on - * the type itself by calling compareTo() on the respective - * type class names. - * - * @param i first score doc. - * @param j second score doc. - * @return a negative integer if i should come before - * j
a positive integer if i - * should come after j
0 if they - * are equal - */ - public int compare(ScoreDoc i, ScoreDoc j) { - return Util.compare(sortValue(i), sortValue(j)); - } - - public int sortType() { - return SortField.CUSTOM; - } - - /** - * Returns the reader index for document n. - * - * @param n document number. - * @return the reader index. - */ - protected int readerIndex(int n) { - int lo = 0; - int hi = readers.size() - 1; - - while (hi >= lo) { - int mid = (lo + hi) >> 1; - int midValue = starts[mid]; - if (n < midValue) { - hi = mid - 1; - } else if (n > midValue) { - lo = mid + 1; - } else { - while (mid + 1 < readers.size() && starts[mid + 1] == midValue) { - mid++; - } - return mid; - } - } - return hi; - } - } - - /** * A score doc comparator that works for order by clauses with properties * directly on the result nodes. */ @@ -240,7 +141,7 @@ String namedValue = FieldNames.createNamedValue(propertyName, ""); for (int i = 0; i < readers.size(); i++) { - IndexReader r = (IndexReader) readers.get(i); + IndexReader r = readers.get(i); indexes[i] = SharedFieldCache.INSTANCE.getValueIndex(r, field, namedValue, SharedFieldSortComparator.this); } @@ -283,7 +184,7 @@ public Comparable sortValue(ScoreDoc i) { try { int idx = readerIndex(i.doc); - IndexReader reader = (IndexReader) readers.get(idx); + IndexReader reader = readers.get(idx); Document doc = reader.document(i.doc - starts[idx], FieldSelectors.UUID); String uuid = doc.get(FieldNames.UUID); Path path = hmgr.getPath(new NodeId(UUID.fromString(uuid))); @@ -330,8 +231,8 @@ * {@inheritDoc} */ public Comparable sortValue(ScoreDoc i) { - for (int j = 0; j < comparators.length; j++) { - Comparable c = comparators[j].sortValue(i); + for (ScoreDocComparator comparator : comparators) { + Comparable c = comparator.sortValue(i); if (c != null) { return c; } Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SingleColumnQueryResult.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SingleColumnQueryResult.java?rev=782644&r1=782643&r2=782644&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SingleColumnQueryResult.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SingleColumnQueryResult.java Mon Jun 8 14:25:26 2009 @@ -23,8 +23,8 @@ import org.apache.jackrabbit.core.ItemManager; import org.apache.jackrabbit.core.SessionImpl; import org.apache.jackrabbit.core.security.AccessManager; -import org.apache.jackrabbit.spi.Path; import org.apache.jackrabbit.spi.commons.query.qom.ColumnImpl; +import org.apache.jackrabbit.spi.Path; import org.apache.lucene.search.Query; /** @@ -38,6 +38,16 @@ */ private final Query query; + /** + * The relative paths of properties to use for ordering the result set. + */ + protected final Path[] orderProps; + + /** + * The order specifier for each of the order properties. + */ + protected final boolean[] orderSpecs; + public SingleColumnQueryResult(SearchIndex index, ItemManager itemMgr, SessionImpl session, @@ -52,8 +62,10 @@ long offset, long limit) throws RepositoryException { super(index, itemMgr, session, accessMgr, queryImpl, spellSuggestion, - columns, orderProps, orderSpecs, documentOrder, offset, limit); + columns, documentOrder, offset, limit); this.query = query; + this.orderProps = orderProps; + this.orderSpecs = orderSpecs; // if document order is requested get all results right away getResults(docOrder ? Integer.MAX_VALUE : index.getResultFetchSize()); } Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SortedLuceneQueryHits.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SortedLuceneQueryHits.java?rev=782644&r1=782643&r2=782644&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SortedLuceneQueryHits.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SortedLuceneQueryHits.java Mon Jun 8 14:25:26 2009 @@ -80,7 +80,7 @@ /** * The score nodes. */ - private final List scoreNodes = new ArrayList(); + private final List scoreNodes = new ArrayList(); /** * The total number of hits. @@ -136,7 +136,7 @@ this.numHits = Math.max(this.numHits, hitIndex * 2); getHits(); } - return (ScoreNode) scoreNodes.get(hitIndex); + return scoreNodes.get(hitIndex); } /** @@ -161,7 +161,7 @@ NodeId id = new NodeId(UUID.fromString(uuid)); scoreNodes.add(new ScoreNode(id, docs[i].score, docs[i].doc)); } - log.debug("getHits() {}/{}", new Integer(scoreNodes.size()), new Integer(numHits)); + log.debug("getHits() {}/{}", scoreNodes.size(), numHits); // double hits for next round numHits *= 2; } Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/UpperCaseSortComparator.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/UpperCaseSortComparator.java?rev=782644&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/UpperCaseSortComparator.java (added) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/UpperCaseSortComparator.java Mon Jun 8 14:25:26 2009 @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.core.query.lucene; + +import java.io.IOException; + +import org.apache.lucene.search.ScoreDocComparator; +import org.apache.lucene.search.ScoreDoc; +import org.apache.lucene.search.SortField; +import org.apache.lucene.search.SortComparatorSource; +import org.apache.lucene.index.IndexReader; + +/** + * UpperCaseSortComparator implements a sort comparator that + * compares the upper-cased string values of a base sort comparator. + */ +public class UpperCaseSortComparator implements SortComparatorSource { + + private static final long serialVersionUID = 2562371983498948119L; + + /** + * The base sort comparator. + */ + private final SortComparatorSource base; + + /** + * Creates a new upper case sort comparator. + * + * @param base the base sort comparator source. + */ + public UpperCaseSortComparator(SortComparatorSource base) { + this.base = base; + } + + /** + * {@inheritDoc} + */ + public ScoreDocComparator newComparator(IndexReader reader, + String fieldname) + throws IOException { + return new Comparator(base.newComparator(reader, fieldname)); + } + + private static final class Comparator implements ScoreDocComparator { + + private ScoreDocComparator base; + + private Comparator(ScoreDocComparator base) { + this.base = base; + } + + /** + * @see Util#compare(Comparable, Comparable) + */ + public int compare(ScoreDoc i, ScoreDoc j) { + return Util.compare(sortValue(i), sortValue(j)); + } + + public Comparable sortValue(ScoreDoc i) { + Comparable c = base.sortValue(i); + if (c != null) { + return c.toString().toUpperCase(); + } else { + return null; + } + } + + public int sortType() { + return SortField.CUSTOM; + } + } +} \ No newline at end of file Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/UpperCaseSortComparator.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/Util.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/Util.java?rev=782644&r1=782643&r2=782644&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/Util.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/Util.java Mon Jun 8 14:25:26 2009 @@ -25,7 +25,6 @@ import org.slf4j.LoggerFactory; import org.slf4j.Logger; -import java.util.Iterator; import java.util.regex.Pattern; import java.io.IOException; @@ -51,8 +50,8 @@ * @param old the document to dispose. */ public static void disposeDocument(Document old) { - for (Iterator it = old.getFields().iterator(); it.hasNext(); ) { - Fieldable f = (Fieldable) it.next(); + for (Object o : old.getFields()) { + Fieldable f = (Fieldable) o; try { if (f.readerValue() != null) { f.readerValue().close(); @@ -75,8 +74,8 @@ * otherwise. */ public static boolean isDocumentReady(Document doc) { - for (Iterator it = doc.getFields().iterator(); it.hasNext(); ) { - Fieldable f = (Fieldable) it.next(); + for (Object o : doc.getFields()) { + Fieldable f = (Fieldable) o; if (f instanceof LazyTextExtractorField) { LazyTextExtractorField field = (LazyTextExtractorField) f; if (!field.isExtractorFinished()) { @@ -145,13 +144,13 @@ case PropertyType.BINARY: return null; case PropertyType.BOOLEAN: - return ComparableBoolean.valueOf(value.getBoolean()); + return value.getBoolean(); case PropertyType.DATE: - return new Long(value.getDate().getTimeInMillis()); + return value.getDate().getTimeInMillis(); case PropertyType.DOUBLE: - return new Double(value.getDouble()); + return value.getDouble(); case PropertyType.LONG: - return new Long(value.getLong()); + return value.getLong(); case PropertyType.DECIMAL: return value.getDecimal(); case PropertyType.NAME: @@ -183,13 +182,13 @@ throws ValueFormatException, RepositoryException { switch (value.getType()) { case PropertyType.BOOLEAN: - return ComparableBoolean.valueOf(value.getBoolean()); + return value.getBoolean(); case PropertyType.DATE: - return new Long(value.getDate().getTimeInMillis()); + return value.getDate().getTimeInMillis(); case PropertyType.DOUBLE: - return new Double(value.getDouble()); + return value.getDouble(); case PropertyType.LONG: - return new Long(value.getLong()); + return value.getLong(); case PropertyType.DECIMAL: return value.getDecimal(); case PropertyType.NAME: @@ -258,16 +257,16 @@ Comparable c2; switch (v1.getType()) { case PropertyType.BOOLEAN: - c2 = ComparableBoolean.valueOf(v2.getBoolean()); + c2 = v2.getBoolean(); break; case PropertyType.DATE: - c2 = new Long(v2.getDate().getTimeInMillis()); + c2 = v2.getDate().getTimeInMillis(); break; case PropertyType.DOUBLE: - c2 = new Double(v2.getDouble()); + c2 = v2.getDouble(); break; case PropertyType.LONG: - c2 = new Long(v2.getLong()); + c2 = v2.getLong(); break; case PropertyType.DECIMAL: c2 = v2.getDecimal(); Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/constraint/ConstraintBuilder.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/constraint/ConstraintBuilder.java?rev=782644&r1=782643&r2=782644&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/constraint/ConstraintBuilder.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/constraint/ConstraintBuilder.java Mon Jun 8 14:25:26 2009 @@ -80,7 +80,7 @@ * constraint. */ public static Constraint create(ConstraintImpl constraint, - Map bindVariableValues, + Map bindVariableValues, SelectorImpl[] selectors, LuceneQueryFactory factory, ValueFactory vf) @@ -103,7 +103,7 @@ /** * The bind variables and their values. */ - private final Map bindVariableValues; + private final Map bindVariableValues; /** * The selectors of the query. @@ -128,7 +128,7 @@ * @param factory the lucene query factory. * @param vf the value factory of the current session. */ - Visitor(Map bindVariableValues, + Visitor(Map bindVariableValues, SelectorImpl[] selectors, LuceneQueryFactory factory, ValueFactory vf) { @@ -333,9 +333,9 @@ // assume default selector return selectors[0]; } - for (int i = 0; i < selectors.length; i++) { - if (selectors[i].getSelectorQName().equals(name)) { - return selectors[i]; + for (SelectorImpl selector : selectors) { + if (selector.getSelectorQName().equals(name)) { + return selector; } } return null; Modified: jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/query/AbstractOrderByTest.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/query/AbstractOrderByTest.java?rev=782644&r1=782643&r2=782644&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/query/AbstractOrderByTest.java (original) +++ jackrabbit/trunk/jackrabbit-jcr-tests/src/main/java/org/apache/jackrabbit/test/api/query/AbstractOrderByTest.java Mon Jun 8 14:25:26 2009 @@ -22,6 +22,11 @@ import javax.jcr.Repository; import javax.jcr.query.Query; import javax.jcr.query.QueryResult; +import javax.jcr.query.qom.QueryObjectModel; +import javax.jcr.query.qom.QueryObjectModelFactory; +import javax.jcr.query.qom.Ordering; +import javax.jcr.query.qom.PropertyValue; + import java.util.Calendar; import java.util.Collections; import java.util.Arrays; @@ -123,6 +128,10 @@ result = q.execute(); checkResultOrder(result, nodeNames); + q = createQOM(true); + result = q.execute(); + checkResultOrder(result, nodeNames); + // then check descending Collections.reverse(Arrays.asList(nodeNames)); @@ -135,6 +144,10 @@ q = superuser.getWorkspace().getQueryManager().createQuery(xpath + " descending", Query.XPATH); result = q.execute(); checkResultOrder(result, nodeNames); + + q = createQOM(false); + result = q.execute(); + checkResultOrder(result, nodeNames); } /** @@ -157,4 +170,21 @@ } } + protected QueryObjectModel createQOM(boolean ascending) + throws RepositoryException { + QueryObjectModelFactory qf = superuser.getWorkspace().getQueryManager().getQOMFactory(); + PropertyValue pv = qf.propertyValue("s", propertyName1); + Ordering ordering; + if (ascending) { + ordering = qf.ascending(pv); + } else { + ordering = qf.descending(pv); + } + return qf.createQuery( + qf.selector(testNodeType, "s"), + qf.descendantNode("s", testRoot), + new Ordering[]{ordering}, + null + ); + } } Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/Order.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/Order.java?rev=782644&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/Order.java (added) +++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/Order.java Mon Jun 8 14:25:26 2009 @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.spi.commons.query.qom; + +import javax.jcr.query.qom.QueryObjectModelConstants; + +/** + * Enumeration of the JCR 2.0 query order. + * + * @since Apache Jackrabbit 2.0 + */ +public enum Order { + + ASCENDING(QueryObjectModelConstants.JCR_ORDER_ASCENDING), + + DESCENDING(QueryObjectModelConstants.JCR_ORDER_DESCENDING); + + /** + * JCR name of this order. + */ + private final String name; + + private Order(String name) { + this.name = name; + } + + /** + * @return the JCR name of this order. + */ + public String getName() { + return name; + } + + /** + * Return the order with the given JCR name. + * + * @param name the JCR name of an order. + * @return the order with the given name. + * @throws IllegalArgumentException if name is not a known JCR + * order name. + */ + public static Order getOrderByName(String name) { + for (Order order : Order.values()) { + if (order.name.equals(name)) { + return order; + } + } + throw new IllegalArgumentException("Unknown order name: " + name); + } +} Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/Order.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/OrderingImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/OrderingImpl.java?rev=782644&r1=782643&r2=782644&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/OrderingImpl.java (original) +++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/qom/OrderingImpl.java Mon Jun 8 14:25:26 2009 @@ -40,14 +40,14 @@ /** * The order. */ - private final String order; + private final Order order; OrderingImpl(NamePathResolver resolver, DynamicOperandImpl operand, String order) { super(resolver); this.operand = operand; - this.order = order; + this.order = Order.getOrderByName(order); } /** @@ -67,9 +67,16 @@ * */ public String getOrder() { - return order; + return order.getName(); } + /** + * @return true if this ordering is ascending. Returns + * false if ordering is descending. + */ + public boolean isAscending() { + return order == Order.ASCENDING; + } //------------------------< AbstractQOMNode >-------------------------------