jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ju...@apache.org
Subject svn commit: r792142 [8/35] - in /jackrabbit/sandbox/JCR-1456: ./ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/ jackrabbit-core/ jackrabbit-core/src/main/java/org/apache/jackrabb...
Date Wed, 08 Jul 2009 13:57:46 GMT
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java Wed Jul  8 13:57:13 2009
@@ -35,7 +35,6 @@
 import javax.jcr.query.InvalidQueryException;
 import javax.jcr.query.QueryResult;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.apache.jackrabbit.spi.commons.query.qom.QueryObjectModelTree;
 
 import javax.jcr.version.VersionException;
 import java.text.NumberFormat;
@@ -51,22 +50,6 @@
     private static final Logger log = LoggerFactory.getLogger(QueryImpl.class);
 
     /**
-     * A string constant representing the JCR-SQL2 query language.
-     *
-     * @since JCR 2.0
-     * TODO: REMOVE WHEN JSR 283 IS FINAL!!
-     */
-    public static final String JCR_SQL2 = "JCR-SQL2";
-
-    /**
-     * A string constant representing the JCR-JQOM query language.
-     *
-     * @since JCR 2.0
-     * TODO: REMOVE WHEN JSR 283 IS FINAL!!
-     */
-    public static final String JCR_JQOM = "JCR-JQOM";
-
-    /**
      * The session of the user executing this query
      */
     protected SessionImpl session;
@@ -105,7 +88,7 @@
     /**
      * The maximum result size
      */
-    private long limit;
+    private long limit = -1;
 
     /**
      * The offset in the total result set
@@ -119,53 +102,19 @@
                      ItemManager itemMgr,
                      QueryHandler handler,
                      String statement,
-                     String language) throws InvalidQueryException {
+                     String language,
+                     Node node) throws InvalidQueryException {
         checkNotInitialized();
         this.session = session;
         this.statement = statement;
         this.language = language;
         this.handler = handler;
-        this.query = handler.createExecutableQuery(session, itemMgr, statement, language);
-        setInitialized();
-    }
-
-    /**
-     * @inheritDoc
-     */
-    public void init(SessionImpl session,
-                     ItemManager itemMgr,
-                     QueryHandler handler,
-                     Node node)
-            throws InvalidQueryException, RepositoryException {
-        checkNotInitialized();
-        this.session = session;
         this.node = node;
-        this.handler = handler;
-
-        if (!node.isNodeType(session.getJCRName(NameConstants.NT_QUERY))) {
-            throw new InvalidQueryException("node is not of type nt:query");
-        }
-        statement = node.getProperty(session.getJCRName(NameConstants.JCR_STATEMENT)).getString();
-        language = node.getProperty(session.getJCRName(NameConstants.JCR_LANGUAGE)).getString();
-        query = handler.createExecutableQuery(session, itemMgr, statement, language);
+        this.query = handler.createExecutableQuery(session, itemMgr, statement, language);
         setInitialized();
     }
 
     /**
-     * @inheritDoc
-     * <p/>
-     * Throws an {@link UnsupportedOperationException}.
-     */
-    public void init(SessionImpl session,
-                     ItemManager itemMgr,
-                     QueryHandler handler,
-                     QueryObjectModelTree qomTree,
-                     String language)
-            throws InvalidQueryException, RepositoryException {
-        throw new UnsupportedOperationException("not a prepared query");
-    }
-
-    /**
      * This method simply forwards the <code>execute</code> call to the
      * {@link ExecutableQuery} object returned by
      * {@link QueryHandler#createExecutableQuery}.
@@ -272,6 +221,9 @@
      * @param limit new maximum size of the result set
      */
     public void setLimit(long limit) {
+        if (limit < 0) {
+            throw new IllegalArgumentException("limit must not be negativ");
+        }
         this.limit = limit;
     }
 
@@ -281,6 +233,9 @@
      * @param offset new start offset of the result set
      */
     public void setOffset(long offset) {
+        if (offset < 0) {
+            throw new IllegalArgumentException("offset must not be negativ");
+        }
         this.offset = offset;
     }
 

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryManagerImpl.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryManagerImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryManagerImpl.java Wed Jul  8 13:57:13 2009
@@ -17,8 +17,9 @@
 package org.apache.jackrabbit.core.query;
 
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
+import java.util.ArrayList;
+import java.io.IOException;
 
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
@@ -31,9 +32,11 @@
 import org.apache.jackrabbit.core.ItemManager;
 import org.apache.jackrabbit.core.SearchManager;
 import org.apache.jackrabbit.core.SessionImpl;
-import org.apache.jackrabbit.spi.commons.query.QueryTreeBuilderRegistry;
+import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.spi.commons.query.qom.QueryObjectModelFactoryImpl;
 import org.apache.jackrabbit.spi.commons.query.qom.QueryObjectModelTree;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.uuid.UUID;
 
 /**
  * This class implements the {@link QueryManager} interface.
@@ -41,17 +44,6 @@
 public class QueryManagerImpl implements QueryManager {
 
     /**
-     * Defines all supported query languages
-     */
-    private static final String[] SUPPORTED_QUERIES = QueryTreeBuilderRegistry.getSupportedLanguages();
-
-    /**
-     * List of all supported query languages
-     */
-    private static final List SUPPORTED_QUERIES_LIST
-            = Collections.unmodifiableList(Arrays.asList(SUPPORTED_QUERIES));
-
-    /**
      * The <code>Session</code> for this QueryManager.
      */
     private final SessionImpl session;
@@ -75,14 +67,15 @@
      * Creates a new <code>QueryManagerImpl</code> for the passed
      * <code>session</code>
      *
-     * @param session
-     * @param itemMgr
-     * @param searchMgr
-     */
-    public QueryManagerImpl(
-            final SessionImpl session,
-            final ItemManager itemMgr,
-            final SearchManager searchMgr)
+     * @param session   the session for this query manager.
+     * @param itemMgr   the item manager of the session.
+     * @param searchMgr the search manager of this workspace.
+     * @throws RepositoryException if an error occurs while initializing the
+     *                             query manager.
+     */
+    public QueryManagerImpl(final SessionImpl session,
+                            final ItemManager itemMgr,
+                            final SearchManager searchMgr)
             throws RepositoryException {
         this.session = session;
         this.itemMgr = itemMgr;
@@ -92,7 +85,7 @@
             protected QueryObjectModel createQuery(QueryObjectModelTree qomTree)
                     throws InvalidQueryException, RepositoryException {
                 return searchMgr.createQueryObjectModel(
-                        session, qomTree, QueryImpl.JCR_SQL2);
+                        session, qomTree, Query.JCR_JQOM, null);
             }
         };
     }
@@ -103,7 +96,8 @@
     public Query createQuery(String statement, String language)
             throws InvalidQueryException, RepositoryException {
         sanityCheck();
-        return searchMgr.createQuery(session, itemMgr, statement, language);
+        QueryFactory qf = new QueryFactoryImpl(language);
+        return qf.createQuery(statement, language);
     }
 
     /**
@@ -112,14 +106,22 @@
     public Query getQuery(Node node)
             throws InvalidQueryException, RepositoryException {
         sanityCheck();
-        return searchMgr.createQuery(session, itemMgr, node);
+        if (!node.isNodeType(session.getJCRName(NameConstants.NT_QUERY))) {
+            throw new InvalidQueryException("node is not of type nt:query");
+        }
+        String statement = node.getProperty(session.getJCRName(NameConstants.JCR_STATEMENT)).getString();
+        String language = node.getProperty(session.getJCRName(NameConstants.JCR_LANGUAGE)).getString();
+
+        QueryFactory qf = new QueryFactoryImpl(node, language);
+        return qf.createQuery(statement, language);
     }
 
     /**
      * {@inheritDoc}
      */
     public String[] getSupportedQueryLanguages() throws RepositoryException {
-        return (String[]) SUPPORTED_QUERIES_LIST.toArray(new String[SUPPORTED_QUERIES.length]);
+        List<String> languages = new QueryFactoryImpl(Query.JCR_JQOM).getSupportedLanguages();
+        return languages.toArray(new String[languages.size()]);
     }
 
     //---------------------------< JSR 283 >------------------------------------
@@ -135,6 +137,31 @@
         return qomFactory;
     }
 
+    //-------------------------< Jackrabbit internal >--------------------------
+
+    /**
+     * Returns the ids of the nodes that refer to the <code>node</code> by weak
+     * references.
+     *
+     * @param node the target node.
+     * @return the referring nodes.
+     * @throws RepositoryException if an error occurs.
+     */
+    public Iterable<Node> getWeaklyReferringNodes(Node node)
+            throws RepositoryException {
+        sanityCheck();
+        List<Node> nodes = new ArrayList<Node>();
+        try {
+            NodeId nodeId = new NodeId(UUID.fromString(node.getIdentifier()));
+            for (NodeId id : searchMgr.getWeaklyReferringNodes(nodeId)) {
+                nodes.add(session.getNodeById(id));
+            }
+        } catch (IOException e) {
+            throw new RepositoryException(e);
+        }
+        return nodes;
+    }
+
     //------------------------< testing only >----------------------------------
 
     /**
@@ -158,4 +185,30 @@
             throw new RepositoryException("corresponding session has been closed");
         }
     }
+
+    private class QueryFactoryImpl extends CompoundQueryFactory {
+
+        public QueryFactoryImpl(String language) {
+            this(null, language);
+        }
+
+        public QueryFactoryImpl(final Node node, final String language) {
+            super(Arrays.asList(
+                new QOMQueryFactory(new QueryObjectModelFactoryImpl(
+                        session, session.getValueFactory()) {
+                    protected QueryObjectModel createQuery(QueryObjectModelTree qomTree)
+                            throws InvalidQueryException, RepositoryException {
+                        return searchMgr.createQueryObjectModel(
+                                session, qomTree, language, node);
+                    }
+                }, session.getValueFactory()),
+                new AQTQueryFactory() {
+                    public Query createQuery(String statement,
+                                             String language)
+                            throws InvalidQueryException, RepositoryException {
+                        return searchMgr.createQuery(session, itemMgr, statement, language, node);
+                    }
+                }));
+        }
+    }
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java Wed Jul  8 13:57:13 2009
@@ -27,11 +27,11 @@
 
 import org.apache.jackrabbit.core.ItemManager;
 import org.apache.jackrabbit.core.SessionImpl;
-import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.spi.commons.query.qom.QueryObjectModelTree;
+import org.apache.jackrabbit.spi.commons.query.QueryObjectModelBuilderRegistry;
 
 /**
- * <code>QueryObjectModelImpl</code>...
+ * <code>QueryObjectModelImpl</code> implements the query object model.
  */
 public class QueryObjectModelImpl extends QueryImpl implements QueryObjectModel {
 
@@ -41,65 +41,51 @@
     protected QueryObjectModelTree qomTree;
 
     /**
-     * @inheritDoc
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException always.
      */
     public void init(SessionImpl session,
                      ItemManager itemMgr,
                      QueryHandler handler,
                      String statement,
-                     String language) throws InvalidQueryException {
-        checkNotInitialized();
-        this.session = session;
-        this.language = language;
-        this.handler = handler;
-        this.statement = statement;
-        this.query = handler.createExecutableQuery(session, itemMgr,
-                createQOMTree(statement, language));
-        setInitialized();
-    }
-
-    /**
-     * @inheritDoc
-     */
-    public void init(SessionImpl session,
-                     ItemManager itemMgr,
-                     QueryHandler handler,
-                     Node node) throws InvalidQueryException, RepositoryException {
-        checkNotInitialized();
-        this.session = session;
-        this.node = node;
-        this.handler = handler;
-
-        if (!node.isNodeType(session.getJCRName(NameConstants.NT_QUERY))) {
-            throw new InvalidQueryException("node is not of type nt:query");
-        }
-        this.statement = node.getProperty(session.getJCRName(NameConstants.JCR_STATEMENT)).getString();
-        this.language = node.getProperty(session.getJCRName(NameConstants.JCR_LANGUAGE)).getString();
-        this.query = handler.createExecutableQuery(session, itemMgr,
-                createQOMTree(statement, language));
-        setInitialized();
+                     String language,
+                     Node node) throws InvalidQueryException {
+        throw new UnsupportedOperationException();
     }
 
     /**
-     * @inheritDoc
+     * Initializes a query instance from a query object model.
+     *
+     * @param session  the session of the user executing this query.
+     * @param itemMgr  the item manager of the session executing this query.
+     * @param handler  the query handler of the search index.
+     * @param qomTree  the query object model tree.
+     * @param language the original query syntax from where the JQOM was
+     *                 created.
+     * @param node     a nt:query node where the query was read from or
+     *                 <code>null</code> if it is not a stored query.
+     * @throws InvalidQueryException if the qom tree cannot be serialized
+     *                               according to the given language.
+     * @throws RepositoryException   if another error occurs
      */
     public void init(SessionImpl session,
                      ItemManager itemMgr,
                      QueryHandler handler,
                      QueryObjectModelTree qomTree,
-                     String language)
+                     String language,
+                     Node node)
             throws InvalidQueryException, RepositoryException {
         checkNotInitialized();
         this.session = session;
         this.language = language;
         this.handler = handler;
         this.qomTree = qomTree;
-        this.statement = null; // TODO: format qomTree into a SQL2 statement
+        this.node = node;
+        this.statement = QueryObjectModelBuilderRegistry.getQueryObjectModelBuilder(language).toString(this);
         this.query = handler.createExecutableQuery(session, itemMgr, qomTree);
         setInitialized();
     }
 
-
     //-------------------------< QueryObjectModel >-----------------------------
 
     /**
@@ -137,22 +123,4 @@
     public Column[] getColumns() {
         return qomTree.getColumns();
     }
-
-    //------------------------------< internal >--------------------------------
-
-    /**
-     * Creates a {@link QueryObjectModelTree} representation for the query
-     * <code>statement</code>.
-     *
-     * @param statement the query statement.
-     * @param language  the language of the query statement.
-     * @return the {@link QueryObjectModelTree} representation.
-     * @throws InvalidQueryException if the query statement is malformed.
-     */
-    private QueryObjectModelTree createQOMTree(String statement,
-                                               String language)
-            throws InvalidQueryException {
-        // TODO: implement
-        return null;
-    }
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractNamespaceMappings.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractNamespaceMappings.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractNamespaceMappings.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractNamespaceMappings.java Wed Jul  8 13:57:13 2009
@@ -32,7 +32,7 @@
         implements NamespaceMappings, NamespaceResolver {
 
     /**
-     * The name resolver used to translate the qualified name to JCR name
+     * The name resolver used to translate the <code>Name</code>s to JCR name strings.
      */
     private final NamePathResolver resolver;
 

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/AbstractQueryImpl.java Wed Jul  8 13:57:13 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&lt;Name>, where Name is a variable name in the query statement.
      */
-    private final Set variableNames = new HashSet();
+    private final Set<Name> variableNames = new HashSet<Name>();
 
     /**
      * Binding of variable name to value. Maps {@link Name} to {@link Value}.
      */
-    private final Map bindValues = new HashMap();
+    private final Map<Name, Value> bindValues = new HashMap<Name, Value>();
 
 
     /**
@@ -150,11 +152,20 @@
      * @return an unmodifieable map, which contains the variable names and their
      *         respective value.
      */
-    protected Map getBindVariableValues() {
+    protected Map<Name, Value> 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 <code>true</code> if this query node needs items under
      * /jcr:system to be queried.
      *

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ConsistencyCheck.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ConsistencyCheck.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ConsistencyCheck.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/ConsistencyCheck.java Wed Jul  8 13:57:13 2009
@@ -28,7 +28,6 @@
 
 import javax.jcr.RepositoryException;
 import java.io.IOException;
-import java.util.Iterator;
 import java.util.List;
 import java.util.ArrayList;
 import java.util.Set;
@@ -66,12 +65,13 @@
     /**
      * All the document UUIDs within the index.
      */
-    private Set documentUUIDs;
+    private Set<UUID> documentUUIDs;
 
     /**
      * List of all errors.
      */
-    private final List errors = new ArrayList();
+    private final List<ConsistencyCheckError> errors =
+        new ArrayList<ConsistencyCheckError>();
 
     /**
      * Private constructor.
@@ -109,8 +109,7 @@
             return;
         }
         int notRepairable = 0;
-        for (Iterator it = errors.iterator(); it.hasNext();) {
-            ConsistencyCheckError error = (ConsistencyCheckError) it.next();
+        for (ConsistencyCheckError error : errors) {
             try {
                 if (error.repairable()) {
                     error.repair();
@@ -139,8 +138,8 @@
      * Returns the errors detected by the consistency check.
      * @return the errors detected by the consistency check.
      */
-    List getErrors() {
-        return new ArrayList(errors);
+    List<ConsistencyCheckError> getErrors() {
+        return new ArrayList<ConsistencyCheckError>(errors);
     }
 
     /**
@@ -149,9 +148,9 @@
      */
     private void run() throws IOException {
         // UUIDs of multiple nodes in the index
-        Set multipleEntries = new HashSet();
+        Set<UUID> multipleEntries = new HashSet<UUID>();
         // collect all documents UUIDs
-        documentUUIDs = new HashSet();
+        documentUUIDs = new HashSet<UUID>();
         CachingMultiIndexReader reader = index.getIndexReader();
         try {
             for (int i = 0; i < reader.maxDoc(); i++) {
@@ -177,8 +176,8 @@
         }
 
         // create multiple entries errors
-        for (Iterator it = multipleEntries.iterator(); it.hasNext();) {
-            errors.add(new MultipleEntries((UUID) it.next()));
+        for (UUID uuid : multipleEntries) {
+            errors.add(new MultipleEntries(uuid));
         }
 
         reader = index.getIndexReader();
@@ -226,7 +225,7 @@
         // remember as fallback
         String uuid = node.getNodeId().toString();
         StringBuffer path = new StringBuffer();
-        List elements = new ArrayList();
+        List<ChildNodeEntry> elements = new ArrayList<ChildNodeEntry>();
         try {
             while (node.getParentId() != null) {
                 NodeId parentId = node.getParentId();

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DerefQuery.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DerefQuery.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DerefQuery.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DerefQuery.java Wed Jul  8 13:57:13 2009
@@ -114,7 +114,15 @@
      * @return 'DerefQuery'.
      */
     public String toString(String field) {
-        return "DerefQuery";
+        StringBuffer sb = new StringBuffer();
+        sb.append("DerefQuery(");
+        sb.append(refProperty);
+        sb.append(", ");
+        sb.append(contextQuery);
+        sb.append(", ");
+        sb.append(nameTest);
+        sb.append(")");
+        return sb.toString();
     }
 
     /**
@@ -291,6 +299,14 @@
             throw new UnsupportedOperationException();
         }
 
+        /**
+         * 1. do context query
+         * 2. go through each document from the query
+         * 3. find reference property UUIDs
+         * 4. Use UUIDs to find document number
+         * 5. Use the name test to filter the documents
+         * @throws IOException
+         */
         private void calculateChildren() throws IOException {
             if (uuids == null) {
                 uuids = new ArrayList();

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/FieldNames.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/FieldNames.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/FieldNames.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/FieldNames.java Wed Jul  8 13:57:13 2009
@@ -112,6 +112,11 @@
     public static final String SHAREABLE_NODE = "_:SHAREABLE_NODE".intern();
 
     /**
+     * Name of the field that contains all weak reference property values.
+     */
+    public static final String WEAK_REFS = "_:WEAK_REFS".intern();
+
+    /**
      * Returns a named length for use as a term in the index. The named length
      * is of the form: <code>propertyName</code> + '[' +
      * {@link LongField#longToString(long)}.

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/FilterMultiColumnQuery.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/FilterMultiColumnQuery.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/FilterMultiColumnQuery.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/FilterMultiColumnQuery.java Wed Jul  8 13:57:13 2009
@@ -20,7 +20,6 @@
 import java.util.Arrays;
 
 import org.apache.jackrabbit.core.query.lucene.constraint.Constraint;
-import org.apache.lucene.search.Sort;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -62,11 +61,11 @@
      * {@inheritDoc}
      */
     public MultiColumnQueryHits execute(final JackrabbitIndexSearcher searcher,
-                                        Sort sort,
+                                        Ordering[] orderings,
                                         long resultFetchHint)
             throws IOException {
-        return new FilterMultiColumnQueryHits(query.execute(
-                searcher, sort, resultFetchHint)) {
+        MultiColumnQueryHits hits = new FilterMultiColumnQueryHits(query.execute(
+                searcher, orderings, resultFetchHint)) {
 
             {
                 log.debug(Arrays.asList(getSelectorNames()).toString());
@@ -84,6 +83,20 @@
                 } 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();
+                }
+            }
         };
+        if (orderings.length > 0) {
+            hits = new SortedMultiColumnQueryHits(hits, orderings, searcher.getIndexReader());
+        }
+        return hits;
     }
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexMerger.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexMerger.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexMerger.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/IndexMerger.java Wed Jul  8 13:57:13 2009
@@ -18,9 +18,6 @@
 
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.IndexReader;
-import org.apache.commons.collections.Buffer;
-import org.apache.commons.collections.BufferUtils;
-import org.apache.commons.collections.buffer.UnboundedFifoBuffer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -28,15 +25,15 @@
 import java.util.Collections;
 import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Semaphore;
 import java.io.IOException;
 
-import EDU.oswego.cs.dl.util.concurrent.Sync;
-import EDU.oswego.cs.dl.util.concurrent.Mutex;
-
 /**
  * Merges indexes in a separate daemon thread.
  */
-class IndexMerger extends Thread implements IndexListener {
+class IndexMerger implements IndexListener {
 
     /**
      * Logger instance for this class.
@@ -66,18 +63,12 @@
     /**
      * Queue of merge Tasks
      */
-    private final Buffer mergeTasks = BufferUtils.blockingBuffer(new UnboundedFifoBuffer());
-
-    /**
-     * List of id <code>Term</code> that identify documents that were deleted
-     * while a merge was running.
-     */
-    private final List deletedDocuments = Collections.synchronizedList(new ArrayList());
+    private final BlockingQueue<Merge> mergeTasks = new LinkedBlockingQueue<Merge>();
 
     /**
      * List of <code>IndexBucket</code>s in ascending document limit.
      */
-    private final List indexBuckets = new ArrayList();
+    private final List<IndexBucket> indexBuckets = new ArrayList<IndexBucket>();
 
     /**
      * The <code>MultiIndex</code> this index merger is working on.
@@ -92,27 +83,40 @@
     /**
      * Mutex that is acquired when replacing indexes on MultiIndex.
      */
-    private final Sync indexReplacement = new Mutex();
+    private final Semaphore indexReplacement;
 
     /**
-     * When released, indicates that this index merger is idle.
+     * List of merger threads that are currently busy.
      */
-    private final Sync mergerIdle = new Mutex();
+    private final List<Worker> busyMergers = new ArrayList<Worker>();
+
+    /**
+     * List of merger threads.
+     */
+    private final List<Worker> workers = new ArrayList<Worker>();
 
     /**
      * Creates an <code>IndexMerger</code>.
      *
      * @param multiIndex the <code>MultiIndex</code>.
+     * @param numWorkers the number of worker threads to use.
      */
-    IndexMerger(MultiIndex multiIndex) {
+    IndexMerger(MultiIndex multiIndex, int numWorkers) {
         this.multiIndex = multiIndex;
-        setName("IndexMerger");
-        setDaemon(true);
-        try {
-            mergerIdle.acquire();
-        } catch (InterruptedException e) {
-            // will never happen, lock is free upon construction
-            throw new InternalError("Unable to acquire mutex after construction");
+        for (int i = 0; i < numWorkers; i++) {
+            Worker w = new Worker();
+            workers.add(w);
+            busyMergers.add(w);
+        }
+        this.indexReplacement = new Semaphore(workers.size());
+    }
+
+    /**
+     * Starts this index merger.
+     */
+    void start() {
+        for (Thread t : workers) {
+            t.start();
         }
     }
 
@@ -149,9 +153,9 @@
             }
 
             // put index in bucket
-            IndexBucket bucket = (IndexBucket) indexBuckets.get(indexBuckets.size() - 1);
-            for (int i = 0; i < indexBuckets.size(); i++) {
-                bucket = (IndexBucket) indexBuckets.get(i);
+            IndexBucket bucket = indexBuckets.get(indexBuckets.size() - 1);
+            for (IndexBucket indexBucket : indexBuckets) {
+                bucket = indexBucket;
                 if (bucket.fits(numDocs)) {
                     break;
                 }
@@ -172,20 +176,27 @@
                 long targetMergeDocs = bucket.upper;
                 targetMergeDocs = Math.min(targetMergeDocs * mergeFactor, maxMergeDocs);
                 // sum up docs in bucket
-                List indexesToMerge = new ArrayList();
+                List<Index> indexesToMerge = new ArrayList<Index>();
                 int mergeDocs = 0;
-                for (Iterator it = bucket.iterator(); it.hasNext() && mergeDocs <= targetMergeDocs;) {
+                for (Iterator<Index> it = bucket.iterator(); it.hasNext() && mergeDocs <= targetMergeDocs;) {
                     indexesToMerge.add(it.next());
                 }
                 if (indexesToMerge.size() > 2) {
                     // found merge
-                    Index[] idxs = (Index[]) indexesToMerge.toArray(new Index[indexesToMerge.size()]);
+                    Index[] idxs = indexesToMerge.toArray(new Index[indexesToMerge.size()]);
                     bucket.removeAll(indexesToMerge);
                     if (log.isDebugEnabled()) {
                         log.debug("requesting merge for " + indexesToMerge);
                     }
-                    mergeTasks.add(new Merge(idxs));
-                    log.debug("merge queue now contains " + mergeTasks.size() + " tasks.");
+                    addMergeTask(new Merge(idxs));
+                    if (log.isDebugEnabled()) {
+                        log.debug("merge queue now contains " + mergeTasks.size() + " tasks.");
+                        int numBusy;
+                        synchronized (busyMergers) {
+                            numBusy = busyMergers.size();
+                        }
+                        log.debug("# of busy merge workers: " + numBusy);
+                    }
                 }
             }
         }
@@ -196,18 +207,27 @@
      */
     public void documentDeleted(Term id) {
         log.debug("document deleted: " + id.text());
-        deletedDocuments.add(id);
+        synchronized (busyMergers) {
+            for (Worker w : busyMergers) {
+                w.documentDeleted(id);
+            }
+        }
     }
 
     /**
      * When the calling thread returns this index merger will be idle, that is
-     * there will be no merge tasks pending anymore. The method returns immediately
-     * if there are currently no tasks pending at all.
+     * there will be no merge tasks pending anymore. The method returns
+     * immediately if there are currently no tasks pending at all.
+     *
+     * @throws InterruptedException if this thread is interrupted while waiting
+     *                              for the worker threads to become idle.
      */
     void waitUntilIdle() throws InterruptedException {
-        mergerIdle.acquire();
-        // and immediately release again
-        mergerIdle.release();
+        synchronized (busyMergers) {
+            while (!busyMergers.isEmpty()) {
+                busyMergers.wait();
+            }
+        }
     }
 
     /**
@@ -216,135 +236,48 @@
      */
     void dispose() {
         log.debug("dispose IndexMerger");
-        // get mutex for index replacements
+        // get all permits for index replacements
         try {
-            indexReplacement.acquire();
+            indexReplacement.acquire(workers.size());
         } catch (InterruptedException e) {
-            log.warn("Interrupted while acquiring index replacement sync: " + e);
+            log.warn("Interrupted while acquiring index replacement permits: " + e);
             // try to stop IndexMerger without the sync
         }
 
+        log.debug("merge queue size: " + mergeTasks.size());
         // clear task queue
         mergeTasks.clear();
 
         // send quit
-        mergeTasks.add(QUIT);
+        addMergeTask(QUIT);
         log.debug("quit sent");
 
         try {
-            // give the merger thread some time to quit,
-            // it is possible that the merger is busy working on a large index.
+            // give the merger threads some time to quit,
+            // it is possible that the mergers are busy working on a large index.
             // if that is the case we will just ignore it and the daemon will
             // die without being able to finish the merge.
             // at this point it is not possible anymore to replace indexes
-            // on the MultiIndex because we hold the indexReplacement Sync.
-            this.join(500);
-            if (isAlive()) {
-                log.info("Unable to stop IndexMerger. Daemon is busy.");
-            } else {
-                log.debug("IndexMerger thread stopped");
-            }
-            log.debug("merge queue size: " + mergeTasks.size());
-        } catch (InterruptedException e) {
-            log.warn("Interrupted while waiting for IndexMerger thread to terminate.");
-        }
-    }
-
-    /**
-     * Implements the index merging.
-     */
-    public void run() {
-        for (;;) {
-            boolean isIdle = false;
-            if (mergeTasks.size() == 0) {
-                mergerIdle.release();
-                isIdle = true;
-            }
-            Merge task = (Merge) mergeTasks.remove();
-            if (task == QUIT) {
-                mergerIdle.release();
-                break;
-            }
-            if (isIdle) {
-                try {
-                    mergerIdle.acquire();
-                } catch (InterruptedException e) {
-                    Thread.interrupted();
-                    log.warn("Unable to acquire mergerIdle sync");
+            // on the MultiIndex because we hold all indexReplacement permits.
+            for (Thread t : workers) {
+                t.join(500);
+                if (t.isAlive()) {
+                    log.info("Unable to stop IndexMerger.Worker. Daemon is busy.");
+                } else {
+                    log.debug("IndexMerger.Worker thread stopped");
                 }
             }
-
-            log.debug("accepted merge request");
-
-            // reset deleted documents
-            deletedDocuments.clear();
-
-            // get readers
-            String[] names = new String[task.indexes.length];
-            for (int i = 0; i < task.indexes.length; i++) {
-                names[i] = task.indexes[i].name;
-            }
-            try {
-                log.debug("create new index");
-                PersistentIndex index = multiIndex.getOrCreateIndex(null);
-                boolean success = false;
-                try {
-
-                    log.debug("get index readers from MultiIndex");
-                    IndexReader[] readers = multiIndex.getIndexReaders(names, this);
-                    try {
-                        // do the merge
-                        long time = System.currentTimeMillis();
-                        index.addIndexes(readers);
-                        time = System.currentTimeMillis() - time;
-                        int docCount = 0;
-                        for (int i = 0; i < readers.length; i++) {
-                            docCount += readers[i].numDocs();
-                        }
-                        log.info("merged " + docCount + " documents in " + time + " ms into " + index.getName() + ".");
-                    } finally {
-                        for (int i = 0; i < readers.length; i++) {
-                            try {
-                                Util.closeOrRelease(readers[i]);
-                            } catch (IOException e) {
-                                log.warn("Unable to close IndexReader: " + e);
-                            }
-                        }
-                    }
-
-                    // inform multi index
-                    // if we cannot get the sync immediately we have to quit
-                    if (!indexReplacement.attempt(0)) {
-                        log.debug("index merging canceled");
-                        break;
-                    }
-                    try {
-                        log.debug("replace indexes");
-                        multiIndex.replaceIndexes(names, index, deletedDocuments);
-                    } finally {
-                        indexReplacement.release();
-                    }
-
-                    success = true;
-
-                } finally {
-                    if (!success) {
-                        // delete index
-                        log.debug("deleting index " + index.getName());
-                        multiIndex.deleteIndex(index);
-                    }
-                }
-            } catch (Throwable e) {
-                log.error("Error while merging indexes: ", e);
-            }
+        } catch (InterruptedException e) {
+            log.warn("Interrupted while waiting for IndexMerger threads to terminate.");
         }
-        log.info("IndexMerger terminated");
     }
 
     //-----------------------< merge properties >-------------------------------
 
     /**
      * The merge factor.
+     *
+     * @param mergeFactor the merge factor.
      */
     public void setMergeFactor(int mergeFactor) {
         this.mergeFactor = mergeFactor;
@@ -353,6 +286,8 @@
 
     /**
      * The initial threshold for number of documents to merge to a new index.
+     *
+     * @param minMergeDocs the min merge docs number.
      */
     public void setMinMergeDocs(int minMergeDocs) {
         this.minMergeDocs = minMergeDocs;
@@ -360,6 +295,8 @@
 
     /**
      * The maximum number of document to merge.
+     *
+     * @param maxMergeDocs the max merge docs number.
      */
     public void setMaxMergeDocs(int maxMergeDocs) {
         this.maxMergeDocs = maxMergeDocs;
@@ -367,6 +304,18 @@
 
     //------------------------------< internal >--------------------------------
 
+    private void addMergeTask(Merge task) {
+        for (;;) {
+            try {
+                mergeTasks.put(task);
+                break;
+            } catch (InterruptedException e) {
+                // try again
+                Thread.interrupted();
+            }
+        }
+    }
+
     /**
      * Implements a simple struct that holds the name of an index and how
      * many document it contains. <code>Index</code> is comparable using the
@@ -446,7 +395,9 @@
      * <code>IndexBucket</code> contains {@link Index}es with documents less
      * or equal the document limit of the bucket.
      */
-    private static final class IndexBucket extends ArrayList {
+    private static final class IndexBucket extends ArrayList<Index> {
+
+        private static final long serialVersionUID = 2985514550083374904L;
 
         /**
          * The lower document limit.
@@ -496,4 +447,130 @@
             return allowMerge;
         }
     }
+
+    private class Worker extends Thread implements IndexListener {
+
+        /**
+         * List of id <code>Term</code> that identify documents that were deleted
+         * while a merge was running.
+         */
+        private final List<Term> deletedDocuments = Collections.synchronizedList(new ArrayList<Term>());
+
+        public Worker() {
+            setName("IndexMerger.Worker");
+            setDaemon(true);
+        }
+
+        /**
+         * Implements the index merging.
+         */
+        public void run() {
+            for (;;) {
+                boolean isIdle = false;
+                if (mergeTasks.size() == 0) {
+                    synchronized (busyMergers) {
+                        busyMergers.remove(this);
+                        busyMergers.notifyAll();
+                    }
+                    isIdle = true;
+                }
+                Merge task;
+                for (;;) {
+                    try {
+                        task = mergeTasks.take();
+                        break;
+                    } catch (InterruptedException e) {
+                        // try again
+                        Thread.interrupted();
+                    }
+                }
+                if (task == QUIT) {
+                    synchronized (busyMergers) {
+                        busyMergers.remove(this);
+                    }
+                    // put back QUIT to signal other workers
+                    addMergeTask(task);
+                    break;
+                }
+                if (isIdle) {
+                    synchronized (busyMergers) {
+                        busyMergers.add(this);
+                    }
+                }
+
+                log.debug("accepted merge request");
+
+                // reset deleted documents
+                deletedDocuments.clear();
+
+                // get readers
+                String[] names = new String[task.indexes.length];
+                for (int i = 0; i < task.indexes.length; i++) {
+                    names[i] = task.indexes[i].name;
+                }
+                try {
+                    log.debug("create new index");
+                    PersistentIndex index = multiIndex.getOrCreateIndex(null);
+                    boolean success = false;
+                    try {
+
+                        log.debug("get index readers from MultiIndex");
+                        IndexReader[] readers = multiIndex.getIndexReaders(names, IndexMerger.this);
+                        try {
+                            // do the merge
+                            long time = System.currentTimeMillis();
+                            index.addIndexes(readers);
+                            time = System.currentTimeMillis() - time;
+                            int docCount = 0;
+                            for (IndexReader reader : readers) {
+                                docCount += reader.numDocs();
+                            }
+                            log.info("merged " + docCount + " documents in " + time + " ms into " + index.getName() + ".");
+                        } finally {
+                            for (IndexReader reader : readers) {
+                                try {
+                                    Util.closeOrRelease(reader);
+                                } catch (IOException e) {
+                                    log.warn("Unable to close IndexReader: " + e);
+                                }
+                            }
+                        }
+
+                        // inform multi index
+                        // if we cannot get the sync immediately we have to quit
+                        if (!indexReplacement.tryAcquire()) {
+                            log.debug("index merging canceled");
+                            break;
+                        }
+                        try {
+                            log.debug("replace indexes");
+                            multiIndex.replaceIndexes(names, index, deletedDocuments);
+                        } finally {
+                            indexReplacement.release();
+                        }
+
+                        success = true;
+
+                    } finally {
+                        if (!success) {
+                            // delete index
+                            log.debug("deleting index " + index.getName());
+                            multiIndex.deleteIndex(index);
+                        }
+                    }
+                } catch (Throwable e) {
+                    log.error("Error while merging indexes: ", e);
+                }
+            }
+            log.info("IndexMerger.Worker terminated");
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public void documentDeleted(Term id) {
+            log.debug("document deleted: " + id.text());
+            deletedDocuments.add(id);
+        }
+    }
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitIndexSearcher.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitIndexSearcher.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitIndexSearcher.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitIndexSearcher.java Wed Jul  8 13:57:13 2009
@@ -102,7 +102,7 @@
             hits = ((JackrabbitQuery) query).execute(this, session, sort);
         }
         if (hits == null) {
-            if (sort == null) {
+            if (sort.getSort().length == 0) {
                 hits = new LuceneQueryHits(reader, this, query);
             } else {
                 hits = new SortedLuceneQueryHits(

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitTextExtractor.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitTextExtractor.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitTextExtractor.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JackrabbitTextExtractor.java Wed Jul  8 13:57:13 2009
@@ -19,15 +19,11 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.Reader;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.Set;
 import java.util.StringTokenizer;
 
-import org.apache.jackrabbit.core.query.TextFilter;
 import org.apache.jackrabbit.extractor.CompositeTextExtractor;
 import org.apache.jackrabbit.extractor.DelegatingTextExtractor;
 import org.apache.jackrabbit.extractor.EmptyTextExtractor;
@@ -40,8 +36,8 @@
  * implements the following functionality:
  * <ul>
  *   <li>
- *     Parses the configured {@link TextExtractor} and {@link TextFilter}
- *     class names and instantiates the configured classes.
+ *     Parses the configured {@link TextExtractor} class names and
+ *     instantiates the configured classes.
  *   </li>
  *   <li>
  *     Acts as the delegate extractor for any configured
@@ -77,10 +73,10 @@
      * Set of content types that are known to be supported by the
      * composite extractor.
      */
-    private final Set types = new HashSet();
+    private final Set<String> types = new HashSet<String>();
 
     /**
-     * Composite extractor used to for all text extration tasks. Contains
+     * Composite extractor used to for all text extraction tasks. Contains
      * all the {@link TextExtractor} instances for directly supported content
      * types, the {@link TextFilterExtractor} adapters for backwards
      * compatibility with configured {@link TextFilter} instances that have
@@ -91,13 +87,6 @@
         new CompositeTextExtractor();
 
     /**
-     * Configured {@link TextFilter} instances. Used for backwards
-     * compatibility with existing configuration files and {@link TextFilter}
-     * implementations.
-     */
-    private final Collection filters = new ArrayList();
-
-    /**
      * Creates a Jackrabbit text extractor containing the configured component
      * classes.
      *
@@ -117,8 +106,6 @@
                 }
                 if (object instanceof TextExtractor) {
                     extractor.addTextExtractor((TextExtractor) object);
-                } else if (object instanceof TextFilter) {
-                    filters.add(object);
                 } else {
                     logger.warn("Unknown text extractor class: {}", name);
                 }
@@ -173,18 +160,6 @@
     public Reader extractText(InputStream stream, String type, String encoding)
             throws IOException {
         logger.debug("extractText(stream, {}, {})", type, encoding);
-        if (!types.contains(type)) {
-            Iterator iterator = filters.iterator();
-            while (iterator.hasNext()) {
-                TextFilter filter = (TextFilter) iterator.next();
-                if (filter.canFilter(type)) {
-                    types.add(type);
-                    extractor.addTextExtractor(
-                            new TextFilterExtractor(type, filter));
-                    break;
-                }
-            }
-        }
 
         if (!types.contains(type)) {
             logger.debug("Full text indexing of {} is not supported", type);

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JoinQuery.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JoinQuery.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JoinQuery.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/JoinQuery.java Wed Jul  8 13:57:13 2009
@@ -18,7 +18,6 @@
 
 import java.io.IOException;
 
-import org.apache.lucene.search.Sort;
 import org.apache.lucene.search.SortComparatorSource;
 import org.apache.lucene.index.IndexReader;
 import org.apache.jackrabbit.core.query.lucene.join.Join;
@@ -89,13 +88,13 @@
      * {@inheritDoc}
      */
     public MultiColumnQueryHits execute(JackrabbitIndexSearcher searcher,
-                                        Sort sort,
+                                        Ordering[] orderings,
                                         long resultFetchHint)
             throws IOException {
         IndexReader reader = searcher.getIndexReader();
         HierarchyResolver resolver = (HierarchyResolver) reader;
-        return Join.create(left.execute(searcher, sort, resultFetchHint),
-                right.execute(searcher, sort, resultFetchHint),
+        return Join.create(left.execute(searcher, orderings, resultFetchHint),
+                right.execute(searcher, orderings, resultFetchHint),
                 joinType, joinCondition, reader, resolver, scs, hmgr);
     }
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/LuceneQueryBuilder.java Wed Jul  8 13:57:13 2009
@@ -41,11 +41,11 @@
 import org.apache.jackrabbit.core.state.ItemStateManager;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
-import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
+import org.apache.jackrabbit.spi.PathFactory;
 import org.apache.jackrabbit.spi.commons.conversion.NameException;
 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.apache.jackrabbit.spi.commons.name.PathBuilder;
+import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
 import org.apache.jackrabbit.spi.commons.query.AndQueryNode;
 import org.apache.jackrabbit.spi.commons.query.DefaultQueryNodeVisitor;
 import org.apache.jackrabbit.spi.commons.query.DerefQueryNode;
@@ -68,11 +68,11 @@
 import org.apache.jackrabbit.util.XMLChar;
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.index.Term;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.QueryParser;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.BooleanClause.Occur;
-import org.apache.lucene.queryParser.QueryParser;
-import org.apache.lucene.queryParser.ParseException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -90,6 +90,16 @@
     private static final Logger log = LoggerFactory.getLogger(LuceneQueryBuilder.class);
 
     /**
+     * The path factory instance.
+     */
+    private static final PathFactory PATH_FACTORY = PathFactoryImpl.getInstance();
+
+    /**
+     * The name of a parent path element.
+     */
+    private static final Name PARENT_ELEMENT_NAME = PATH_FACTORY.getParentElement().getName();
+
+    /**
      * Root node of the abstract query tree
      */
     private final QueryRootNode root;
@@ -494,6 +504,10 @@
 
         NameQuery nameTest = null;
         if (node.getNameTest() != null) {
+            if (node.getNameTest().equals(PARENT_ELEMENT_NAME)) {
+                andQuery.add(new ParentAxisQuery(context, null, indexFormatVersion, nsMappings), Occur.MUST);
+                return andQuery;
+            }
             nameTest = new NameQuery(node.getNameTest(), indexFormatVersion, nsMappings);
         }
 
@@ -587,6 +601,16 @@
     }
 
     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 = steps[steps.length - 1].getNameTest();
+        
         Query query;
         String[] stringValues = new String[1];
         switch (node.getValueType()) {
@@ -608,7 +632,6 @@
                         || node.getOperation() == QueryConstants.OPERATION_NE_GENERAL
                         || node.getOperation() == QueryConstants.OPERATION_NE_VALUE) {
                     // only use coercing on non-range operations
-                    Name propertyName = node.getRelativePath().getNameElement().getName();
                     stringValues = getStringValues(propertyName, node.getStringValue());
                 } else {
                     stringValues[0] = node.getStringValue();
@@ -622,13 +645,6 @@
                         + node.getValueType());
         }
 
-        if (node.getRelativePath() == null
-                && node.getOperation() != QueryConstants.OPERATION_SIMILAR
-                && node.getOperation() != QueryConstants.OPERATION_SPELLCHECK) {
-            exceptions.add(new InvalidQueryException("@* not supported in predicate"));
-            return data;
-        }
-
         // get property transformation
         final int[] transform = new int[]{TransformConstants.TRANSFORM_NONE};
         node.acceptOperands(new DefaultQueryNodeVisitor() {
@@ -642,37 +658,24 @@
             }
         }, null);
 
-        Path relPath = node.getRelativePath();
         if (node.getOperation() == QueryConstants.OPERATION_SIMILAR) {
             // this is a bit ugly:
-            // add the name of a dummy property because relPath actually
+            // use the name of a dummy property because relPath actually
             // references a property. whereas the relPath of the similar
             // operation references a node
-            PathBuilder builder;
-            if (relPath == null) {
-                builder = new PathBuilder();
-            } else {
-                builder = new PathBuilder(relPath);
-            }
-            builder.addLast(NameConstants.JCR_PRIMARYTYPE);
-            try {
-                relPath = builder.getPath();
-            } catch (MalformedPathException e) {
-                // will never happen
-            }
+            propertyName = NameConstants.JCR_PRIMARYTYPE;
         }
         String field = "";
         try {
-            field = resolver.getJCRName(relPath.getNameElement().getName());
+            field = resolver.getJCRName(propertyName);
         } catch (NamespaceException e) {
             // should never happen
             exceptions.add(e);
         }
 
         // support for fn:name()
-        Name propName = relPath.getNameElement().getName();
-        if (propName.getNamespaceURI().equals(SearchManager.NS_FN_URI)
-                && propName.getLocalName().equals("name()")) {
+        if (propertyName.getNamespaceURI().equals(SearchManager.NS_FN_URI)
+                && propertyName.getLocalName().equals("name()")) {
             if (node.getValueType() != QueryConstants.TYPE_STRING) {
                 exceptions.add(new InvalidQueryException("Name function can "
                         + "only be used in conjunction with a string literal"));
@@ -864,40 +867,114 @@
             }
         }
 
-        if (relPath.getLength() > 1) {
+        if (steps.length > 1) {
             // child axis in relation
-            Path.Element[] 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--) {
+            boolean selectParent = true; 
+            for (int i = steps.length - 2; i >= 0; i--) {
+                LocationStepQueryNode step = steps[i];
                 Name name = null;
-                if (!elements[i].getName().equals(RelationQueryNode.STAR_NAME_TEST)) {
-                    name = elements[i].getName();
+                if (!RelationQueryNode.STAR_NAME_TEST.equals(steps[i].getNameTest())) {
+                    name = steps[i].getNameTest();
                 }
-                if (i == elements.length - 2) {
-                    // join name test with property query if there is one
-                    if (name != null) {
-                        Query nameTest = new NameQuery(name,
-                                indexFormatVersion, nsMappings);
-                        BooleanQuery and = new BooleanQuery();
-                        and.add(query, Occur.MUST);
-                        and.add(nameTest, Occur.MUST);
-                        query = and;
-                    } else {
-                        // otherwise the query can be used as is
+                if (i == steps.length - 2) {
+                    if (step instanceof DerefQueryNode) {
+                        query = createPredicateDeref(query, (DerefQueryNode) step, data);
+                        if (steps.length == 2) {
+                            selectParent = false;
+                        }
+                    } else if (step instanceof LocationStepQueryNode) {
+                        // 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 {
-                    query = new ParentAxisQuery(query, name,
-                            indexFormatVersion, nsMappings);
+                    if (step instanceof LocationStepQueryNode) {
+                        query = new ParentAxisQuery(query, name, indexFormatVersion, nsMappings);
+                    } else {
+                        throw new UnsupportedOperationException();
+                    }
                 }
             }
             // finally select the parent of the selected nodes
-            query = new ParentAxisQuery(query, null,
-                    indexFormatVersion, nsMappings);
+            if (selectParent) {
+                query = new ParentAxisQuery(query, null, indexFormatVersion, nsMappings);
+            }
         }
 
         return query;
     }
+    
+    public Query createPredicateDeref(Query subQuery, DerefQueryNode node, Object data) throws RepositoryException {
+        Query context = (Query) data;
+        
+        if (context == null) {
+            exceptions.add(new IllegalArgumentException("Unsupported query"));
+        }
+
+        try {
+            String refProperty = resolver.getJCRName(node.getRefProperty());
+
+            context = new PredicateDerefQuery(subQuery, refProperty, node.getNameTest(),
+                    indexFormatVersion, nsMappings);
+
+            // attach predicates
+            Object[] predicates = node.acceptOperands(this, data);
+            if (predicates.length > 0) {
+                BooleanQuery andQuery = new BooleanQuery();
+                for (int i = 0; i < predicates.length; i++) {
+                    andQuery.add((Query) predicates[i], Occur.MUST);
+                }
+                andQuery.add(context, Occur.MUST);
+                context = andQuery;
+            }
+            
+        } catch (NamespaceException e) {
+            // should never happen
+            exceptions.add(e);
+        }
+
+        return context;
+    }
 
     public Object visit(OrderQueryNode node, Object data) {
         return data;
@@ -1004,6 +1081,18 @@
                         log.debug("Unable to coerce '" + literal + "' into a LONG: " + e.toString());
                     }
                     break;
+                case PropertyType.DECIMAL:
+                    // try to parse decimal
+                    try {
+                        BigDecimal d = new BigDecimal(literal);
+                        values.add(DecimalField.decimalToString(d));
+                        log.debug("Coerced " + literal + " into DECIMAL.");
+                    } catch (NumberFormatException e) {
+                        log.debug("Unable to coerce '" + literal + "' into a DECIMAL: " + e.toString());
+                    }
+                    break;
+                case PropertyType.URI:
+                    // fall through... TODO: correct?
                 case PropertyType.STRING:
                     values.add(literal);
                     log.debug("Using literal " + literal + " as is.");

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiColumnQuery.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiColumnQuery.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiColumnQuery.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiColumnQuery.java Wed Jul  8 13:57:13 2009
@@ -18,8 +18,6 @@
 
 import java.io.IOException;
 
-import org.apache.lucene.search.Sort;
-
 /**
  * <code>MultiColumnQuery</code> defines an interface for a query that returns
  * {@link MultiColumnQueryHits}.
@@ -30,13 +28,13 @@
      * Executes this query and returns multi column query hits.
      *
      * @param searcher        the index searcher.
-     * @param sort            the sort criteria.
+     * @param orderings       the orderings.
      * @param resultFetchHint the result fetch hint.
      * @return the query hits.
      * @throws IOException if an error occurs while executing the query.
      */
     public MultiColumnQueryHits execute(JackrabbitIndexSearcher searcher,
-                                        Sort sort,
+                                        Ordering[] orderings,
                                         long resultFetchHint)
             throws IOException;
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiColumnQueryAdapter.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiColumnQueryAdapter.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiColumnQueryAdapter.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiColumnQueryAdapter.java Wed Jul  8 13:57:13 2009
@@ -19,6 +19,7 @@
 import java.io.IOException;
 
 import org.apache.lucene.search.Query;
+import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.Sort;
 import org.apache.jackrabbit.spi.Name;
 
@@ -64,9 +65,13 @@
      * {@inheritDoc}
      */
     public MultiColumnQueryHits execute(JackrabbitIndexSearcher searcher,
-                                        Sort sort,
+                                        Ordering[] orderings,
                                         long resultFetchHint)
             throws IOException {
-        return searcher.execute(query, sort, resultFetchHint, selectorName);
+        SortField[] fields = new SortField[orderings.length];
+        for (int i = 0; i < orderings.length; i++) {
+            fields[i] = orderings[i].getSortField();
+        }
+        return searcher.execute(query, new Sort(fields), resultFetchHint, selectorName);
     }
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiColumnQueryResult.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiColumnQueryResult.java?rev=792142&r1=792141&r2=792142&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiColumnQueryResult.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/MultiColumnQueryResult.java Wed Jul  8 13:57:13 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.Name;
-import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.commons.query.qom.ColumnImpl;
+import org.apache.jackrabbit.spi.commons.query.qom.OrderingImpl;
 
 /**
  * <code>MultiColumnQueryResult</code> 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 Ordering[] orderings;
+
     public MultiColumnQueryResult(SearchIndex index,
                                   ItemManager itemMgr,
                                   SessionImpl session,
@@ -44,15 +49,15 @@
                                   AbstractQueryImpl queryImpl,
                                   MultiColumnQuery query,
                                   SpellSuggestion spellSuggestion,
-                                  Name[] selectProps,
-                                  Path[] orderProps,
-                                  boolean[] orderSpecs,
+                                  ColumnImpl[] columns,
+                                  OrderingImpl[] orderings,
                                   boolean documentOrder,
                                   long offset,
                                   long limit) throws RepositoryException {
         super(index, itemMgr, session, accessMgr, queryImpl, spellSuggestion,
-                selectProps, orderProps, orderSpecs, documentOrder, offset, limit);
+                columns, documentOrder, offset, limit);
         this.query = query;
+        this.orderings = index.createOrderings(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);
     }
 
     /**



Mime
View raw message