jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mreut...@apache.org
Subject svn commit: r480917 - in /jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene: LazyQueryResultImpl.java QueryImpl.java QueryResultImpl.java
Date Thu, 30 Nov 2006 13:33:35 GMT
Author: mreutegg
Date: Thu Nov 30 05:33:34 2006
New Revision: 480917

URL: http://svn.apache.org/viewvc?view=rev&rev=480917
Log:
JCR-651: Improve performance for queries with large result sets
- reverted changes on QueryResultImpl to provide a backward compatible constructor
- the newly introduces lazy access right check is now implemented in LazyQueryResultImpl.

Added:
    jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/LazyQueryResultImpl.java
  (with props)
Modified:
    jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java
    jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java

Added: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/LazyQueryResultImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/LazyQueryResultImpl.java?view=auto&rev=480917
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/LazyQueryResultImpl.java
(added)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/LazyQueryResultImpl.java
Thu Nov 30 05:33:34 2006
@@ -0,0 +1,441 @@
+/*
+ * 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 org.apache.jackrabbit.core.ItemManager;
+import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.NodeImpl;
+import org.apache.jackrabbit.core.security.AccessManager;
+import org.apache.jackrabbit.name.NamespaceResolver;
+import org.apache.jackrabbit.name.NoPrefixDeclaredException;
+import org.apache.jackrabbit.name.QName;
+import org.apache.jackrabbit.name.NameFormat;
+import org.apache.lucene.search.Query;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.Node;
+import javax.jcr.query.QueryResult;
+import javax.jcr.query.RowIterator;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * Implements the <code>javax.jcr.query.QueryResult</code> interface.
+ */
+public class LazyQueryResultImpl implements QueryResult {
+
+    /**
+     * The logger instance for this class
+     */
+    private static final Logger log = LoggerFactory.getLogger(QueryResultImpl.class);
+
+    /**
+     * The search index to execute the query.
+     */
+    private final SearchIndex index;
+
+    /**
+     * The item manager of the session executing the query
+     */
+    private final ItemManager itemMgr;
+
+    /**
+     * The namespace resolver of the session executing the query
+     */
+    protected final NamespaceResolver resolver;
+
+    /**
+     * The access manager of the session that executes the query.
+     */
+    private final AccessManager accessMgr;
+
+    /**
+     * The query instance which created this query result.
+     */
+    protected final QueryImpl queryImpl;
+
+    /**
+     * The lucene query to execute.
+     */
+    protected final Query query;
+
+    /**
+     * The select properties
+     */
+    protected final QName[] selectProps;
+
+    /**
+     * The names of properties to use for ordering the result set.
+     */
+    protected final QName[] 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.
+     */
+    private final List resultNodes = new ArrayList();
+
+    /**
+     * This is the raw number of results that matched the query. This number
+     * also includes matches which will not be returned due to access
+     * restrictions. This value is set when the query is executed the first
+     * time.
+     */
+    private int numResults = -1;
+
+    /**
+     * The number of results that are invalid, either because a node does not
+     * exist anymore or because the session does not have access to the node.
+     */
+    private int invalid = 0;
+
+    /**
+     * If <code>true</code> nodes are returned in document order.
+     */
+    private final boolean docOrder;
+
+    /**
+     * Creates a new query result.
+     *
+     * @param index         the search index where the query is executed.
+     * @param itemMgr       the item manager of the session executing the
+     *                      query.
+     * @param resolver      the namespace resolver of the session executing the
+     *                      query.
+     * @param accessMgr     the access manager of the session executiong the
+     *                      query.
+     * @param queryImpl     the query instance which created this query result.
+     * @param query         the lucene query to execute on the index.
+     * @param selectProps   the select properties of the query.
+     * @param orderProps    the names of the order properties.
+     * @param orderSpecs    the order specs, one for each order property name.
+     * @param documentOrder if <code>true</code> the result is returned in
+     *                      document order.
+     */
+    public LazyQueryResultImpl(SearchIndex index,
+                           ItemManager itemMgr,
+                           NamespaceResolver resolver,
+                           AccessManager accessMgr,
+                           QueryImpl queryImpl,
+                           Query query,
+                           QName[] selectProps,
+                           QName[] orderProps,
+                           boolean[] orderSpecs,
+                           boolean documentOrder) throws RepositoryException {
+        this.index = index;
+        this.itemMgr = itemMgr;
+        this.resolver = resolver;
+        this.accessMgr = accessMgr;
+        this.queryImpl = queryImpl;
+        this.query = query;
+        this.selectProps = selectProps;
+        this.orderProps = orderProps;
+        this.orderSpecs = orderSpecs;
+        this.docOrder = orderProps.length == 0 && documentOrder;
+        // if document order is requested get all results right away
+        getResults(docOrder ? Integer.MAX_VALUE : index.getResultFetchSize());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String[] getColumnNames() throws RepositoryException {
+        try {
+            String[] propNames = new String[selectProps.length];
+            for (int i = 0; i < selectProps.length; i++) {
+                propNames[i] = NameFormat.format(selectProps[i], resolver);
+            }
+            return propNames;
+        } catch (NoPrefixDeclaredException npde) {
+            String msg = "encountered invalid property name";
+            log.debug(msg);
+            throw new RepositoryException(msg, npde);
+
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public NodeIterator getNodes() throws RepositoryException {
+        return getNodeIterator();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public RowIterator getRows() throws RepositoryException {
+        return new RowIteratorImpl(getNodeIterator(), selectProps, resolver);
+    }
+
+    /**
+     * Executes the query for this result and returns hits. The caller must
+     * close the query hits when he is done using it.
+     *
+     * @return hits for this query result.
+     * @throws IOException if an error occurs while executing the query.
+     */
+    protected QueryHits executeQuery() throws IOException {
+        return index.executeQuery(queryImpl, query, orderProps, orderSpecs);
+    }
+
+    //--------------------------------< internal >------------------------------
+
+    /**
+     * Creates a node iterator over the result nodes.
+     *
+     * @return a node iterator over the result nodes.
+     */
+    private ScoreNodeIterator getNodeIterator() {
+        if (docOrder) {
+            return new DocOrderNodeIteratorImpl(itemMgr, resultNodes);
+        } else {
+            return new LazyScoreNodeIterator();
+        }
+    }
+
+    /**
+     * Attempts to get <code>size</code> results and puts them into {@link
+     * #resultNodes}. If the size of {@link #resultNodes} is less than
+     * <code>size</code> then there are no more than <code>resultNodes.size()</code>
+     * results for this query.
+     *
+     * @param size the number of results to fetch for the query.
+     * @throws RepositoryException if an error occurs while executing the
+     *                             query.
+     */
+    private void getResults(int size) throws RepositoryException {
+        if (log.isDebugEnabled()) {
+            log.debug("getResults(" + size + ")");
+        }
+        if (resultNodes.size() >= size) {
+            // we already have them all
+            return;
+        }
+
+        // execute it
+        QueryHits result = null;
+        try {
+            result = executeQuery();
+
+            // set num results with the first query execution
+            if (numResults == -1) {
+                numResults = result.length();
+            }
+
+            int start = resultNodes.size() + invalid;
+            int max = Math.min(result.length(), numResults);
+            for (int i = start; i < max && resultNodes.size() < size; i++)
{
+                NodeId id = NodeId.valueOf(result.doc(i).get(FieldNames.UUID));
+                // check access
+                try {
+                    if (accessMgr.isGranted(id, AccessManager.READ)) {
+                        resultNodes.add(new ScoreNode(id, result.score(i)));
+                    }
+                } catch (ItemNotFoundException e) {
+                    // has been deleted meanwhile
+                    invalid++;
+                }
+            }
+        } catch (IOException e) {
+            log.error("Exception while executing query: ", e);
+            // todo throw?
+        } finally {
+            if (result != null) {
+                try {
+                    result.close();
+                } catch (IOException e) {
+                    log.warn("Unable to close query result: " + e);
+                }
+            }
+        }
+    }
+
+    private final class LazyScoreNodeIterator implements ScoreNodeIterator {
+
+        private int position = -1;
+
+        private boolean initialized = false;
+
+        private NodeImpl next;
+
+        /**
+         * {@inheritDoc}
+         */
+        public float getScore() {
+            initialize();
+            if (!hasNext()) {
+                throw new NoSuchElementException();
+            }
+            return ((ScoreNode) resultNodes.get(position)).getScore();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public NodeImpl nextNodeImpl() {
+            initialize();
+            if (next == null) {
+                throw new NoSuchElementException();
+            }
+            NodeImpl n = next;
+            fetchNext();
+            return n;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Node nextNode() {
+            return nextNodeImpl();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public void skip(long skipNum) {
+            initialize();
+            if (skipNum < 0) {
+                throw new IllegalArgumentException("skipNum must not be negative");
+            }
+            if ((position + invalid + skipNum) > numResults) {
+                throw new NoSuchElementException();
+            }
+            if (skipNum == 0) {
+                // do nothing
+            } else {
+                // attempt to get enough results
+                try {
+                    getResults(position + invalid + (int) skipNum);
+                    if (resultNodes.size() >= position + skipNum) {
+                        // skip within already fetched results
+                        position += skipNum - 1;
+                        fetchNext();
+                    } else {
+                        // not enough results after getResults()
+                        throw new NoSuchElementException();
+                    }
+                } catch (RepositoryException e) {
+                    throw new NoSuchElementException(e.getMessage());
+                }
+            }
+        }
+
+        /**
+         * {@inheritDoc}
+         * <p/>
+         * This value may shrink when the query result encounters non-existing
+         * nodes or the session does not have access to a node.
+         */
+        public long getSize() {
+            return numResults - invalid;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public long getPosition() {
+            initialize();
+            return position;
+        }
+
+        /**
+         * @throws UnsupportedOperationException always.
+         */
+        public void remove() {
+            throw new UnsupportedOperationException("remove");
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public boolean hasNext() {
+            initialize();
+            return next != null;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Object next() {
+            return nextNodeImpl();
+        }
+
+        /**
+         * Initializes this iterator but only if it is not yet initialized.
+         */
+        private void initialize() {
+            if (!initialized) {
+                fetchNext();
+                initialized = true;
+            }
+        }
+
+        /**
+         * Fetches the next node to return by this iterator. If this method
+         * returns and {@link #next} is <code>null</code> then there is no next
+         * node.
+         */
+        private void fetchNext() {
+            next = null;
+            int nextPos = position + 1;
+            while (next == null && (nextPos + invalid) < numResults) {
+                if (nextPos >= resultNodes.size()) {
+                    // fetch more results
+                    try {
+                        int num;
+                        if (resultNodes.size() == 0) {
+                            num = index.getResultFetchSize();
+                        } else {
+                            num = resultNodes.size() * 2;
+                        }
+                        getResults(num);
+                    } catch (RepositoryException e) {
+                        log.warn("Exception getting more results: " + e);
+                    }
+                    // check again
+                    if (nextPos >= resultNodes.size()) {
+                        // no more valid results
+                        return;
+                    }
+                }
+                ScoreNode sn = (ScoreNode) resultNodes.get(nextPos);
+                try {
+                    next = (NodeImpl) itemMgr.getItem(sn.getNodeId());
+                } catch (RepositoryException e) {
+                    log.warn("Exception retrieving Node with UUID: "
+                            + sn.getNodeId() + ": " + e.toString());
+                    // remove score node and try next
+                    resultNodes.remove(nextPos);
+                    invalid++;
+                }
+            }
+            position++;
+        }
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/LazyQueryResultImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java?view=diff&rev=480917&r1=480916&r2=480917
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java
(original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java
Thu Nov 30 05:33:34 2006
@@ -160,7 +160,7 @@
             ascSpecs[i] = orderSpecs[i].isAscending();
         }
 
-        return new QueryResultImpl(index, itemMgr, session.getNamespaceResolver(),
+        return new LazyQueryResultImpl(index, itemMgr, session.getNamespaceResolver(),
                 session.getAccessManager(), this, query, getSelectProperties(),
                 orderProperties, ascSpecs, documentOrder);
     }

Modified: jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java?view=diff&rev=480917&r1=480916&r2=480917
==============================================================================
--- jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java
(original)
+++ jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java
Thu Nov 30 05:33:34 2006
@@ -18,26 +18,18 @@
 
 import org.apache.jackrabbit.core.ItemManager;
 import org.apache.jackrabbit.core.NodeId;
-import org.apache.jackrabbit.core.NodeImpl;
-import org.apache.jackrabbit.core.security.AccessManager;
 import org.apache.jackrabbit.name.NamespaceResolver;
 import org.apache.jackrabbit.name.NoPrefixDeclaredException;
 import org.apache.jackrabbit.name.QName;
 import org.apache.jackrabbit.name.NameFormat;
-import org.apache.lucene.search.Query;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import javax.jcr.NodeIterator;
 import javax.jcr.RepositoryException;
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.Node;
 import javax.jcr.query.QueryResult;
 import javax.jcr.query.RowIterator;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.NoSuchElementException;
+import java.util.Arrays;
 
 /**
  * Implements the <code>javax.jcr.query.QueryResult</code> interface.
@@ -50,69 +42,24 @@
     private static final Logger log = LoggerFactory.getLogger(QueryResultImpl.class);
 
     /**
-     * The search index to execute the query.
-     */
-    private final SearchIndex index;
-
-    /**
      * The item manager of the session executing the query
      */
     private final ItemManager itemMgr;
 
     /**
-     * The namespace resolver of the session executing the query
-     */
-    protected final NamespaceResolver resolver;
-
-    /**
-     * The access manager of the session that executes the query.
-     */
-    private final AccessManager accessMgr;
-
-    /**
-     * The query instance which created this query result.
-     */
-    protected final QueryImpl queryImpl;
-
-    /**
-     * The lucene query to execute.
+     * The result nodes and their scores
      */
-    protected final Query query;
+    private final ScoreNode[] scoreNodes;
 
     /**
      * The select properties
      */
-    protected final QName[] selectProps;
-
-    /**
-     * The names of properties to use for ordering the result set.
-     */
-    protected final QName[] 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.
-     */
-    private final List resultNodes = new ArrayList();
+    private final QName[] selectProps;
 
     /**
-     * This is the raw number of results that matched the query. This number
-     * also includes matches which will not be returned due to access
-     * restrictions. This value is set when the query is executed the first
-     * time.
-     */
-    private int numResults = -1;
-
-    /**
-     * The number of results that are invalid, either because a node does not
-     * exist anymore or because the session does not have access to the node.
+     * The namespace resolver of the session executing the query
      */
-    private int invalid = 0;
+    private final NamespaceResolver resolver;
 
     /**
      * If <code>true</code> nodes are returned in document order.
@@ -122,43 +69,28 @@
     /**
      * Creates a new query result.
      *
-     * @param index         the search index where the query is executed.
-     * @param itemMgr       the item manager of the session executing the
-     *                      query.
-     * @param resolver      the namespace resolver of the session executing the
-     *                      query.
-     * @param accessMgr     the access manager of the session executiong the
-     *                      query.
-     * @param queryImpl     the query instance which created this query result.
-     * @param query         the lucene query to execute on the index.
-     * @param selectProps   the select properties of the query.
-     * @param orderProps    the names of the order properties.
-     * @param orderSpecs    the order specs, one for each order property name.
-     * @param documentOrder if <code>true</code> the result is returned in
-     *                      document order.
-     */
-    public QueryResultImpl(SearchIndex index,
-                           ItemManager itemMgr,
-                           NamespaceResolver resolver,
-                           AccessManager accessMgr,
-                           QueryImpl queryImpl,
-                           Query query,
+     * @param itemMgr     the item manager of the session executing the query.
+     * @param ids         the Ids of the result nodes.
+     * @param scores      the score values of the result nodes.
+     * @param selectProps the select properties of the query.
+     * @param resolver    the namespace resolver of the session executing the query.
+     * @param docOrder    if <code>true</code> the result is returned in document
+     *  order.
+     */
+    public QueryResultImpl(ItemManager itemMgr,
+                           NodeId[] ids,
+                           Float[] scores,
                            QName[] selectProps,
-                           QName[] orderProps,
-                           boolean[] orderSpecs,
-                           boolean documentOrder) throws RepositoryException {
-        this.index = index;
+                           NamespaceResolver resolver,
+                           boolean docOrder) {
+        this.scoreNodes = new ScoreNode[ids.length];
         this.itemMgr = itemMgr;
-        this.resolver = resolver;
-        this.accessMgr = accessMgr;
-        this.queryImpl = queryImpl;
-        this.query = query;
         this.selectProps = selectProps;
-        this.orderProps = orderProps;
-        this.orderSpecs = orderSpecs;
-        this.docOrder = orderProps.length == 0 && documentOrder;
-        // if document order is requested get all results right away
-        getResults(docOrder ? Integer.MAX_VALUE : index.getResultFetchSize());
+        this.resolver = resolver;
+        this.docOrder = docOrder;
+        for (int i = 0; i < ids.length; i++) {
+            scoreNodes[i] = new ScoreNode(ids[i], scores[i].floatValue());
+        }
     }
 
     /**
@@ -194,248 +126,14 @@
     }
 
     /**
-     * Executes the query for this result and returns hits. The caller must
-     * close the query hits when he is done using it.
-     *
-     * @return hits for this query result.
-     * @throws IOException if an error occurs while executing the query.
-     */
-    protected QueryHits executeQuery() throws IOException {
-        return index.executeQuery(queryImpl, query, orderProps, orderSpecs);
-    }
-
-    //--------------------------------< internal >------------------------------
-
-    /**
      * Creates a node iterator over the result nodes.
-     *
      * @return a node iterator over the result nodes.
      */
     private ScoreNodeIterator getNodeIterator() {
         if (docOrder) {
-            return new DocOrderNodeIteratorImpl(itemMgr, resultNodes);
+            return new DocOrderNodeIteratorImpl(itemMgr, Arrays.asList(scoreNodes));
         } else {
-            return new LazyScoreNodeIterator();
-        }
-    }
-
-    /**
-     * Attempts to get <code>size</code> results and puts them into {@link
-     * #resultNodes}. If the size of {@link #resultNodes} is less than
-     * <code>size</code> then there are no more than <code>resultNodes.size()</code>
-     * results for this query.
-     *
-     * @param size the number of results to fetch for the query.
-     * @throws RepositoryException if an error occurs while executing the
-     *                             query.
-     */
-    private void getResults(int size) throws RepositoryException {
-        if (log.isDebugEnabled()) {
-            log.debug("getResults(" + size + ")");
-        }
-        if (resultNodes.size() >= size) {
-            // we already have them all
-            return;
-        }
-
-        // execute it
-        QueryHits result = null;
-        try {
-            result = executeQuery();
-
-            // set num results with the first query execution
-            if (numResults == -1) {
-                numResults = result.length();
-            }
-
-            int start = resultNodes.size() + invalid;
-            int max = Math.min(result.length(), numResults);
-            for (int i = start; i < max && resultNodes.size() < size; i++)
{
-                NodeId id = NodeId.valueOf(result.doc(i).get(FieldNames.UUID));
-                // check access
-                try {
-                    if (accessMgr.isGranted(id, AccessManager.READ)) {
-                        resultNodes.add(new ScoreNode(id, result.score(i)));
-                    }
-                } catch (ItemNotFoundException e) {
-                    // has been deleted meanwhile
-                    invalid++;
-                }
-            }
-        } catch (IOException e) {
-            log.error("Exception while executing query: ", e);
-            // todo throw?
-        } finally {
-            if (result != null) {
-                try {
-                    result.close();
-                } catch (IOException e) {
-                    log.warn("Unable to close query result: " + e);
-                }
-            }
-        }
-    }
-
-    private final class LazyScoreNodeIterator implements ScoreNodeIterator {
-
-        private int position = -1;
-
-        private boolean initialized = false;
-
-        private NodeImpl next;
-
-        /**
-         * {@inheritDoc}
-         */
-        public float getScore() {
-            initialize();
-            if (!hasNext()) {
-                throw new NoSuchElementException();
-            }
-            return ((ScoreNode) resultNodes.get(position)).getScore();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public NodeImpl nextNodeImpl() {
-            initialize();
-            if (next == null) {
-                throw new NoSuchElementException();
-            }
-            NodeImpl n = next;
-            fetchNext();
-            return n;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public Node nextNode() {
-            return nextNodeImpl();
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public void skip(long skipNum) {
-            initialize();
-            if (skipNum < 0) {
-                throw new IllegalArgumentException("skipNum must not be negative");
-            }
-            if ((position + invalid + skipNum) > numResults) {
-                throw new NoSuchElementException();
-            }
-            if (skipNum == 0) {
-                // do nothing
-            } else {
-                // attempt to get enough results
-                try {
-                    getResults(position + invalid + (int) skipNum);
-                    if (resultNodes.size() >= position + skipNum) {
-                        // skip within already fetched results
-                        position += skipNum - 1;
-                        fetchNext();
-                    } else {
-                        // not enough results after getResults()
-                        throw new NoSuchElementException();
-                    }
-                } catch (RepositoryException e) {
-                    throw new NoSuchElementException(e.getMessage());
-                }
-            }
-        }
-
-        /**
-         * {@inheritDoc}
-         * <p/>
-         * This value may shrink when the query result encounters non-existing
-         * nodes or the session does not have access to a node.
-         */
-        public long getSize() {
-            return numResults - invalid;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public long getPosition() {
-            initialize();
-            return position;
-        }
-
-        /**
-         * @throws UnsupportedOperationException always.
-         */
-        public void remove() {
-            throw new UnsupportedOperationException("remove");
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public boolean hasNext() {
-            initialize();
-            return next != null;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public Object next() {
-            return nextNodeImpl();
-        }
-
-        /**
-         * Initializes this iterator but only if it is not yet initialized.
-         */
-        private void initialize() {
-            if (!initialized) {
-                fetchNext();
-                initialized = true;
-            }
-        }
-
-        /**
-         * Fetches the next node to return by this iterator. If this method
-         * returns and {@link #next} is <code>null</code> then there is no next
-         * node.
-         */
-        private void fetchNext() {
-            next = null;
-            int nextPos = position + 1;
-            while (next == null && (nextPos + invalid) < numResults) {
-                if (nextPos >= resultNodes.size()) {
-                    // fetch more results
-                    try {
-                        int num;
-                        if (resultNodes.size() == 0) {
-                            num = index.getResultFetchSize();
-                        } else {
-                            num = resultNodes.size() * 2;
-                        }
-                        getResults(num);
-                    } catch (RepositoryException e) {
-                        log.warn("Exception getting more results: " + e);
-                    }
-                    // check again
-                    if (nextPos >= resultNodes.size()) {
-                        // no more valid results
-                        return;
-                    }
-                }
-                ScoreNode sn = (ScoreNode) resultNodes.get(nextPos);
-                try {
-                    next = (NodeImpl) itemMgr.getItem(sn.getNodeId());
-                } catch (RepositoryException e) {
-                    log.warn("Exception retrieving Node with UUID: "
-                            + sn.getNodeId() + ": " + e.toString());
-                    // remove score node and try next
-                    resultNodes.remove(nextPos);
-                    invalid++;
-                }
-            }
-            position++;
+            return new NodeIteratorImpl(itemMgr, scoreNodes);
         }
     }
 }



Mime
View raw message