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

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

package net.pincette.rs;

import static java.util.Arrays.asList;
import static net.pincette.rs.Serializer.dispatch;
import static net.pincette.rs.Util.empty;

import java.util.List;
import java.util.concurrent.Flow.Publisher;
import java.util.concurrent.Flow.Subscriber;

/**
 * Concatenates multiple publishers of the same type to form one publisher that completes when the
 * last given publisher completes.
 *
 * @param  the value type.
 * @author Werner Donn\u00e9
 * @since 3.0
 */
public class Concat implements Publisher {
  private final Chainer chainer = new Chainer();
  private final List> publishers;

  public Concat(final List> publishers) {
    this.publishers = publishers;
  }

  public static  Publisher of(final List> publishers) {
    return new Concat<>(publishers);
  }

  @SafeVarargs
  public static  Publisher of(final Publisher... publishers) {
    return new Concat<>(asList(publishers));
  }

  @Override
  public void subscribe(final Subscriber subscriber) {
    if (publishers.isEmpty()) {
      final Publisher empty = empty();

      empty.subscribe(subscriber);
    } else {
      publishers.get(0).subscribe(chainer);
      chainer.subscribe(subscriber);
    }
  }

  private class Chainer extends ProcessorBase {
    private int position;
    private long requested;

    @Override
    public void cancel() {
      // Don't cancel when a new subscription is taken, because then this dynamic subscription
      // switching is no longer transparent for the publishers.
    }

    @Override
    protected void emit(final long number) {
      dispatch(
          () -> {
            requested += number;
            more();
          });
    }

    private void more() {
      if (requested > 0) {
        subscription.request(1);
      }
    }

    @Override
    public void onComplete() {
      dispatch(
          () -> {
            if (position < publishers.size() - 1) {
              publishers.get(++position).subscribe(this);
              more();
            } else {
              super.onComplete();
            }
          });
    }

    @Override
    public void onNext(final T item) {
      dispatch(
          () -> {
            --requested;
            subscriber.onNext(item);
            more();
          });
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy