@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; } } }
@Override public int characteristics() { int c = NONNULL; c |= spliterator.hasCharacteristics(ORDERED) ? ORDERED : 0; c |= spliterator.hasCharacteristics(SIZED) ? SIZED : 0; return c; }
@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))); }
@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)); } }
@Override public Spliterator<R> trySplit() { Spliterator<T> prefix = source.trySplit(); if (prefix == null) return null; Connector<T, R> newBox = new Connector<>(null, none(), this); synchronized (root) { CollapseSpliterator<T, R> result = new CollapseSpliterator<>(root, prefix, left, newBox); this.left = newBox; return result; } }
@Test public void splitsAndIteratesEventsBackward() { 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; s1 = spliterator.trySplit(); assertNotNull(s1); s1.forEachRemaining(result::add); spliterator.forEachRemaining(result::add); assertNull(spliterator.trySplit()); assertEquals(40, result.size()); assertThat(recordedEventsFrom(result), containsInOrder(reverse(events))); }
/** * Overrides AbstractTask version to include checks for early exits while splitting or computing. */ @Override public void compute() { Spliterator<P_IN> rs = spliterator, ls; long sizeEstimate = rs.estimateSize(); long sizeThreshold = getTargetSize(sizeEstimate); boolean forkRight = false; @SuppressWarnings("unchecked") K task = (K) this; AtomicReference<R> sr = sharedResult; R result; while ((result = sr.get()) == null) { if (task.taskCanceled()) { result = task.getEmptyResult(); break; } if (sizeEstimate <= sizeThreshold || (ls = rs.trySplit()) == null) { result = task.doLeaf(); break; } K leftChild, rightChild, taskToFork; task.leftChild = leftChild = task.makeChild(ls); task.rightChild = rightChild = task.makeChild(rs); task.setPendingCount(1); if (forkRight) { forkRight = false; rs = ls; task = leftChild; taskToFork = rightChild; } else { forkRight = true; task = rightChild; taskToFork = leftChild; } taskToFork.fork(); sizeEstimate = rs.estimateSize(); } task.setLocalResult(result); task.tryComplete(); }
@Test public void iteratesAllRemainingEventsForwardWithoutTryAdvanceCall() { final String stream = generateStreamName(); List<EventData> events = newTestEvents(19); 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<>(); spliterator.forEachRemaining(result::add); assertFalse(spliterator.tryAdvance(result::add)); spliterator.forEachRemaining(e -> fail("Should be no more elements remaining")); assertNull(spliterator.trySplit()); assertEquals(19, result.size()); assertThat(recordedEventsFrom(result), containsInOrder(events)); }
@Override public Void call() throws Exception { String baseUrl = PropertyHandler.getInstance().getValue("baseUrl"); String urlPageSuffix = PropertyHandler.getInstance().getValue("urlPageSuffix"); String numberOfPages = PropertyHandler.getInstance().getValue("numberOfPages"); String tagToParse = PropertyHandler.getInstance().getValue("tagToParse"); assert (numberOfPages.matches("^-?\\d+$")); // make sure someone supplied only numbers Elements headlines = null; int goal = Integer.parseInt(numberOfPages); try { for (int i = 0; i < goal; i++) { String url = baseUrl + urlPageSuffix + i; headlines = fetchContent(url, tagToParse); Spliterator<Element> elementSpliterator = headlines.spliterator().trySplit(); elementSpliterator.forEachRemaining( headline -> { try { if (!headline.text().toLowerCase().contains("permalink")) { logger.info("Produced: " + headline); queue.put(headline); } } catch (InterruptedException e) { e.printStackTrace(); } }); Thread.sleep(1000); } this.queue.continueProducing = Boolean.FALSE; System.out.println("Producer finished its job; terminating."); } catch (Exception ex) { ex.printStackTrace(); } return null; }
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 iteratesAndSplitsEventsForward() { final String stream = generateStreamName(); List<EventData> events = newTestEvents(17); eventstore.appendToStream(stream, ExpectedVersion.NO_STREAM, events).join(); Spliterator<ResolvedEvent> spliterator = new StreamEventsSpliterator( StreamPosition.START, i -> eventstore.readStreamEventsForward(stream, i, 5, 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(17, result.size()); assertThat(recordedEventsFrom(result), containsInOrder(events)); }
@Override public int characteristics() { return source.characteristics() & (CONCURRENT | IMMUTABLE | ORDERED); }
@Override public long estimateSize() { return source.estimateSize(); }