DATAKV-101 - Favor Iterable over Collection types for KeyValueOperations.
Change return types for Adapter and Operations from Collection types to Iterable. Added count(keyspace) to KeyValueAdapter. Original pull request: #8.
This commit is contained in:
committed by
Thomas Darimont
parent
16dc4b5e7d
commit
952a901164
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Converter capable of transforming a given {@link Iterable} into a collection type.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @param <T>
|
||||
*/
|
||||
public final class IterableConverter {
|
||||
|
||||
private IterableConverter() {}
|
||||
|
||||
/**
|
||||
* Converts a given {@link Iterable} into a {@link List}
|
||||
*
|
||||
* @param source
|
||||
* @return {@link Collections#emptyList()} when source is {@literal null}.
|
||||
*/
|
||||
public static <T> List<T> toList(Iterable<T> source) {
|
||||
|
||||
if (source == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
if (source instanceof List) {
|
||||
return (List<T>) source;
|
||||
}
|
||||
|
||||
if (source instanceof Collection) {
|
||||
return new ArrayList<T>((Collection<T>) source);
|
||||
}
|
||||
|
||||
List<T> result = new ArrayList<T>();
|
||||
for (T value : source) {
|
||||
result.add(value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,7 @@ public interface KeyValueAdapter extends DisposableBean {
|
||||
* @param keyspace must not be {@literal null}.
|
||||
* @return empty {@link Collection} if nothing found.
|
||||
*/
|
||||
Collection<?> getAllOf(Serializable keyspace);
|
||||
Iterable<?> getAllOf(Serializable keyspace);
|
||||
|
||||
/**
|
||||
* Returns a {@link KeyValueIterator} that iterates over all entries.
|
||||
@@ -100,7 +100,14 @@ public interface KeyValueAdapter extends DisposableBean {
|
||||
* @param keyspace must not be {@literal null}.
|
||||
* @return empty {@link Collection} if no match found.
|
||||
*/
|
||||
Collection<?> find(KeyValueQuery<?> query, Serializable keyspace);
|
||||
Iterable<?> find(KeyValueQuery<?> query, Serializable keyspace);
|
||||
|
||||
/**
|
||||
* Count number of objects within {@literal keyspace}.
|
||||
*
|
||||
* @param keyspace must not be {@literal null}.
|
||||
*/
|
||||
long count(Serializable keyspace);
|
||||
|
||||
/**
|
||||
* Count all matching objects within {@literal keyspace}.
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package org.springframework.data.keyvalue.core;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.data.domain.Sort;
|
||||
@@ -52,9 +51,9 @@ public interface KeyValueOperations extends DisposableBean {
|
||||
* assigned to requested type.
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @return empty collection if no elements found.
|
||||
* @return empty iterable if no elements found.
|
||||
*/
|
||||
<T> List<T> findAll(Class<T> type);
|
||||
<T> Iterable<T> findAll(Class<T> type);
|
||||
|
||||
/**
|
||||
* Get all elements ordered by sort. Respects {@link KeySpace} if present and therefore returns all elements that can
|
||||
@@ -64,7 +63,7 @@ public interface KeyValueOperations extends DisposableBean {
|
||||
* @param type must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
<T> List<T> findAll(Sort sort, Class<T> type);
|
||||
<T> Iterable<T> findAll(Sort sort, Class<T> type);
|
||||
|
||||
/**
|
||||
* Get element of given type with given id. Respects {@link KeySpace} if present and therefore returns all elements
|
||||
@@ -90,9 +89,9 @@ public interface KeyValueOperations extends DisposableBean {
|
||||
*
|
||||
* @param query must not be {@literal null}.
|
||||
* @param type must not be {@literal null}.
|
||||
* @return empty collection if no match found.
|
||||
* @return empty iterable if no match found.
|
||||
*/
|
||||
<T> List<T> find(KeyValueQuery<?> query, Class<T> type);
|
||||
<T> Iterable<T> find(KeyValueQuery<?> query, Class<T> type);
|
||||
|
||||
/**
|
||||
* Get all elements in given range. Respects {@link KeySpace} if present and therefore returns all elements that can
|
||||
@@ -103,7 +102,7 @@ public interface KeyValueOperations extends DisposableBean {
|
||||
* @param type must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
<T> List<T> findInRange(int offset, int rows, Class<T> type);
|
||||
<T> Iterable<T> findInRange(int offset, int rows, Class<T> type);
|
||||
|
||||
/**
|
||||
* Get all elements in given range ordered by sort. Respects {@link KeySpace} if present and therefore returns all
|
||||
@@ -115,7 +114,7 @@ public interface KeyValueOperations extends DisposableBean {
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
<T> List<T> findInRange(int offset, int rows, Sort sort, Class<T> type);
|
||||
<T> Iterable<T> findInRange(int offset, int rows, Sort sort, Class<T> type);
|
||||
|
||||
/**
|
||||
* @param objectToUpdate must not be {@literal null}.
|
||||
|
||||
@@ -19,7 +19,6 @@ import static org.springframework.data.keyvalue.core.KeySpaceUtils.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -203,14 +202,14 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationContextA
|
||||
@Override
|
||||
public List<T> doInKeyValue(KeyValueAdapter adapter) {
|
||||
|
||||
Collection<?> x = adapter.getAllOf(resolveKeySpace(type));
|
||||
Iterable<?> values = adapter.getAllOf(resolveKeySpace(type));
|
||||
|
||||
if (getKeySpace(type) == null) {
|
||||
return new ArrayList<T>((Collection<T>) x);
|
||||
return new ArrayList<T>(IterableConverter.toList((Iterable<T>) values));
|
||||
}
|
||||
|
||||
ArrayList<T> filtered = new ArrayList<T>();
|
||||
for (Object candidate : x) {
|
||||
for (Object candidate : values) {
|
||||
if (typeCheck(type, candidate)) {
|
||||
filtered.add((T) candidate);
|
||||
}
|
||||
@@ -332,7 +331,7 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationContextA
|
||||
public long count(Class<?> type) {
|
||||
|
||||
Assert.notNull(type, "Type for count must not be null!");
|
||||
return findAll(type).size();
|
||||
return adapter.count(resolveKeySpace(type));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -364,10 +363,10 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationContextA
|
||||
@Override
|
||||
public List<T> doInKeyValue(KeyValueAdapter adapter) {
|
||||
|
||||
Collection<?> result = adapter.find(query, resolveKeySpace(type));
|
||||
Iterable<?> result = adapter.find(query, resolveKeySpace(type));
|
||||
|
||||
if (getKeySpace(type) == null) {
|
||||
return new ArrayList<T>((Collection<T>) result);
|
||||
return new ArrayList<T>(IterableConverter.toList((Iterable<T>) result));
|
||||
}
|
||||
|
||||
List<T> filtered = new ArrayList<T>();
|
||||
@@ -517,7 +516,7 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationContextA
|
||||
}
|
||||
|
||||
private void potentiallyPublishEvent(KeyValueEvent event) {
|
||||
|
||||
|
||||
if (eventPublisher == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -65,10 +65,10 @@ class SpelQueryEngine<T extends KeyValueAdapter> extends QueryEngine<KeyValueAda
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private List<?> sortAndFilterMatchingRange(Collection<?> source, SpelExpression criteria, Comparator sort,
|
||||
int offset, int rows) {
|
||||
private List<?> sortAndFilterMatchingRange(Iterable<?> source, SpelExpression criteria, Comparator sort, int offset,
|
||||
int rows) {
|
||||
|
||||
List<?> tmp = new ArrayList(source);
|
||||
List<?> tmp = IterableConverter.toList(source);
|
||||
if (sort != null) {
|
||||
Collections.sort(tmp, sort);
|
||||
}
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
package org.springframework.data.keyvalue.repository.query;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.keyvalue.core.IterableConverter;
|
||||
import org.springframework.data.keyvalue.core.KeyValueOperations;
|
||||
import org.springframework.data.keyvalue.core.query.KeyValueQuery;
|
||||
import org.springframework.data.repository.query.EvaluationContextProvider;
|
||||
@@ -33,7 +33,6 @@ import org.springframework.data.repository.query.parser.PartTree;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.spel.standard.SpelExpression;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* {@link RepositoryQuery} implementation deriving queries from {@link PartTree} using a predefined
|
||||
@@ -77,12 +76,12 @@ public class KeyValuePartTreeQuery implements RepositoryQuery {
|
||||
query.setOffset(page.getOffset());
|
||||
query.setRows(page.getPageSize());
|
||||
|
||||
List<?> result = this.keyValueOperations.find(query, queryMethod.getEntityInformation().getJavaType());
|
||||
Iterable<?> result = this.keyValueOperations.find(query, queryMethod.getEntityInformation().getJavaType());
|
||||
|
||||
long count = queryMethod.isSliceQuery() ? 0 : keyValueOperations.count(query, queryMethod.getEntityInformation()
|
||||
.getJavaType());
|
||||
|
||||
return new PageImpl(result, page, count);
|
||||
return new PageImpl(IterableConverter.toList(result), page, count);
|
||||
|
||||
} else if (queryMethod.isCollectionQuery()) {
|
||||
|
||||
@@ -90,8 +89,8 @@ public class KeyValuePartTreeQuery implements RepositoryQuery {
|
||||
|
||||
} else if (queryMethod.isQueryForEntity()) {
|
||||
|
||||
List<?> result = this.keyValueOperations.find(query, queryMethod.getEntityInformation().getJavaType());
|
||||
return CollectionUtils.isEmpty(result) ? null : result.get(0);
|
||||
Iterable<?> result = this.keyValueOperations.find(query, queryMethod.getEntityInformation().getJavaType());
|
||||
return result.iterator().hasNext() ? result.iterator().next() : null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.keyvalue.core.IterableConverter;
|
||||
import org.springframework.data.keyvalue.core.KeyValueOperations;
|
||||
import org.springframework.data.keyvalue.repository.KeyValueRepository;
|
||||
import org.springframework.data.repository.core.EntityInformation;
|
||||
@@ -76,12 +77,11 @@ public class SimpleKeyValueRepository<T, ID extends Serializable> implements Key
|
||||
return new PageImpl<T>(result, null, result.size());
|
||||
}
|
||||
|
||||
List<T> content = null;
|
||||
|
||||
content = operations.findInRange(pageable.getOffset(), pageable.getPageSize(), pageable.getSort(),
|
||||
Iterable<T> content = operations.findInRange(pageable.getOffset(), pageable.getPageSize(), pageable.getSort(),
|
||||
entityInformation.getJavaType());
|
||||
|
||||
return new PageImpl<T>(content, pageable, this.operations.count(entityInformation.getJavaType()));
|
||||
return new PageImpl<T>(IterableConverter.toList(content), pageable, this.operations.count(entityInformation
|
||||
.getJavaType()));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -139,7 +139,7 @@ public class SimpleKeyValueRepository<T, ID extends Serializable> implements Key
|
||||
*/
|
||||
@Override
|
||||
public List<T> findAll() {
|
||||
return operations.findAll(entityInformation.getJavaType());
|
||||
return IterableConverter.toList(operations.findAll(entityInformation.getJavaType()));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-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.
|
||||
@@ -104,6 +104,15 @@ public class MapKeyValueAdapter extends AbstractKeyValueAdapter {
|
||||
return get(id, keyspace) != null;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.keyvalue.core.KeyValueAdapter#count(java.io.Serializable)
|
||||
*/
|
||||
@Override
|
||||
public long count(Serializable keyspace) {
|
||||
return getKeySpaceMap(keyspace).size();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.keyvalue.core.KeyValueAdapter#get(java.io.Serializable, java.io.Serializable)
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.collection.IsEmptyCollection.*;
|
||||
import static org.hamcrest.collection.IsIterableContainingInOrder.*;
|
||||
import static org.hamcrest.core.IsInstanceOf.*;
|
||||
import static org.hamcrest.core.IsNull.*;
|
||||
import static org.hamcrest.core.IsSame.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.keyvalue.core.IterableConverter.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class IterableConverterUnitTests {
|
||||
|
||||
/**
|
||||
* @see DATAKV-101
|
||||
*/
|
||||
@Test
|
||||
public void toListShouldReturnEmptyListWhenSourceIsNull() {
|
||||
assertThat(toList(null), notNullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAKV-101
|
||||
*/
|
||||
@Test
|
||||
public void toListShouldReturnEmptyListWhenSourceEmpty() {
|
||||
assertThat(toList(Collections.emptySet()), empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAKV-101
|
||||
*/
|
||||
@Test
|
||||
public void toListShouldReturnSameObjectWhenSourceIsAlreadyListType() {
|
||||
|
||||
List<String> source = new ArrayList<String>();
|
||||
|
||||
assertThat(toList(source), sameInstance(source));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAKV-101
|
||||
*/
|
||||
@Test
|
||||
public void toListShouldReturnListWhenSourceIsNonListType() {
|
||||
|
||||
Set<String> source = new HashSet<String>();
|
||||
source.add("tyrion");
|
||||
|
||||
assertThat(toList(source), instanceOf(List.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAKV-101
|
||||
*/
|
||||
@Test
|
||||
public void toListShouldHoldValuesInOrderOfSource() {
|
||||
|
||||
Set<String> source = new LinkedHashSet<String>();
|
||||
source.add("tyrion");
|
||||
source.add("jaime");
|
||||
|
||||
assertThat(toList(source), contains(source.toArray(new String[2])));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -362,11 +362,9 @@ public class KeyValueTemplateUnitTests {
|
||||
* @see DATACMNS-525
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void countShouldReturnCollectionSize() {
|
||||
|
||||
Collection foo = Arrays.asList(FOO_ONE, FOO_ONE);
|
||||
when(adapterMock.getAllOf(Foo.class.getName())).thenReturn(foo);
|
||||
when(adapterMock.count(Foo.class.getName())).thenReturn(2L);
|
||||
|
||||
assertThat(template.count(Foo.class), is(2L));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user