From 022af00d5dc3bcfa3e6cc941688ceffe749f1e93 Mon Sep 17 00:00:00 2001 From: niall Date: Wed, 2 Oct 2013 19:30:28 +0000 Subject: [PATCH] Fixed FilteringIterator.hasNext advances iterator every time it is called, with patch from Gabe Hicks (issue 23) --- .../resultset/filter/FilteringIterator.java | 14 +-- .../filter/FilteringIteratorTest.java | 96 +++++++++++++++++++ 2 files changed, 104 insertions(+), 6 deletions(-) create mode 100644 cqengine/trunk/src/test/java/com/googlecode/cqengine/resultset/filter/FilteringIteratorTest.java diff --git a/cqengine/trunk/src/main/java/com/googlecode/cqengine/resultset/filter/FilteringIterator.java b/cqengine/trunk/src/main/java/com/googlecode/cqengine/resultset/filter/FilteringIterator.java index a2b4170..4c4b1c8 100644 --- a/cqengine/trunk/src/main/java/com/googlecode/cqengine/resultset/filter/FilteringIterator.java +++ b/cqengine/trunk/src/main/java/com/googlecode/cqengine/resultset/filter/FilteringIterator.java @@ -41,6 +41,9 @@ public FilteringIterator(Iterator wrappedIterator) { @Override public boolean hasNext() { + if(nextObjectIsNull || nextObject != null) { + return true; + } while (wrappedIterator.hasNext()) { nextObject = wrappedIterator.next(); if (isValid(nextObject)) { @@ -54,14 +57,13 @@ public boolean hasNext() { @Override public O next() { - if (nextObjectIsNull) { - nextObjectIsNull = false; - return null; - } - if (nextObject == null) { + if(!hasNext()) { throw new NoSuchElementException(); } - return nextObject; + O objectToReturn = nextObject; + nextObject = null; + nextObjectIsNull = false; + return objectToReturn; } public abstract boolean isValid(O object); diff --git a/cqengine/trunk/src/test/java/com/googlecode/cqengine/resultset/filter/FilteringIteratorTest.java b/cqengine/trunk/src/test/java/com/googlecode/cqengine/resultset/filter/FilteringIteratorTest.java new file mode 100644 index 0000000..5286151 --- /dev/null +++ b/cqengine/trunk/src/test/java/com/googlecode/cqengine/resultset/filter/FilteringIteratorTest.java @@ -0,0 +1,96 @@ +/** + * Copyright 2012 Niall Gallagher + * + * Licensed 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 com.googlecode.cqengine.resultset.filter; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.NoSuchElementException; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; + +public class FilteringIteratorTest { + @Test + public void testHasNextDoesNotAdvanceIterator(){ + List testList = Arrays.asList("abc", "bcd", "cde"); + FilteringIterator iterator = new FilteringIterator(testList.iterator()) { + @Override + public boolean isValid(String object) { + return true; + } + }; + iterator.hasNext(); + iterator.hasNext(); + iterator.hasNext(); + assertThat(iterator.next(), is("abc")); + } + + @Test + public void testNextPopulatedWithoutCallingHasNext(){ + List testList = Arrays.asList("abc", "bcd", "cde"); + FilteringIterator iterator = new FilteringIterator(testList.iterator()) { + @Override + public boolean isValid(String object) { + return true; + } + }; + assertThat(iterator.next(), is("abc")); + } + + @Test + public void testDelegatedIteratorHasNulls() { + List testList = Arrays.asList("abc", null, "cde"); + FilteringIterator iterator = new FilteringIterator(testList.iterator()) { + @Override + public boolean isValid(String object) { + return true; + } + }; + assertThat(iterator.next(), is("abc")); + assertThat(iterator.next(), nullValue()); + assertThat(iterator.next(), is("cde")); + assertThat(iterator.hasNext(), is(false)); + } + + @Test + public void testFiltering() { + List testList = Arrays.asList("aaa", "bbb", "aab", "bba"); + FilteringIterator iterator = new FilteringIterator(testList.iterator()) { + @Override + public boolean isValid(String object) { + return object.startsWith("aa"); + } + }; + assertThat(iterator.next(), is("aaa")); + assertThat(iterator.next(), is("aab")); + assertThat(iterator.hasNext(), is(false)); + } + + @Test(expected = NoSuchElementException.class) + public void testEmptyDelegate() { + List testList = Arrays.asList(); + FilteringIterator iterator = new FilteringIterator(testList.iterator()) { + @Override + public boolean isValid(String object) { + return true; + } + }; + iterator.next(); + } +}