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

net.pincette.rs.Chain Maven / Gradle / Ivy

package net.pincette.rs;

import java.time.Duration;
import java.util.List;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Flow.Processor;
import java.util.concurrent.Flow.Publisher;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * Chains processors after the initial publisher.
 *
 * @param  the object type of the initial publisher.
 * @author Werner Donné
 * @since 1.0
 */
public class Chain {
  private final Publisher publisher;

  private Chain(final Publisher publisher) {
    this.publisher = publisher;
  }

  /**
   * Creates a chain with the initial publisher.
   *
   * @param publisher the initial publisher.
   * @param  the object type of the initial publisher.
   * @return The chain.
   * @since 1.0
   */
  public static  Chain with(final Publisher publisher) {
    return new Chain<>(publisher);
  }

  /**
   * Appends value to the stream.
   *
   * @param value the value to emit. It may be null.
   * @return the new stream.
   * @since 1.0
   */
  public Chain after(final T value) {
    return map(After.after(value));
  }

  /**
   * Asks the upstream for more elements if it hasn't received any before the timeout, until the
   * stream completes.
   *
   * @since 3.0
   */
  public Chain askForever(final Duration timeout) {
    return map(AskForever.askForever(timeout));
  }

  /**
   * Appends the result of value to the stream.
   *
   * @param value the function that produces the value to emit. It may not be null.
   * @return the new stream.
   * @since 1.2.1
   */
  public Chain after(final Supplier value) {
    return map(After.after(value));
  }

  /**
   * Puts value before the stream.
   *
   * @param value the value to emit. It may be null.
   * @return the new stream.
   * @since 1.0
   */
  public Chain before(final T value) {
    return map(Before.before(value));
  }

  /**
   * Puts the result of value before the stream.
   *
   * @param value the function that produces the value to emit. It may not be null.
   * @return the new stream.
   * @since 1.2.1
   */
  public Chain before(final Supplier value) {
    return map(Before.before(value));
  }

  /**
   * Buffers a number of values. It always requests the number of values from the publisher that
   * equals the buffer size.
   *
   * @param size the buffer size.
   * @return the new stream.
   * @since 1.7
   */
  public Chain buffer(final int size) {
    return map(Buffer.buffer(size));
  }

  /**
   * Buffers a number of values. It always requests the number of values from the publisher that
   * equals the buffer size.
   *
   * @param size the buffer size.
   * @param timeout the time after which the buffer requests a new value, even if it hasn't received
   *     enough elements yet.
   * @return the new stream.
   * @since 3.0.2
   */
  public Chain buffer(final int size, final Duration timeout) {
    return map(Buffer.buffer(size, timeout));
  }

  /**
   * When the down stream requests more messages this indicates all messages it has received were
   * processed correctly. This is a moment to perform a commit with a function that receives the
   * list of uncommitted messages.
   *
   * @param commit the commit function. New messages are only requested when the completion stage
   *     returns true.
   * @return A new chain with the same object type.
   * @since 3.0
   */
  public Chain commit(final Function, CompletionStage> commit) {
    return map(Commit.commit(commit));
  }

  /**
   * Appends a processor that filters objects using the predicate function.
   *
   * @param predicate the predicate function.
   * @return A new chain with the same object type.
   * @since 1.0
   */
  public Chain filter(final Predicate predicate) {
    return map(Filter.filter(predicate));
  }

  /**
   * Appends a processor that only emits the first value it receives.
   *
   * @return A new chain with the same object type.
   * @since 1.4
   */
  public Chain first() {
    return map(First.first());
  }

  /**
   * Appends a processor that emits the elements from the generated publisher individually.
   *
   * @param function the function that generates the publisher.
   * @return A new chain with the same object type.
   * @since 3.0
   */
  public  Chain flatMap(final Function> function) {
    return map(Flatten.flatMap(function));
  }

  /**
   * Appends a processor that emits the elements from the generated list individually.
   *
   * @param function the function that generates the list.
   * @return A new chain with the same object type.
   * @since 3.0
   */
  public  Chain flatMapList(final Function> function) {
    return map(FlattenList.flatMapList(function));
  }

  /**
   * Returns the publisher of the chain.
   *
   * @return The publisher.
   * @since 1.0
   */
  public Publisher get() {
    return publisher;
  }

  /**
   * Appends a processor that doesn't emit the head of a stream, but instead gives it to a function.
   *
   * @param head the function that receives the first value.
   * @param tail the function that receives all other values.
   * @param  the object type for the new chain.
   * @return The new chain.
   * @since 3.0
   */
  public  Chain headTail(final Consumer head, final Function tail) {
    return map(HeadTail.headTail(head, tail));
  }

  /**
   * Appends a processor that only emits the last value it receives.
   *
   * @return A new chain with the same object type.
   * @since 1.4
   */
  public Chain last() {
    return map(Last.last());
  }

  /**
   * Appends processor to the chain.
   *
   * @param processor the given processor.
   * @param  the object type for the new chain.
   * @return The new chain.
   * @since 1.0
   */
  public  Chain map(final Processor processor) {
    publisher.subscribe(processor);

    return new Chain<>(processor);
  }

  /**
   * Appends a processor with the mapping function, which transforms the objects.
   *
   * @param function the mapping function.
   * @param  the object type for the new chain.
   * @return The new chain.
   * @since 1.0
   */
  public  Chain map(final Function function) {
    return map(Mapper.map(function));
  }

  /**
   * Appends a processor with the mapping function, which transforms the objects. The completion
   * stages are processed in the order of the stream, which completes only after the last stage is
   * completed. The functions are executed in sequence, which means a function call starts only
   * after the previous completion stage has completed.
   *
   * @param function the mapping function.
   * @param  the object type for the new chain.
   * @return The new chain.
   * @since 3.1.2
   */
  public  Chain mapAsyncSequential(final Function> function) {
    return map(Async.mapAsyncSequential(function));
  }

  /**
   * Appends a processor with the mapping function, which transforms the objects. The completion
   * stages are processed in the order of the stream, which completes only after the last stage is
   * completed. This means the functions may start in parallel, but the completions are emitted in
   * the proper order.
   *
   * @param function the mapping function.
   * @param  the object type for the new chain.
   * @return The new chain.
   * @since 1.5.1
   */
  public  Chain mapAsync(final Function> function) {
    return map(Async.mapAsync(function));
  }

  /**
   * Appends a processor with the mapping function, which transforms the objects. The functions
   * stages are executed in the order of the stream, which completes only after the last stage is
   * completed. A function call will also receive the result of the previous call, which is 
   * null for the first call.
   *
   * @param function the mapping function.
   * @param  the object type for the new chain.
   * @return The new chain.
   * @since 3.0
   */
  public  Chain mapAsync(final BiFunction> function) {
    return map(AsyncDepend.mapAsync(function));
  }

  /**
   * Appends a processor that filters objects using negation of the predicate function.
   *
   * @param predicate the predicate function.
   * @return A new chain with the same object type.
   * @since 1.0
   */
  public Chain notFilter(final Predicate predicate) {
    return map(NotFilter.notFilter(predicate));
  }

  /**
   * Buffers a number of values. It always requests the number of values from the publisher that
   * equals the buffer size. It emits the buffered values as a list.
   *
   * @param size the buffer size.
   * @return the new stream.
   * @since 2.0
   */
  public Chain> per(final int size) {
    return map(Per.per(size));
  }

  /**
   * Buffers a number of values. It always requests the number of values from the publisher that
   * equals the buffer size. It emits the buffered values as a list.
   *
   * @param size the buffer size.
   * @param timeout the timeout after which the buffer is flushed. It should be positive.
   * @return the new stream.
   * @since 3.0.2
   */
  public Chain> per(final int size, final Duration timeout) {
    return map(Per.per(size, timeout));
  }

  /**
   * Buffers a number of values. It always requests the number of values from the publisher that
   * equals the buffer size. It emits the buffered values as a list.
   *
   * @param size the buffer size.
   * @param timeout the timeout after which the buffer is flushed. It should be positive.
   * @param requestTimeout the time after which an additional element is requested, even if the
   *     upstream publisher hasn't sent all requested elements yet. This provides the opportunity to
   *     the publisher to complete properly when it has fewer elements left than the buffer size. It
   *     may be null.
   * @return the new stream.
   * @since 3.0.2
   */
  public Chain> per(final int size, final Duration timeout, final Duration requestTimeout) {
    return map(Per.per(size, timeout, requestTimeout));
  }

  /**
   * Puts value between the emitted values.
   *
   * @param value the value to emit between the emitted values. It may be null.
   * @return The new stream.
   * @since 1.0
   */
  public Chain separate(final T value) {
    return map(Separator.separator(value));
  }

  /**
   * Puts the result of value between the emitted values.
   *
   * @param value the function that produces the value to emit between the emitted values. It may
   *     not be null.
   * @return The new stream.
   * @since 1.2.1
   */
  public Chain separate(final Supplier value) {
    return map(Separator.separator(value));
  }

  /**
   * When the upstream or downstream could cause races, this processor serializes everything with a
   * thread and a blocking queue.
   *
   * @since 3.0
   */
  public Chain split() {
    return map(Split.split());
  }

  /**
   * Appends a processor that emits values until it receives one that matches predicate
   * , which is also emitted.
   *
   * @param predicate the predicate function.
   * @return A new chain with the same object type.
   * @since 1.4
   */
  public Chain until(final Predicate predicate) {
    return map(Until.until(predicate));
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy