You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2010/08/20 18:49:32 UTC

svn commit: r987567 - in /jackrabbit/trunk/jackrabbit-jcr-commons/src: main/java/org/apache/jackrabbit/commons/iterator/ test/java/org/apache/jackrabbit/commons/iterator/

Author: jukka
Date: Fri Aug 20 16:49:32 2010
New Revision: 987567

URL: http://svn.apache.org/viewvc?rev=987567&view=rev
Log:
JCR-2722: Add a filtered RangeIterator

Added:
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/iterator/FilteredRangeIterator.java   (with props)
    jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/commons/iterator/
    jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/commons/iterator/FilteredRangeIteratorTest.java   (with props)

Added: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/iterator/FilteredRangeIterator.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/iterator/FilteredRangeIterator.java?rev=987567&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/iterator/FilteredRangeIterator.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/iterator/FilteredRangeIterator.java Fri Aug 20 16:49:32 2010
@@ -0,0 +1,204 @@
+/*
+ * 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.commons.iterator;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import javax.jcr.RangeIterator;
+
+import org.apache.jackrabbit.commons.predicate.Predicate;
+
+/**
+ * Filtering decorator for iterators.
+ */
+public class FilteredRangeIterator implements RangeIterator {
+
+    /**
+     * The underlying iterator.
+     */
+    private final Iterator<?> iterator;
+
+    /**
+     * Predicate used for filtering.
+     */
+    private final Predicate predicate;
+
+    /**
+     * Buffer of pre-fetched objects from the underlying iterator.
+     */
+    private final Object[] buffer;
+
+    /**
+     * Current position within the buffer. Guaranteed to be within the
+     * range [0, {@link #bufferSize}].
+     */
+    private int bufferPosition = 0;
+
+    /**
+     * Number of pre-fetched objects in the buffer.
+     */
+    private int bufferSize = 0;
+
+    /**
+     * The zero-based position of the first element in the buffer.
+     */
+    private long position = 0;
+
+    /**
+     * The number of filtered items up to the end of the buffer.
+     */
+    private long size = 0;
+
+
+    /**
+     * Creates a new filtered iterator.
+     *
+     * @param iterator underlying iterator
+     * @param predicate 
+     * @param bufferSize
+     */
+    public FilteredRangeIterator(
+            Iterator<?> iterator, Predicate predicate, int bufferSize) {
+        this.iterator = iterator;
+        this.predicate = predicate;
+        this.buffer = new Object[bufferSize];
+    }
+
+    /**
+     * Creates a new filtered iterator with the default pre-fetch buffer size.
+     *
+     * @param iterator underlying iterator
+     * @param predicate predicate used for filtering
+     */
+    public FilteredRangeIterator(Iterator<?> iterator, Predicate predicate) {
+        this(iterator, predicate, 1000);
+    }
+
+    /**
+     * Creates a pre-fetching decorator for the given iterator. This
+     * constructor is mostly useful when it is desirable to use the
+     * pre-fetching feature to automatically 
+     * 
+     *
+     * @param iterator underlying iterator
+     * @param predicate predicate used for filtering
+     */
+    public FilteredRangeIterator(Iterator<?> iterator) {
+        this(iterator, Predicate.TRUE, 1000);
+    }
+
+    /**
+     * Pre-fetches more items into the buffer.
+     */
+    private void fetch() {
+        if (bufferPosition == bufferSize) {
+            position += bufferSize;
+            bufferPosition = 0;
+            bufferSize = 0;
+            while (bufferSize < buffer.length && iterator.hasNext()) {
+                Object object = iterator.next();
+                if (predicate.evaluate(object)) {
+                    buffer[bufferSize++] = object;
+                }
+            }
+            size += bufferSize;
+        }
+    }
+
+    /**
+     * Returns the zero-based position of the next element in this iterator.
+     *
+     * @return position of the next element
+     */
+    public long getPosition() {
+        return position + bufferPosition;
+    }
+
+    /**
+     * Returns the total number of elements in this iterator, or -1 if that
+     * number is unknown.
+     *
+     * @return number of elements in this iterator, or -1
+     */
+    public long getSize() {
+        fetch();
+        if (iterator.hasNext()) {
+            return -1; // still unknown
+        } else {
+            return size;
+        }
+    }
+
+    /**
+     * Skips the next n elements.
+     *
+     * @param n number of elements to skip
+     * @throws IllegalArgumentException if n is negative
+     * @throws NoSuchElementException if there are not enough elements to skip
+     */
+    public void skip(long n)
+            throws IllegalArgumentException, NoSuchElementException {
+        if (n < 0) {
+            throw new IllegalArgumentException();
+        }
+        while (n > 0) {
+            fetch();
+            if (bufferPosition < bufferSize) {
+                long m = Math.min(n, bufferSize - bufferPosition);
+                bufferPosition += m;
+                n -= m;
+            } else {
+                throw new NoSuchElementException();
+            }
+        }
+    }
+
+    /**
+     * Checks whether there are more elements in this iterator.
+     *
+     * @return <code>true</code> if there are more elements,
+     *         <code>false</code> otherwise
+     */
+    public boolean hasNext() {
+        fetch();
+        return bufferPosition < bufferSize;
+    }
+
+    /**
+     * Returns the next element in this iterator.
+     *
+     * @return next element
+     * @throws NoSuchElementException if there are no more elements
+     */
+    public Object next() throws NoSuchElementException {
+        fetch();
+        if (bufferPosition < bufferSize) {
+            return buffer[bufferPosition++];
+        } else {
+            throw new NoSuchElementException();
+        }
+    }
+
+    /**
+     * Not supported.
+     */
+    public void remove() throws UnsupportedOperationException {
+        throw new UnsupportedOperationException();
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/iterator/FilteredRangeIterator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/commons/iterator/FilteredRangeIteratorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/commons/iterator/FilteredRangeIteratorTest.java?rev=987567&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/commons/iterator/FilteredRangeIteratorTest.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/commons/iterator/FilteredRangeIteratorTest.java Fri Aug 20 16:49:32 2010
@@ -0,0 +1,83 @@
+/*
+ * 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.commons.iterator;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.jcr.RangeIterator;
+
+import org.apache.jackrabbit.commons.predicate.Predicate;
+
+import junit.framework.TestCase;
+
+/**
+ * Test cases for the {@link FilteredRangeIterator} class.
+ *
+ * @see <a href="https://issues.apache.org/jira/browse/JCR-2722">JCR-2722</a>
+ */
+public class FilteredRangeIteratorTest extends TestCase {
+
+    private static final List<String> LIST = Arrays.asList("x", "y", "z");
+
+    public void testMatchAll() {
+        RangeIterator iterator = new FilteredRangeIterator(LIST.iterator());
+        assertEquals(3, iterator.getSize());
+
+        assertEquals(0, iterator.getPosition());
+        assertTrue(iterator.hasNext());
+        assertEquals("x", iterator.next());
+
+        assertEquals(1, iterator.getPosition());
+        assertTrue(iterator.hasNext());
+        assertEquals("y", iterator.next());
+
+        assertEquals(2, iterator.getPosition());
+        assertTrue(iterator.hasNext());
+        assertEquals("z", iterator.next());
+
+        assertEquals(3, iterator.getPosition());
+        assertFalse(iterator.hasNext());
+    }
+
+    public void testMatchNone() {
+        RangeIterator iterator =
+            new FilteredRangeIterator(LIST.iterator(), Predicate.FALSE);
+        assertEquals(0, iterator.getSize());
+        assertEquals(0, iterator.getPosition());
+        assertFalse(iterator.hasNext());
+    }
+
+    public void testSkip() {
+        RangeIterator iterator = new FilteredRangeIterator(LIST.iterator());
+        assertEquals(3, iterator.getSize());
+
+        assertEquals(0, iterator.getPosition());
+        assertTrue(iterator.hasNext());
+        assertEquals("x", iterator.next());
+
+        iterator.skip(1);
+
+        assertEquals(2, iterator.getPosition());
+        assertTrue(iterator.hasNext());
+        assertEquals("z", iterator.next());
+
+        assertEquals(3, iterator.getPosition());
+        assertFalse(iterator.hasNext());
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/commons/iterator/FilteredRangeIteratorTest.java
------------------------------------------------------------------------------
    svn:eol-style = native