/* * 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.eventloop.Eventloop; import java.util.ArrayList; import java.util.List; import static com.google.common.base.Preconditions.checkNotNull; import static java.util.Collections.unmodifiableList; /** * Represents {@link AbstractStreamProducer} with few {@link AbstractStreamConsumer}. * * @param <O> type of sending items */ @SuppressWarnings("unchecked") public abstract class AbstractStreamTransformer_N_1<O> implements HasOutput<O>, HasInputs { protected final Eventloop eventloop; protected final List<AbstractInputConsumer<?>> inputConsumers = new ArrayList<>(); protected AbstractOutputProducer outputProducer; protected int countEndOfStreams = 0; protected abstract class AbstractInputConsumer<I> extends AbstractStreamConsumer<I> { protected int index; public AbstractInputConsumer() { super(AbstractStreamTransformer_N_1.this.eventloop); } @Override protected final void onStarted() { onUpstreamStarted(); } protected void onUpstreamStarted() { } @Override protected final void onEndOfStream() { countEndOfStreams++; onUpstreamEndOfStream(); } protected abstract void onUpstreamEndOfStream(); @Override protected final void onError(Exception e) { countEndOfStreams++; for (AbstractInputConsumer<?> input : inputConsumers) { if (input != this) { input.closeWithError(e); } } outputProducer.closeWithError(e); } } protected abstract class AbstractOutputProducer extends AbstractStreamProducer<O> { public AbstractOutputProducer() { super(AbstractStreamTransformer_N_1.this.eventloop); } @Override protected final void onDataReceiverChanged() { for (AbstractInputConsumer<?> input : inputConsumers) { if (input.getUpstream() != null) { input.getUpstream().bindDataReceiver(); } } } @Override protected final void onStarted() { for (AbstractInputConsumer<?> input : inputConsumers) { if (input.getUpstream() != null) { input.getUpstream().bindDataReceiver(); } } onDownstreamStarted(); } protected void onDownstreamStarted() { } @Override protected final void onError(Exception e) { for (AbstractInputConsumer<?> input : inputConsumers) { input.closeWithError(e); } } @Override protected final void onSuspended() { onDownstreamSuspended(); } protected abstract void onDownstreamSuspended(); @Override protected final void onResumed() { onDownstreamResumed(); } protected abstract void onDownstreamResumed(); } /** * Creates a new instance of this object * * @param eventloop event loop in which this producer will run */ public AbstractStreamTransformer_N_1(Eventloop eventloop) { this.eventloop = eventloop; } /** * Adds a new stream consumer to this producer * * @param <T> type of stream consumer * @param upstreamConsumer stream consumer events handler */ protected <T> StreamConsumer<T> addInput(final AbstractInputConsumer<T> upstreamConsumer) { checkNotNull(upstreamConsumer); upstreamConsumer.index = inputConsumers.size(); inputConsumers.add(upstreamConsumer); return upstreamConsumer; } protected final void suspendAllUpstreams() { for (AbstractInputConsumer<?> upstreamConsumer : inputConsumers) { upstreamConsumer.suspend(); } } protected final void resumeAllUpstreams() { for (AbstractInputConsumer<?> upstreamConsumer : inputConsumers) { upstreamConsumer.resume(); } } protected boolean allUpstreamsEndOfStream() { return countEndOfStreams == inputConsumers.size(); } @Override public StreamProducer<O> getOutput() { return outputProducer; } @Override public final List<? extends StreamConsumer<?>> getInputs() { return unmodifiableList(inputConsumers); } @Override public StreamConsumer<?> getInput(int index) { return inputConsumers.get(index); } }