/* * 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 io.datakernel.jmx.ExceptionStats; import io.datakernel.jmx.JmxAttribute; import io.datakernel.jmx.JmxReducers.JmxReducerSum; import io.datakernel.stream.processor.StreamTransformer; /** * Represent {@link StreamProducer} and {@link StreamConsumer} in the one object. * This object can receive and send streams of data. * * @param <I> type of input data for consumer * @param <O> type of output data of producer */ @SuppressWarnings("unchecked") public abstract class AbstractStreamTransformer_1_1<I, O> implements StreamTransformer<I, O> { protected final Eventloop eventloop; protected Object tag; protected Inspector inspector; public interface Inspector { void onStarted(); void onEndOfStream(); void onError(Exception e); void onSuspended(); void onResumed(); } public static class JmxInspector implements Inspector { private int started; private int endOfStream; private ExceptionStats errors = ExceptionStats.create(); private long suspended; private long resumed; @Override public void onStarted() { started++; } @Override public void onEndOfStream() { endOfStream++; } @Override public void onError(Exception e) { errors.recordException(e); } @Override public void onSuspended() { suspended++; } @Override public void onResumed() { resumed++; } @JmxAttribute(reducer = JmxReducerSum.class) public int getStarted() { return started; } @JmxAttribute(reducer = JmxReducerSum.class) public int getEndOfStream() { return endOfStream; } @JmxAttribute public ExceptionStats getErrors() { return errors; } @JmxAttribute(reducer = JmxReducerSum.class) public long getSuspended() { return suspended; } @JmxAttribute(reducer = JmxReducerSum.class) public long getResumed() { return resumed; } } protected abstract class AbstractInputConsumer extends AbstractStreamConsumer<I> { protected StreamDataReceiver<O> downstreamDataReceiver; public AbstractInputConsumer() { super(AbstractStreamTransformer_1_1.this.eventloop); } @Override protected final void onStarted() { if (inspector != null) inspector.onStarted(); onUpstreamStarted(); } protected void onUpstreamStarted() { } @Override protected final void onEndOfStream() { if (inspector != null) inspector.onEndOfStream(); onUpstreamEndOfStream(); } protected abstract void onUpstreamEndOfStream(); @Override protected void onError(Exception e) { if (inspector != null) inspector.onError(e); getOutputImpl().closeWithError(e); } @Override public void suspend() { super.suspend(); } @Override public void resume() { super.resume(); } @Override public void closeWithError(Exception e) { super.closeWithError(e); } } protected abstract class AbstractOutputProducer extends AbstractStreamProducer<O> { public AbstractOutputProducer() { super(AbstractStreamTransformer_1_1.this.eventloop); } @Override protected final void onDataReceiverChanged() { AbstractInputConsumer inputConsumer = getInputImpl(); inputConsumer.downstreamDataReceiver = this.downstreamDataReceiver; if (inputConsumer.getUpstream() != null) { inputConsumer.getUpstream().bindDataReceiver(); } } @Override protected final void onStarted() { getInputImpl().bindUpstream(); onDownstreamStarted(); } protected void onDownstreamStarted() { } @Override protected void onError(Exception e) { getInputImpl().closeWithError(e); } @Override protected final void onSuspended() { if (inspector != null) inspector.onSuspended(); onDownstreamSuspended(); } protected abstract void onDownstreamSuspended(); @Override protected final void onResumed() { if (inspector != null) inspector.onResumed(); onDownstreamResumed(); } protected abstract void onDownstreamResumed(); } protected AbstractStreamTransformer_1_1(Eventloop eventloop) { this.eventloop = eventloop; } protected abstract AbstractInputConsumer getInputImpl(); protected abstract AbstractOutputProducer getOutputImpl(); @Override public final StreamConsumer<I> getInput() { return getInputImpl(); } @Override public final StreamProducer<O> getOutput() { return getOutputImpl(); } public void setTag(Object tag) { this.tag = tag; } @Override public String toString() { return tag != null ? tag.toString() : super.toString(); } }