added EAGER_IGNORE_RESULT iteration mode for callback-only PathMappers

This commit is contained in:
Michael Hunger
2011-02-23 00:30:02 +01:00
parent 767bb95fbc
commit b6c65812ea
4 changed files with 76 additions and 12 deletions

View File

@@ -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();
}

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -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;
}