added EAGER_IGNORE_RESULT iteration mode for callback-only PathMappers
This commit is contained in:
@@ -6,7 +6,7 @@ package org.springframework.data.graph.neo4j.template;
|
||||
*/
|
||||
public interface IterationController {
|
||||
public enum IterationMode {
|
||||
LAZY, EAGER, EAGER_STOP_ON_NULL
|
||||
LAZY, EAGER, EAGER_STOP_ON_NULL, EAGER_IGNORE_RESULTS
|
||||
}
|
||||
IterationMode getIterationMode();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,13 @@ package org.springframework.data.graph.neo4j.template;
|
||||
import org.neo4j.graphdb.Path;
|
||||
|
||||
/**
|
||||
* A mapper for paths as the generic return type of querying graph operations. Simple results like just nodes
|
||||
* or relationships are also wrapped in a @{see Path} for uniform access.
|
||||
*
|
||||
* Allows iteration control when implementing @{see IterationController}. Default iteration mode is @{see IterationMode#LAZY}
|
||||
*
|
||||
* Inner class @{see PathMapper.WithoutResult} allows callbacks instead and comes with an eager iteration mode.
|
||||
* @see Path
|
||||
* @author mh
|
||||
* @since 19.02.11
|
||||
*/
|
||||
@@ -10,6 +17,9 @@ public interface PathMapper<T> {
|
||||
|
||||
T mapPath(Path path);
|
||||
|
||||
/**
|
||||
* callback instead of mapping
|
||||
*/
|
||||
public abstract class WithoutResult implements PathMapper<Void>, IterationController{
|
||||
public abstract void eachPath(Path path);
|
||||
|
||||
@@ -21,7 +31,7 @@ public interface PathMapper<T> {
|
||||
|
||||
@Override
|
||||
public IterationMode getIterationMode() {
|
||||
return IterationMode.EAGER;
|
||||
return IterationMode.EAGER_IGNORE_RESULTS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,12 @@ public class PathMappingIterator {
|
||||
result.add(mapped);
|
||||
}
|
||||
return result;
|
||||
|
||||
case EAGER_IGNORE_RESULTS:
|
||||
for (Path path : paths) {
|
||||
pathMapper.mapPath(path);
|
||||
}
|
||||
return null;
|
||||
case LAZY:
|
||||
return new IterableWrapper<T, Path>(paths) {
|
||||
@Override
|
||||
|
||||
@@ -5,8 +5,10 @@ import org.neo4j.graphdb.Path;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
@@ -15,27 +17,73 @@ import static org.mockito.Mockito.mock;
|
||||
*/
|
||||
public class PathMappingIteratorTest {
|
||||
|
||||
private static final int PATHS_COUNT = 3;
|
||||
|
||||
@Test
|
||||
public void lazyIteratorShouldNotCallBackBeforeUse() {
|
||||
runAndCheckMode(0, 3, IterationController.IterationMode.LAZY);
|
||||
runAndCheckMode(0, PATHS_COUNT, IterationController.IterationMode.LAZY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eagerIteratorShouldBeCalledImmediately() {
|
||||
runAndCheckMode(3, 3, IterationController.IterationMode.EAGER);
|
||||
runAndCheckMode(PATHS_COUNT, PATHS_COUNT, IterationController.IterationMode.EAGER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eagerStopOnNullIteratorShouldBeCalledImmediatelyAndReturnReducedResult() {
|
||||
runAndCheckMode(2, 2, IterationController.IterationMode.EAGER_STOP_ON_NULL);
|
||||
}
|
||||
@Test
|
||||
public void eagerStopIgnoresResultIteratorShouldBeCalledImmediatelyAndReturnNoResult() {
|
||||
Iterable<Integer> result = runAndCheckMode(PATHS_COUNT, PATHS_COUNT, IterationController.IterationMode.EAGER_IGNORE_RESULTS);
|
||||
assertNull("no result",result);
|
||||
}
|
||||
|
||||
private void runAndCheckMode(int countAfterMap, int countAfterIteration, IterationController.IterationMode iterationMode) {
|
||||
TestPathMapper lazyMapper = new TestPathMapper(iterationMode);
|
||||
@Test
|
||||
public void defaultPathMapperIsLazy() {
|
||||
final AtomicInteger counter=new AtomicInteger();
|
||||
PathMapper<Integer> pathMapper = new PathMapper<Integer>() {
|
||||
|
||||
@Override
|
||||
public Integer mapPath(Path path) {
|
||||
return counter.incrementAndGet();
|
||||
}
|
||||
};
|
||||
Iterable<Integer> result = new PathMappingIterator().mapPaths(paths(), pathMapper);
|
||||
assertEquals(0, counter.get());
|
||||
for (Integer integer : result) ;
|
||||
assertEquals(PATHS_COUNT, counter.get());
|
||||
}
|
||||
@Test
|
||||
public void defaultPathCallbackIsEagerAndIgnoresResult() {
|
||||
final AtomicInteger counter=new AtomicInteger();
|
||||
PathMapper.WithoutResult pathMapper = new PathMapper.WithoutResult() {
|
||||
|
||||
@Override
|
||||
public void eachPath(Path path) {
|
||||
counter.incrementAndGet();
|
||||
}
|
||||
};
|
||||
Iterable<Void> result = new PathMappingIterator().mapPaths(paths(), pathMapper);
|
||||
assertEquals(PATHS_COUNT, counter.get());
|
||||
assertNull("no result",result);
|
||||
assertEquals(PATHS_COUNT, counter.get());
|
||||
}
|
||||
|
||||
private List<Path> paths() {
|
||||
Path anyPath = mock(Path.class);
|
||||
List<Path> paths = Arrays.asList(anyPath, anyPath, anyPath);
|
||||
Iterable<Integer> result = new PathMappingIterator().mapPaths(paths, lazyMapper);
|
||||
assertEquals(countAfterMap, lazyMapper.counter);
|
||||
for (Integer integer : result);
|
||||
assertEquals(countAfterIteration, lazyMapper.counter);
|
||||
Path[] paths=new Path[3];
|
||||
Arrays.fill(paths,anyPath);
|
||||
return Arrays.asList(paths);
|
||||
}
|
||||
|
||||
private Iterable<Integer> runAndCheckMode(int countAfterMap, int countAfterIteration, IterationController.IterationMode iterationMode) {
|
||||
TestPathMapper pathMapper = new TestPathMapper(iterationMode);
|
||||
Iterable<Integer> result = new PathMappingIterator().mapPaths(paths(), pathMapper);
|
||||
assertEquals(countAfterMap, pathMapper.counter);
|
||||
if (result!=null) for (Integer integer : result) ;
|
||||
assertEquals(countAfterIteration, pathMapper.counter);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class TestPathMapper implements PathMapper<Integer>, IterationController {
|
||||
@@ -49,7 +97,7 @@ public class PathMappingIteratorTest {
|
||||
@Override
|
||||
public Integer mapPath(Path path) {
|
||||
counter++;
|
||||
if (counter==2) return null;
|
||||
if (counter == 2) return null;
|
||||
return counter;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user