Skip to content

DATAKV-99 - Add KeyValueIterator. #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-keyvalue</artifactId>
<version>0.1.0.BUILD-SNAPSHOT</version>
<version>0.1.0.DATAKV-99-SNAPSHOT</version>

<name>Spring Data KeyValue</name>

Expand Down
27 changes: 27 additions & 0 deletions src/main/java/org/springframework/data/keyvalue/core/Entry.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* 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 <K>
* @param <V>
*/
public interface Entry<K, V> extends Map.Entry<K, V> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* 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 <K>
* @param <V>
*/
public class ForwardingKeyValueIterator<K, V> implements KeyValueIterator<K, V> {

private final Iterator<? extends Map.Entry<K, V>> delegate;

public ForwardingKeyValueIterator(Iterator<? extends java.util.Map.Entry<K, V>> delegate) {
this.delegate = delegate;
}

@Override
public boolean hasNext() {
return delegate.hasNext();
}

@Override
public Entry<K, V> next() {
return new ForwardingEntry(delegate.next());
}

@Override
public void close() throws IOException {

}

class ForwardingEntry implements Entry<K, V> {

private final Map.Entry<K, V> entry;

public ForwardingEntry(Map.Entry<K, V> 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";
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* {@link KeyValueAdapter} unifies access and shields the underlying key/value specific implementation.
*
* @author Christoph Strobl
* @author Thomas Darimont
*/
public interface KeyValueAdapter extends DisposableBean {

Expand Down Expand Up @@ -72,6 +73,14 @@ public interface KeyValueAdapter extends DisposableBean {
*/
Collection<?> getAllOf(Serializable keyspace);

/**
* Returns a {@link KeyValueIterator} that iterates over all entries.
*
* @param keyspace
* @return
*/
KeyValueIterator<? extends Serializable, ?> entries(Serializable keyspace);

/**
* Remove all objects of given type.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* 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 <K>
* @param <V>
*/
public interface KeyValueIterator<K, V> extends Iterator<Entry<K, V>>, Closeable {

}
12 changes: 12 additions & 0 deletions src/main/java/org/springframework/data/map/MapKeyValueAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@

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.KeyValueAdapter;
import org.springframework.data.keyvalue.core.KeyValueIterator;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

Expand Down Expand Up @@ -133,6 +135,15 @@ public Collection<?> getAllOf(Serializable keyspace) {
return getKeySpaceMap(keyspace).values();
}

/*
* (non-Javadoc)
* @see org.springframework.data.keyvalue.core.KeyValueAdapter#entries(java.io.Serializable)
*/
@Override
public KeyValueIterator<Serializable, ?> entries(Serializable keyspace) {
return new ForwardingKeyValueIterator<Serializable, Object>(getKeySpaceMap(keyspace).entrySet().iterator());
}

/*
* (non-Javadoc)
* @see org.springframework.data.keyvalue.core.KeyValueAdapter#deleteAllOf(java.io.Serializable)
Expand Down Expand Up @@ -194,4 +205,5 @@ protected Map<Serializable, Object> getKeySpaceMap(Serializable keyspace) {
private void addMapForKeySpace(Serializable keyspace) {
store.put(keyspace, CollectionFactory.<Serializable, Object> createMap(keySpaceMapType, 1000));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* 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 static org.hamcrest.core.Is.*;
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;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

/**
* @author Christoph Strobl
*/
@RunWith(MockitoJUnitRunner.class)
public class ForwardingIteratorUnitTests<K, V> {

@Mock Iterator<Map.Entry<K, V>> iteratorMock;

/**
* @see DATAKV-99
*/
@Test
public void hasNextShoudDelegateToWrappedIterator() {

when(iteratorMock.hasNext()).thenReturn(true);

assertThat(new ForwardingKeyValueIterator<K, V>(iteratorMock).hasNext(), is(true));

verify(iteratorMock, times(1)).hasNext();
}

/**
* @see DATAKV-99
*/
@Test
public void nextShoudDelegateToWrappedIterator() {

when(iteratorMock.next()).thenReturn((Map.Entry<K, V>) mock(Map.Entry.class));

assertThat(new ForwardingKeyValueIterator<K, V>(iteratorMock).next(), notNullValue());

verify(iteratorMock, times(1)).next();
}

/**
* @see DATAKV-99
*/
@Test(expected = NoSuchElementException.class)
public void nextShoudThrowErrorWhenWrappedIteratorHasNoMoreElements() {

when(iteratorMock.next()).thenThrow(new NoSuchElementException());

new ForwardingKeyValueIterator<K, V>(iteratorMock).next();
}

/**
* @see DATAKV-99
*/
@Test
public void closeShouldDoNothing() throws IOException {

new ForwardingKeyValueIterator<K, V>(iteratorMock).close();

verifyZeroInteractions(iteratorMock);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* 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.test.util;

import org.hamcrest.CustomMatcher;
import org.hamcrest.core.IsEqual;
import org.springframework.data.keyvalue.core.Entry;

/**
* @author Christoph Strobl
*/
public class IsEntry extends CustomMatcher<Entry<?, ?>> {

private final Entry<?, ?> expected;

private IsEntry(Entry<?, ?> entry) {
super(String.format("an entry %s=%s.", entry != null ? entry.getKey() : "null", entry != null ? entry.getValue()
: "null"));
this.expected = entry;
}

@Override
public boolean matches(Object item) {

if (item == null && expected == null) {
return true;
}

if (!(item instanceof Entry)) {
return false;
}

Entry<?, ?> actual = (Entry<?, ?>) item;

return new IsEqual<Object>(expected.getKey()).matches(actual.getKey())
&& new IsEqual<Object>(expected.getValue()).matches(actual.getValue());
}

public static IsEntry isEntry(Object key, Object value) {
return isEntry(new EntryImpl(key, value));
}

public static IsEntry isEntry(Entry<?, ?> entry) {
return new IsEntry(entry);
}

private static class EntryImpl implements Entry<Object, Object> {

private final Object key;
private final Object value;

private EntryImpl(Object key, Object value) {
this.key = key;
this.value = value;
}

@Override
public Object getKey() {
return key;
}

@Override
public Object getValue() {
return value;
}

@Override
public Object setValue(Object value) {
throw new UnsupportedOperationException();
}
}
}
Loading