All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.thorbenkuck.network.stream.AbstractEventStream Maven / Gradle / Ivy

The newest version!
package com.github.thorbenkuck.network.stream;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;

public abstract class AbstractEventStream implements ManagedEventStream {

	private final List> subscriptions = new ArrayList<>();
	private final List buffer = new ArrayList<>();
	private final EventStreamSubscriptionReference reference = new EventStreamSubscriptionReference();
	private boolean paused = false;
	private boolean disabled = false;

	private void publish(T t) {
		List> copy = new ArrayList<>(subscriptions);
		dispatch(copy, t);
	}

	protected abstract void dispatch(List> subscriptions, T t);

	protected void newSubscription(NotifiableSubscription subscription) {
	}

	protected void deletedSubscription(NotifiableSubscription subscription) {
	}

	private void removeSubscription(NotifiableSubscription subscription) {
		subscriptions.remove(subscription);
		deletedSubscription(subscription);
	}

	private void addSubscription(NotifiableSubscription subscription) {
		subscriptions.add(subscription);
		newSubscription(subscription);
	}

	@Override
	public void clearSubscribers() {
		ArrayList> notifiableSubscriptions = new ArrayList<>(subscriptions);
		notifiableSubscriptions.forEach(Subscription::cancel);
	}

	@Override
	public void pushError(Throwable throwable) {
		List> copy = new ArrayList<>(subscriptions);
		copy.forEach(subscription -> subscription.notify(throwable));
		copy.clear();
	}

	@Override
	public void unPause() {
		paused = false;
		buffer.forEach(this::publish);
		buffer.clear();
	}

	@Override
	public void pause() {
		paused = true;
	}

	@Override
	public void close() {
		List> copy = new ArrayList<>(subscriptions);

		pause();
		setDisabled(true);
		copy.forEach(Subscription::cancel);
		subscriptions.clear();
		buffer.clear();
	}

	@Override
	public boolean isPaused() {
		return paused;
	}

	@Override
	public void push(T t) {
		if (isDisabled()) {
			return;
		}

		if (isPaused()) {
			buffer.add(t);
		} else {
			publish(t);
		}
	}

	@Override
	public Subscription subscribe(Subscriber subscriber) {
		NotifiableSubscription subscription = new SimpleSubscription<>(subscriber, reference);
		addSubscription(subscription);
		subscriber.onSubscribe();
		return subscription;
	}

	@Override
	public  EventStream pipe(Transformation transformation, Supplier> eventStreamFunction) {
		DataStream eventStream = eventStreamFunction.get();
		subscribe(t -> {
			try {
				S s = transformation.apply(t);
				eventStream.push(s);
			} catch (Exception e) {
				eventStream.pushError(e);
			}
		});
		return eventStream;
	}

	@Override
	public List> getSubscriptions() {
		return Collections.unmodifiableList(subscriptions);
	}

	@Override
	public boolean isDisabled() {
		return disabled;
	}

	@Override
	public void setDisabled(boolean disabled) {
		this.disabled = disabled;
	}

	private final class EventStreamSubscriptionReference implements SubscriptionReference> {

		@Override
		public boolean contains(NotifiableSubscription subscription) {
			return subscriptions.contains(subscription);
		}

		@Override
		public void remove(NotifiableSubscription subscription) {
			removeSubscription(subscription);
		}
	}
}