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

io.datakernel.stream.StreamProducers Maven / Gradle / Ivy

Go to download

Composable asynchronous/reactive streams with powerful data processing capabilities.

The newest version!
/*
 * Copyright (C) 2015 SoftIndex LLC.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.datakernel.stream;

import io.datakernel.async.*;
import io.datakernel.eventloop.Eventloop;

import java.util.Arrays;
import java.util.Iterator;

import static com.google.common.base.Preconditions.checkNotNull;
import static io.datakernel.async.AsyncIterators.asyncIteratorOfIterator;

public class StreamProducers {
	private StreamProducers() {
	}

	/**
	 * Returns producer which doing nothing - not sending any data and not closing itself.
	 *
	 * @param eventloop event loop in which will run it
	 */
	public static  StreamProducer idle(Eventloop eventloop) {
		return new Idle<>(eventloop);
	}

	/**
	 * Returns producer which closes itself
	 *
	 * @param eventloop event loop in which will run it
	 * @param        type of item for send
	 */
	public static  StreamProducer closing(Eventloop eventloop) {
		return new EndOfStream<>(eventloop);
	}

	public static  StreamProducer closingWithError(Eventloop eventloop, Exception e) {
		return new ClosingWithError<>(eventloop, e);
	}

	/**
	 * Creates producer which sends value and closes itself
	 *
	 * @param eventloop event loop in which will run it
	 * @param value     value for sending
	 * @param        type of value
	 */
	public static  StreamProducer ofValue(Eventloop eventloop, final T value) {
		return new OfValue<>(eventloop, value);
	}

	/**
	 * Creates producer which sends value and closes itself
	 *
	 * @param eventloop event loop in which will run it
	 * @param value     value for sending
	 * @param close     if producer is closed
	 * @param        type of value
	 */
	public static  StreamProducer ofValue(Eventloop eventloop, final T value, boolean close) {
		return new OfValue<>(eventloop, value, close);
	}

	/**
	 * Returns new {@link OfIterator} which sends items from iterator
	 *
	 * @param eventloop event loop in which will run it
	 * @param iterator  iterator with items for sending
	 * @param        type of item
	 */
	public static  StreamProducer ofIterator(Eventloop eventloop, Iterator iterator) {
		return new OfIterator<>(eventloop, iterator);
	}

	/**
	 * Returns new {@link OfIterator} which sends items from {@code iterable}
	 *
	 * @param eventloop event loop in which will run it
	 * @param iterable  iterable with items for sending
	 * @param        type of item
	 */
	public static  StreamProducer ofIterable(Eventloop eventloop, Iterable iterable) {
		return new OfIterator<>(eventloop, iterable.iterator());
	}

	/**
	 * Represents asynchronously resolving producer.
	 *
	 * @param eventloop      event loop in which will run it
	 * @param producerGetter getter with producer
	 * @param             type of output data
	 */
	public static  StreamProducer asynchronouslyResolving(final Eventloop eventloop, final AsyncGetter> producerGetter) {
		final StreamForwarder forwarder = new StreamForwarder<>(eventloop);
		eventloop.post(new Runnable() {
			@Override
			public void run() {
				producerGetter.get(new ResultCallback>() {
					@Override
					public void onResult(StreamProducer actualProducer) {
						actualProducer.streamTo(forwarder);
					}

					@Override
					public void onException(Exception exception) {
						new ClosingWithError(eventloop, exception).streamTo(forwarder);
					}
				});
			}
		});
		return forwarder;
	}

	/**
	 * Returns {@link StreamProducerConcat} with producers from asyncIterator  which will stream to this
	 *
	 * @param eventloop     event loop in which will run it
	 * @param asyncIterator iterator with producers
	 * @param            type of output data
	 */
	public static  StreamProducer concat(Eventloop eventloop, AsyncIterator> asyncIterator) {
		return new StreamProducerConcat<>(eventloop, asyncIterator);
	}

	/**
	 * Returns  {@link StreamProducerConcat} with producers from AsyncIterable  which will stream to this
	 *
	 * @param eventloop     event loop in which will run it
	 * @param asyncIterator iterable with producers
	 * @param            type of output data
	 */
	public static  StreamProducer concat(Eventloop eventloop, AsyncIterable> asyncIterator) {
		return concat(eventloop, asyncIterator.asyncIterator());
	}

	/**
	 * Returns  {@link StreamProducerConcat} with producers from Iterator  which will stream to this
	 *
	 * @param eventloop event loop in which will run it
	 * @param iterator  iterator with producers
	 * @param        type of output data
	 */
	public static  StreamProducer concat(Eventloop eventloop, Iterator> iterator) {
		return concat(eventloop, asyncIteratorOfIterator(iterator));
	}

	/**
	 * Returns  {@link StreamProducerConcat} with producers from Iterable which will stream to this
	 *
	 * @param eventloop event loop in which will run it
	 * @param iterable  iterator with producers
	 * @param        type of output data
	 */
	public static  StreamProducer concat(Eventloop eventloop, Iterable> iterable) {
		return concat(eventloop, iterable.iterator());
	}

	@SafeVarargs
	public static  StreamProducer concat(Eventloop eventloop, StreamProducer... producers) {
		return concat(eventloop, Arrays.asList(producers));
	}

	/**
	 * Represent a {@link AbstractStreamProducer} which once sends to consumer end of stream.
	 *
	 * @param 
	 */
	public static class EndOfStream extends AbstractStreamProducer {
		public EndOfStream(Eventloop eventloop) {
			super(eventloop);
		}

		@Override
		protected void onProducerStarted() {
			sendEndOfStream();
		}
	}

	/**
	 * Represent producer which sends specified exception to consumer.
	 *
	 * @param 
	 */
	public static class ClosingWithError extends AbstractStreamProducer {
		private final Exception exception;

		public ClosingWithError(Eventloop eventloop, Exception exception) {
			super(eventloop);
			this.exception = exception;
		}

		@Override
		protected void onProducerStarted() {
			closeWithError(exception);
		}
	}

	public static class Idle extends AbstractStreamProducer {
		public Idle(Eventloop eventloop) {
			super(eventloop);
		}
	}

	/**
	 * Represents a {@link AbstractStreamProducer} which will send all values from iterator.
	 *
	 * @param  type of output data
	 */
	public static class OfIterator extends AbstractStreamProducer {
		private final Iterator iterator;
		private boolean sendEndOfStream = true;

		/**
		 * Creates a new instance of  StreamProducerOfIterator
		 *
		 * @param eventloop event loop where producer will run
		 * @param iterator  iterator with object which need to send
		 */
		public OfIterator(Eventloop eventloop, Iterator iterator) {
			this(eventloop, iterator, true);
		}

		public OfIterator(Eventloop eventloop, Iterator iterator, boolean sendEndOfStream) {
			super(eventloop);
			this.iterator = checkNotNull(iterator);
			this.sendEndOfStream = sendEndOfStream;
		}

		@Override
		protected void doProduce() {
			for (; ; ) {
				if (!iterator.hasNext())
					break;
				if (status != READY)
					return;
				T item = iterator.next();
				send(item);
			}
			if (sendEndOfStream)
				sendEndOfStream();
		}

		@Override
		protected void onProducerStarted() {
			produce();
		}

		@Override
		protected void onResumed() {
			resumeProduce();
		}
	}

	/**
	 * It is {@link AbstractStreamProducer} which sends specified single value to its consumer, followed by end-of-stream
	 *
	 * @param  type of value for send
	 */
	public static class OfValue extends AbstractStreamProducer {
		private final T value;
		private final boolean sendEndOfStream;

		/**
		 * Creates producer which sends value and closes itself
		 *
		 * @param eventloop event loop  in which this producer will run
		 * @param value     value for sending
		 */
		public OfValue(Eventloop eventloop, T value) {
			this(eventloop, value, true);
		}

		/**
		 * Creates producer which sends value and optionally closes itself
		 *
		 * @param eventloop       event loop  in which this producer will run
		 * @param value           value for sending
		 * @param sendEndOfStream if producer is closed
		 */
		public OfValue(Eventloop eventloop, T value, boolean sendEndOfStream) {
			super(eventloop);
			this.value = value;
			this.sendEndOfStream = sendEndOfStream;
		}

		@Override
		protected void onProducerStarted() {
			send(value);
			if (sendEndOfStream)
				sendEndOfStream();
		}
	}

	/**
	 * Represents {@link AbstractStreamTransformer_1_1}, which created with iterator with {@link AbstractStreamProducer}
	 * which will stream to this
	 *
	 * @param  type of received data
	 */
	public static class StreamProducerConcat extends StreamProducerDecorator {
		private final AsyncIterator> iterator;
		private final StreamProducerSwitcher switcher;

		public StreamProducerConcat(Eventloop eventloop, AsyncIterator> iterator) {
			super(eventloop);
			this.iterator = checkNotNull(iterator);
			this.switcher = new StreamProducerSwitcher<>(eventloop);
			decorate(switcher);
		}

		/**
		 * This method is called if consumer was changed for changing consumer status. It begins streaming
		 * from producers from iterator
		 */
		@Override
		protected void onProducerStarted() {
			doNext();
		}

		private void doNext() {
			eventloop.post(new Runnable() {
				@Override
				public void run() {
					iterator.next(new IteratorCallback>() {
						@Override
						public void onNext(StreamProducer actualProducer) {
							switcher.switchProducerTo(new StreamProducerDecorator(eventloop, actualProducer) {
								@Override
								public void onEndOfStream() {
									doNext();
								}
							});
						}

						@Override
						public void onEnd() {
							switcher.switchProducerTo(new EndOfStream(eventloop));
						}

						@Override
						public void onException(Exception e) {
							switcher.switchProducerTo(new ClosingWithError(eventloop, e));
						}
					});
				}
			});
		}

	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy