@Override public boolean tryAdvance(Consumer<? super R> action) { if (left != null) { if (accept(handleLeft(), action)) { return true; } } if (cur == none()) { // start if (!source.tryAdvance(this)) { return accept(pushRight(none(), none()), action); } } T first = cur; R acc = mapper.apply(cur); T last = first; while (source.tryAdvance(this)) { if (!this.mergeable.test(last, cur)) { action.accept(acc); return true; } last = cur; acc = this.accumulator.apply(acc, last); } return accept(pushRight(acc, last), action); }
@Test public void splitsEventsBackward() { final String stream = generateStreamName(); List<EventData> events = newTestEvents(40); eventstore.appendToStream(stream, ExpectedVersion.NO_STREAM, events).join(); Spliterator<ResolvedEvent> spliterator = new StreamEventsSpliterator( StreamPosition.END, i -> eventstore.readStreamEventsBackward(stream, i, 8, false)); List<ResolvedEvent> result = new ArrayList<>(); range(0, 5) .forEach( i -> { Spliterator<ResolvedEvent> s = spliterator.trySplit(); assertNotNull(s); s.forEachRemaining(result::add); }); assertEquals(40, result.size()); assertNull(spliterator.trySplit()); spliterator.forEachRemaining(e -> fail("Should be no more elements remaining")); assertFalse(spliterator.tryAdvance(result::add)); assertEquals(40, result.size()); assertThat(recordedEventsFrom(result), containsInOrder(reverse(events))); }
@Override public void forEachRemaining(Consumer<? super R> action) { while (left != null) { accept(handleLeft(), action); } if (cur == none()) { if (!source.tryAdvance(this)) { accept(pushRight(none(), none()), action); return; } } acc = mapper.apply(cur); source.forEachRemaining( next -> { if (!this.mergeable.test(cur, next)) { action.accept(acc); acc = mapper.apply(next); } else { acc = accumulator.apply(acc, next); } cur = next; }); if (accept(pushRight(acc, cur), action)) { if (right != null) { action.accept(right.acc); right = null; } } }
@Test public void iteratesAllRemainingEventsForward() { final String stream = generateStreamName(); List<EventData> events = newTestEvents(82); eventstore.appendToStream(stream, ExpectedVersion.NO_STREAM, events).join(); Spliterator<ResolvedEvent> spliterator = new StreamEventsSpliterator( StreamPosition.START, i -> eventstore.readStreamEventsForward(stream, i, 17, false)); List<ResolvedEvent> result = new ArrayList<>(); assertTrue(spliterator.tryAdvance(result::add)); spliterator.forEachRemaining(result::add); assertFalse(spliterator.tryAdvance(result::add)); spliterator.forEachRemaining(e -> fail("Should be no more elements remaining")); assertNull(spliterator.trySplit()); assertEquals(82, result.size()); assertThat(recordedEventsFrom(result), containsInOrder(events)); }
private R handleLeft() { synchronized (root) { Connector<T, R> l = left; if (l == null) { return none(); } if (l.left == NONE && l.right == NONE && l.acc != NONE) { return l.drain(); } } if (source.tryAdvance(this)) { T first = this.cur; T last = first; R acc = this.mapper.apply(first); while (source.tryAdvance(this)) { if (!this.mergeable.test(last, cur)) return pushLeft(first, acc); last = cur; acc = this.accumulator.apply(acc, last); } cur = none(); return connectOne(first, acc, last); } return connectEmpty(); }
@Test public void failsWhenActionIsNull() { Spliterator<ResolvedEvent> spliterator = new StreamEventsSpliterator( StreamPosition.START, i -> eventstore.readStreamEventsForward("foo", i, 1, false)); try { spliterator.tryAdvance(null); fail("should fail with 'NullPointerException'"); } catch (Exception e) { assertThat(e, instanceOf(NullPointerException.class)); } try { spliterator.forEachRemaining(null); fail("should fail with 'NullPointerException'"); } catch (Exception e) { assertThat(e, instanceOf(NullPointerException.class)); } }
@Test public void iteratesAndSplitsEventsBackward() { final String stream = generateStreamName(); List<EventData> events = newTestEvents(40); eventstore.appendToStream(stream, ExpectedVersion.NO_STREAM, events).join(); Spliterator<ResolvedEvent> spliterator = new StreamEventsSpliterator( StreamPosition.END, i -> eventstore.readStreamEventsBackward(stream, i, 8, false)); List<ResolvedEvent> result = new ArrayList<>(); Spliterator<ResolvedEvent> s1, s2, s3; assertTrue(spliterator.tryAdvance(result::add)); s1 = spliterator.trySplit(); assertNotNull(s1); assertTrue(s1.tryAdvance(result::add)); s2 = s1.trySplit(); assertNotNull(s2); assertTrue(s2.tryAdvance(result::add)); s2.forEachRemaining(result::add); assertTrue(s1.tryAdvance(result::add)); s1.forEachRemaining(result::add); assertTrue(spliterator.tryAdvance(result::add)); s3 = spliterator.trySplit(); assertNotNull(s3); assertTrue(s3.tryAdvance(result::add)); s3.forEachRemaining(result::add); assertTrue(spliterator.tryAdvance(result::add)); spliterator.forEachRemaining(result::add); assertNull(spliterator.trySplit()); assertEquals(40, result.size()); assertThat(recordedEventsFrom(result), containsInOrder(reverse(events))); }