org.reactfx.util.NotificationAccumulator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of richtextfx Show documentation
Show all versions of richtextfx Show documentation
FX-Text-Area for formatted text and other special effects.
package org.reactfx.util;
import java.util.Deque;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import org.reactfx.collection.ListModificationSequence;
import org.reactfx.collection.LiveList;
import org.reactfx.collection.LiveList.Observer;
import org.reactfx.collection.QuasiListChange;
/**
* @param observer type
* @param type of produced values
* @param type of accumulated value
*/
public interface NotificationAccumulator {
static NotificationAccumulator, T, A> accumulativeStreamNotifications(
Function super A, AccumulatorSize> size,
Function super A, ? extends T> head,
Function super A, ? extends A> tail,
Function super T, ? extends A> initialTransformation,
BiFunction super A, ? super T, ? extends A> reduction) {
return new AccumulativeStreamNotifications<>(
size, head, tail, initialTransformation, reduction);
}
static NotificationAccumulator, T, Deque> queuingStreamNotifications() {
return new QueuingStreamNotifications<>();
}
static NotificationAccumulator, T, T> reducingStreamNotifications(BinaryOperator reduction) {
return new ReducingStreamNotifications<>(reduction);
}
static NotificationAccumulator, T, T> retainLatestStreamNotifications() {
return new RetainLatestStreamNotifications<>();
}
static NotificationAccumulator, T, T> retainOldestValNotifications() {
return new RetailOldestValNotifications<>();
}
static NotificationAccumulator, T, T> nonAccumulativeStreamNotifications() {
return new NonAccumulativeStreamNotifications<>();
}
static NotificationAccumulator, QuasiListChange extends E>, ListModificationSequence> listNotifications() {
return new ListNotifications<>();
}
/* Interface methods */
boolean isEmpty();
Runnable takeOne();
void addAll(Iterator observers, V value);
void clear();
AccumulationFacility getAccumulationFacility();
}
abstract class NotificationAccumulatorBase
implements NotificationAccumulator, AccumulationFacility {
private AccuMap accuMap = AccuMap.empty();
protected abstract AccumulatorSize size(O observer, A accumulatedValue);
protected abstract Runnable head(O observer, A accumulatedValue);
protected abstract A tail(O observer, A accumulatedValue);
@Override
public AccumulationFacility getAccumulationFacility() {
return this;
}
@Override
public boolean isEmpty() {
return accuMap.isEmpty();
}
@Override
public Runnable takeOne() {
Tuple2 t = accuMap.peek(this);
switch(t.map(this::size)) {
case ZERO:
accuMap = accuMap.dropPeeked();
return () -> {};
case ONE:
accuMap = accuMap.dropPeeked();
return t.map(this::head);
case MANY:
Runnable notification = t.map(this::head);
A newAccumulatedValue = t.map(this::tail);
accuMap = accuMap.updatePeeked(newAccumulatedValue);
return notification;
default:
throw new AssertionError("Unreachable code");
}
}
@Override
public void addAll(Iterator keys, V value) {
accuMap = accuMap.addAll(keys, value, this);
}
@Override
public void clear() {
accuMap = AccuMap.empty();
}
}
/* ******************** *
* Non-recursive stream *
* ******************** */
final class NonAccumulativeStreamNotifications
extends NotificationAccumulatorBase, T, T>
implements AccumulationFacility.NoAccumulation {
@Override
protected AccumulatorSize size(
Consumer super T> observer,
T accumulatedValue) {
return AccumulatorSize.ONE;
}
@Override
protected Runnable head(Consumer super T> observer, T accumulatedValue) {
return () -> observer.accept(accumulatedValue);
}
@Override
protected T tail(Consumer super T> observer, T accumulatedValue) {
throw new NoSuchElementException();
}
}
/* ******************* *
* Accumulative stream *
* ******************* */
final class AccumulativeStreamNotifications
extends NotificationAccumulatorBase, T, A> {
private final Function super A, AccumulatorSize> size;
private final Function super A, ? extends T> head;
private final Function super A, ? extends A> tail;
private final Function super T, ? extends A> initialTransformation;
private final BiFunction super A, ? super T, ? extends A> reduction;
AccumulativeStreamNotifications(
Function super A, AccumulatorSize> size,
Function super A, ? extends T> head,
Function super A, ? extends A> tail,
Function super T, ? extends A> initialTransformation,
BiFunction super A, ? super T, ? extends A> reduction) {
this.size = size;
this.head = head;
this.tail = tail;
this.initialTransformation = initialTransformation;
this.reduction = reduction;
}
@Override
protected AccumulatorSize size(Consumer super T> observer, A accumulatedValue) {
return size.apply(accumulatedValue);
}
@Override
protected Runnable head(Consumer super T> observer, A accumulatedValue) {
T event = head.apply(accumulatedValue);
return () -> observer.accept(event);
}
@Override
protected A tail(Consumer super T> observer, A accumulatedValue) {
return tail.apply( accumulatedValue);
}
@Override
public A initialAccumulator(T value) {
return initialTransformation.apply(value);
}
@Override
public A reduce(A accum, T value) {
return reduction.apply(accum, value);
}
}
/* ************** *
* Queuing stream *
* ************** */
final class QueuingStreamNotifications
extends NotificationAccumulatorBase, T, Deque>
implements AccumulationFacility.Queuing {
@Override
protected AccumulatorSize size(
Consumer super T> observer,
Deque accumulatedValue) {
return AccumulatorSize.fromInt(accumulatedValue.size());
}
@Override
protected Runnable head(
Consumer super T> observer,
Deque accumulatedValue) {
T t = accumulatedValue.getFirst();
return () -> observer.accept(t);
}
@Override
protected Deque tail(
Consumer super T> observer,
Deque accumulatedValue) {
accumulatedValue.removeFirst();
return accumulatedValue;
}
}
/* *************** *
* Reducing stream *
* *************** */
abstract class AbstractReducingStreamNotifications
extends NotificationAccumulatorBase, T, T>
implements AccumulationFacility.HomotypicAccumulation {
@Override
protected final AccumulatorSize size(
Consumer super T> observer,
T accumulatedValue) {
return AccumulatorSize.ONE;
}
@Override
protected final Runnable head(Consumer super T> observer, T accumulatedValue) {
return () -> observer.accept(accumulatedValue);
}
@Override
protected final T tail(Consumer super T> observer, T accumulatedValue) {
throw new NoSuchElementException();
}
}
final class ReducingStreamNotifications
extends AbstractReducingStreamNotifications {
private final BinaryOperator reduction;
ReducingStreamNotifications(BinaryOperator reduction) {
this.reduction = reduction;
}
@Override
public T reduce(T accum, T value) {
return reduction.apply(accum, value);
}
}
/* ******************** *
* Retain Latest stream *
* ******************** */
final class RetainLatestStreamNotifications
extends AbstractReducingStreamNotifications
implements AccumulationFacility.RetainLatest {}
/* ***************** *
* Retain Oldest Val *
* ***************** */
final class RetailOldestValNotifications
extends AbstractReducingStreamNotifications
implements AccumulationFacility.RetainOldest {}
/* ************************ *
* List change accumulation *
* ************************ */
final class ListNotifications
extends NotificationAccumulatorBase, QuasiListChange extends E>, ListModificationSequence>
implements AccumulationFacility.ListChangeAccumulation {
@Override
protected AccumulatorSize size(
Observer super E, ?> observer,
ListModificationSequence accumulatedValue) {
return observer.sizeOf(accumulatedValue);
}
@Override
protected Runnable head(
Observer super E, ?> observer,
ListModificationSequence mods) {
return takeHead(observer, mods);
}
private final Runnable takeHead(
Observer super E, O> observer,
ListModificationSequence mods) {
O h = observer.headOf(mods);
return () -> observer.onChange(h);
}
@Override
protected ListModificationSequence tail(
Observer super E, ?> observer,
ListModificationSequence mods) {
return observer.tailOf(mods);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy