diff --git a/src/main/java/org/springframework/data/keyvalue/core/Entry.java b/src/main/java/org/springframework/data/keyvalue/core/Entry.java deleted file mode 100644 index fde586f..0000000 --- a/src/main/java/org/springframework/data/keyvalue/core/Entry.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * 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 org.springframework.data.keyvalue.core; - -import java.util.Map; - -/** - * @author Christoph Strobl - * @param - * @param - */ -public interface Entry extends Map.Entry { - -} diff --git a/src/main/java/org/springframework/data/keyvalue/core/ForwardingCloseableIterator.java b/src/main/java/org/springframework/data/keyvalue/core/ForwardingCloseableIterator.java new file mode 100644 index 0000000..924ed9d --- /dev/null +++ b/src/main/java/org/springframework/data/keyvalue/core/ForwardingCloseableIterator.java @@ -0,0 +1,72 @@ +/* + * Copyright 2015 the original author or authors. + * + * 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 org.springframework.data.keyvalue.core; + +import java.util.Iterator; +import java.util.Map; + +import org.springframework.data.util.CloseableIterator; + +/** + * Forwards {@link CloseableIterator} invocations to the configured {@link Iterator} delegate. + * + * @author Christoph Strobl + * @author Thomas Darimont + * @param + * @param + */ +public class ForwardingCloseableIterator implements CloseableIterator> { + + private final Iterator> delegate; + private final Runnable closeHandler; + + /** + * Creates a new {@link ForwardingCloseableIterator}. + * + * @param delegate must not be {@literal null} + */ + public ForwardingCloseableIterator(Iterator> delegate) { + this(delegate, null); + } + + /** + * Creates a new {@link ForwardingCloseableIterator} that invokes the configured {@code closeHanlder} on {@link #close()}. + * + * @param delegate must not be {@literal null} + * @param closeHandler may be {@literal null} + */ + public ForwardingCloseableIterator(Iterator> delegate, Runnable closeHandler) { + this.delegate = delegate; + this.closeHandler = closeHandler; + } + + @Override + public boolean hasNext() { + return delegate.hasNext(); + } + + @Override + public Map.Entry next() { + return delegate.next(); + } + + @Override + public void close() { + if (closeHandler != null) { + closeHandler.run(); + } + } +} diff --git a/src/main/java/org/springframework/data/keyvalue/core/ForwardingKeyValueIterator.java b/src/main/java/org/springframework/data/keyvalue/core/ForwardingKeyValueIterator.java deleted file mode 100644 index ce19979..0000000 --- a/src/main/java/org/springframework/data/keyvalue/core/ForwardingKeyValueIterator.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * 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 org.springframework.data.keyvalue.core; - -import java.io.IOException; -import java.util.Iterator; -import java.util.Map; - -/** - * @author Christoph Strobl - * @param - * @param - */ -public class ForwardingKeyValueIterator implements KeyValueIterator { - - private final Iterator> delegate; - - public ForwardingKeyValueIterator(Iterator> delegate) { - this.delegate = delegate; - } - - @Override - public boolean hasNext() { - return delegate.hasNext(); - } - - @Override - public Entry next() { - return new ForwardingEntry(delegate.next()); - } - - @Override - public void close() throws IOException { - - } - - class ForwardingEntry implements Entry { - - private final Map.Entry entry; - - public ForwardingEntry(Map.Entry entry) { - this.entry = entry; - } - - @Override - public K getKey() { - return entry.getKey(); - } - - @Override - public V getValue() { - return entry.getValue(); - } - - @Override - public V setValue(V value) { - return entry.setValue(value); - } - - @Override - public String toString() { - return entry != null ? entry.toString() : "null"; - } - - } -} diff --git a/src/main/java/org/springframework/data/keyvalue/core/KeyValueAdapter.java b/src/main/java/org/springframework/data/keyvalue/core/KeyValueAdapter.java index 14a0477..8903417 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/KeyValueAdapter.java +++ b/src/main/java/org/springframework/data/keyvalue/core/KeyValueAdapter.java @@ -17,9 +17,11 @@ package org.springframework.data.keyvalue.core; import java.io.Serializable; import java.util.Collection; +import java.util.Map; import org.springframework.beans.factory.DisposableBean; import org.springframework.data.keyvalue.core.query.KeyValueQuery; +import org.springframework.data.util.CloseableIterator; /** * {@link KeyValueAdapter} unifies access and shields the underlying key/value specific implementation. @@ -79,7 +81,7 @@ public interface KeyValueAdapter extends DisposableBean { * @param keyspace * @return */ - KeyValueIterator entries(Serializable keyspace); + CloseableIterator> entries(Serializable keyspace); /** * Remove all objects of given type. diff --git a/src/main/java/org/springframework/data/keyvalue/core/KeyValueIterator.java b/src/main/java/org/springframework/data/keyvalue/core/KeyValueIterator.java deleted file mode 100644 index 9aec129..0000000 --- a/src/main/java/org/springframework/data/keyvalue/core/KeyValueIterator.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2015 the original author or authors. - * - * 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 org.springframework.data.keyvalue.core; - -import java.io.Closeable; -import java.util.Iterator; - -/** - * @author Christoph Strobl - * @param - * @param - */ -public interface KeyValueIterator extends Iterator>, Closeable { - -} diff --git a/src/main/java/org/springframework/data/map/MapKeyValueAdapter.java b/src/main/java/org/springframework/data/map/MapKeyValueAdapter.java index 4c0acc8..38012c9 100644 --- a/src/main/java/org/springframework/data/map/MapKeyValueAdapter.java +++ b/src/main/java/org/springframework/data/map/MapKeyValueAdapter.java @@ -17,14 +17,16 @@ package org.springframework.data.map; import java.io.Serializable; import java.util.Collection; +import java.util.Iterator; import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import org.springframework.core.CollectionFactory; import org.springframework.data.keyvalue.core.AbstractKeyValueAdapter; -import org.springframework.data.keyvalue.core.ForwardingKeyValueIterator; +import org.springframework.data.keyvalue.core.ForwardingCloseableIterator; import org.springframework.data.keyvalue.core.KeyValueAdapter; -import org.springframework.data.keyvalue.core.KeyValueIterator; +import org.springframework.data.util.CloseableIterator; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -104,7 +106,6 @@ public class MapKeyValueAdapter extends AbstractKeyValueAdapter { return get(id, keyspace) != null; } - /* (non-Javadoc) * @see org.springframework.data.keyvalue.core.KeyValueAdapter#count(java.io.Serializable) */ @@ -149,8 +150,8 @@ public class MapKeyValueAdapter extends AbstractKeyValueAdapter { * @see org.springframework.data.keyvalue.core.KeyValueAdapter#entries(java.io.Serializable) */ @Override - public KeyValueIterator entries(Serializable keyspace) { - return new ForwardingKeyValueIterator(getKeySpaceMap(keyspace).entrySet().iterator()); + public CloseableIterator> entries(Serializable keyspace) { + return new ForwardingCloseableIterator(getKeySpaceMap(keyspace).entrySet().iterator()); } /* diff --git a/src/test/java/org/springframework/data/keyvalue/core/ForwardingIteratorUnitTests.java b/src/test/java/org/springframework/data/keyvalue/core/ForwardingCloseableIteratorUnitTests.java similarity index 73% rename from src/test/java/org/springframework/data/keyvalue/core/ForwardingIteratorUnitTests.java rename to src/test/java/org/springframework/data/keyvalue/core/ForwardingCloseableIteratorUnitTests.java index 7ad0145..4291cc8 100644 --- a/src/test/java/org/springframework/data/keyvalue/core/ForwardingIteratorUnitTests.java +++ b/src/test/java/org/springframework/data/keyvalue/core/ForwardingCloseableIteratorUnitTests.java @@ -20,7 +20,6 @@ import static org.hamcrest.core.IsNull.*; import static org.junit.Assert.*; import static org.mockito.Mockito.*; -import java.io.IOException; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; @@ -32,11 +31,13 @@ import org.mockito.runners.MockitoJUnitRunner; /** * @author Christoph Strobl + * @author Thomas Darimont */ @RunWith(MockitoJUnitRunner.class) -public class ForwardingIteratorUnitTests { +public class ForwardingCloseableIteratorUnitTests { @Mock Iterator> iteratorMock; + @Mock Runnable closeActionMock; /** * @see DATAKV-99 @@ -46,7 +47,7 @@ public class ForwardingIteratorUnitTests { when(iteratorMock.hasNext()).thenReturn(true); - assertThat(new ForwardingKeyValueIterator(iteratorMock).hasNext(), is(true)); + assertThat(new ForwardingCloseableIterator(iteratorMock).hasNext(), is(true)); verify(iteratorMock, times(1)).hasNext(); } @@ -59,7 +60,7 @@ public class ForwardingIteratorUnitTests { when(iteratorMock.next()).thenReturn((Map.Entry) mock(Map.Entry.class)); - assertThat(new ForwardingKeyValueIterator(iteratorMock).next(), notNullValue()); + assertThat(new ForwardingCloseableIterator(iteratorMock).next(), notNullValue()); verify(iteratorMock, times(1)).next(); } @@ -72,18 +73,28 @@ public class ForwardingIteratorUnitTests { when(iteratorMock.next()).thenThrow(new NoSuchElementException()); - new ForwardingKeyValueIterator(iteratorMock).next(); + new ForwardingCloseableIterator(iteratorMock).next(); } /** * @see DATAKV-99 */ @Test - public void closeShouldDoNothing() throws IOException { + public void closeShouldDoNothingByDefault() { - new ForwardingKeyValueIterator(iteratorMock).close(); + new ForwardingCloseableIterator(iteratorMock).close(); verifyZeroInteractions(iteratorMock); } + /** + * @see DATAKV-99 + */ + @Test + public void closeShouldInvokeConfiguredCloseAction() { + + new ForwardingCloseableIterator(iteratorMock, closeActionMock).close(); + + verify(closeActionMock, times(1)).run(); + } } diff --git a/src/test/java/org/springframework/data/keyvalue/test/util/IsEntry.java b/src/test/java/org/springframework/data/keyvalue/test/util/IsEntry.java index 8b3ef19..b7138cf 100644 --- a/src/test/java/org/springframework/data/keyvalue/test/util/IsEntry.java +++ b/src/test/java/org/springframework/data/keyvalue/test/util/IsEntry.java @@ -15,18 +15,21 @@ */ package org.springframework.data.keyvalue.test.util; +import java.util.AbstractMap; +import java.util.Map; + import org.hamcrest.CustomMatcher; import org.hamcrest.core.IsEqual; -import org.springframework.data.keyvalue.core.Entry; /** * @author Christoph Strobl + * @author Thomas Darimont */ -public class IsEntry extends CustomMatcher> { +public class IsEntry extends CustomMatcher> { - private final Entry expected; + private final Map.Entry expected; - private IsEntry(Entry entry) { + private IsEntry(Map.Entry entry) { super(String.format("an entry %s=%s.", entry != null ? entry.getKey() : "null", entry != null ? entry.getValue() : "null")); this.expected = entry; @@ -39,11 +42,11 @@ public class IsEntry extends CustomMatcher> { return true; } - if (!(item instanceof Entry)) { + if (!(item instanceof Map.Entry)) { return false; } - Entry actual = (Entry) item; + Map.Entry actual = (Map.Entry) item; return new IsEqual(expected.getKey()).matches(actual.getKey()) && new IsEqual(expected.getValue()).matches(actual.getValue()); @@ -53,28 +56,16 @@ public class IsEntry extends CustomMatcher> { return isEntry(new EntryImpl(key, value)); } - public static IsEntry isEntry(Entry entry) { + public static IsEntry isEntry(Map.Entry entry) { return new IsEntry(entry); } - private static class EntryImpl implements Entry { + private static class EntryImpl extends AbstractMap.SimpleEntry { - private final Object key; - private final Object value; + private static final long serialVersionUID = 1L; private EntryImpl(Object key, Object value) { - this.key = key; - this.value = value; - } - - @Override - public Object getKey() { - return key; - } - - @Override - public Object getValue() { - return value; + super(key, value); } @Override diff --git a/src/test/java/org/springframework/data/map/MapKeyValueAdapterUnitTests.java b/src/test/java/org/springframework/data/map/MapKeyValueAdapterUnitTests.java index e36d640..16a135d 100644 --- a/src/test/java/org/springframework/data/map/MapKeyValueAdapterUnitTests.java +++ b/src/test/java/org/springframework/data/map/MapKeyValueAdapterUnitTests.java @@ -23,10 +23,11 @@ import static org.junit.Assert.*; import static org.springframework.data.keyvalue.test.util.IsEntry.*; import java.io.Serializable; +import java.util.Map; import org.junit.Before; import org.junit.Test; -import org.springframework.data.keyvalue.core.KeyValueIterator; +import org.springframework.data.util.CloseableIterator; import org.springframework.util.ObjectUtils; /** @@ -198,7 +199,7 @@ public class MapKeyValueAdapterUnitTests { adapter.put("1", object1, COLLECTION_1); adapter.put("2", object2, COLLECTION_1); - KeyValueIterator iterator = adapter.entries(COLLECTION_1); + CloseableIterator> iterator = adapter.entries(COLLECTION_1); assertThat(iterator.next(), isEntry("1", object1)); assertThat(iterator.next(), isEntry("2", object2)); @@ -222,7 +223,7 @@ public class MapKeyValueAdapterUnitTests { adapter.put("1", object1, COLLECTION_1); adapter.put("2", object2, COLLECTION_2); - KeyValueIterator iterator = adapter.entries(COLLECTION_1); + CloseableIterator> iterator = adapter.entries(COLLECTION_1); assertThat(iterator.next(), isEntry("1", object1)); assertThat(iterator.hasNext(), is(false));