com.github.dm.jrt.function.DefaultFunctionalRoutine Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jroutine Show documentation
Show all versions of jroutine Show documentation
Parallel programming on the go
/*
* 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 com.github.dm.jrt.function;
import com.github.dm.jrt.channel.OutputChannel;
import com.github.dm.jrt.channel.ResultChannel;
import com.github.dm.jrt.channel.RoutineException;
import com.github.dm.jrt.channel.StreamingChannel;
import com.github.dm.jrt.invocation.DelegatingInvocation;
import com.github.dm.jrt.invocation.DelegatingInvocation.DelegationType;
import com.github.dm.jrt.invocation.Invocation;
import com.github.dm.jrt.routine.Routine;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static com.github.dm.jrt.core.Channels.syncStream;
/**
* Default implementation of a functional routine.
*
* Created by davide-maestroni on 10/16/2015.
*
* @param the input data type.
* @param the output data type.
*/
class DefaultFunctionalRoutine extends AbstractFunctionalRoutine {
private final Routine mRoutine;
/**
* Constructor.
*
* @param routine the backing routine instance.
*/
@SuppressWarnings("ConstantConditions")
DefaultFunctionalRoutine(@NotNull final Routine routine) {
if (routine == null) {
throw new NullPointerException("the backing routine must not be null");
}
mRoutine = routine;
}
@NotNull
public FunctionalRoutine thenLift(
@NotNull final Function super FunctionalRoutine, ? extends Routine> function) {
return new DefaultFunctionalRoutine(function.apply(this));
}
@NotNull
@Override
protected Invocation newInvocation(@NotNull final InvocationType type) {
return new DelegatingInvocation(mRoutine, DelegationType.SYNC);
}
/**
* Functional routine implementation concatenating two different routines.
*
* @param the input data type.
* @param the output data type.
* @param the concatenation output type.
*/
private static class AfterFunctionalRoutine
extends AbstractFunctionalRoutine {
private final Routine super OUT, AFTER> mAfterRoutine;
private final DelegationType mDelegationType;
private final FunctionalRoutine mRoutine;
/**
* Constructor.
*
* @param routine the backing routine instance.
* @param afterRoutine the concatenated routine instance.
* @param delegationType the concatenated delegation type.
*/
@SuppressWarnings("ConstantConditions")
private AfterFunctionalRoutine(@NotNull final FunctionalRoutine routine,
@NotNull final Routine super OUT, AFTER> afterRoutine,
@NotNull final DelegationType delegationType) {
if (afterRoutine == null) {
throw new NullPointerException("the concatenated routine must not be null");
}
if (delegationType == null) {
throw new NullPointerException("the delegation type must not be null");
}
mRoutine = routine;
mAfterRoutine = afterRoutine;
mDelegationType = delegationType;
}
@NotNull
@Override
protected FunctionalRoutine andThen(
@NotNull final Routine super AFTER, NEXT> routine,
@NotNull final DelegationType delegationType) {
return new AfterFunctionalRoutine(this, routine, delegationType);
}
@NotNull
public FunctionalRoutine thenLift(
@NotNull final Function super FunctionalRoutine, ? extends
Routine> function) {
return new DefaultFunctionalRoutine(function.apply(this));
}
@NotNull
@Override
protected Invocation newInvocation(@NotNull final InvocationType type) {
return new AfterInvocation(mRoutine, mAfterRoutine, mDelegationType);
}
}
/**
* Invocation implementation concatenating two different routines.
*
* @param the input data type.
* @param the output data type.
* @param the concatenation output type.
*/
private static class AfterInvocation implements Invocation {
private final Routine super OUT, AFTER> mAfterRoutine;
private final DelegationType mDelegationType;
private final FunctionalRoutine mRoutine;
private StreamingChannel mInputChannel;
private OutputChannel mOutputChannel;
/**
* Constructor.
*
* @param routine the backing routine instance.
* @param afterRoutine the concatenated routine instance.
* @param delegationType the concatenated delegation type.
*/
private AfterInvocation(@NotNull final FunctionalRoutine routine,
@NotNull final Routine super OUT, AFTER> afterRoutine,
@NotNull final DelegationType delegationType) {
mRoutine = routine;
mAfterRoutine = afterRoutine;
mDelegationType = delegationType;
}
public void onAbort(@Nullable final RoutineException reason) {
mInputChannel.abort(reason);
}
public void onDestroy() {
mInputChannel = null;
mOutputChannel = null;
}
public void onInitialize() {
final StreamingChannel streamingChannel = syncStream(mRoutine);
final DelegationType delegationType = mDelegationType;
if (delegationType == DelegationType.ASYNC) {
mOutputChannel = streamingChannel.passTo(mAfterRoutine.asyncInvoke()).result();
mInputChannel = streamingChannel;
} else if (delegationType == DelegationType.PARALLEL) {
mOutputChannel = streamingChannel.passTo(mAfterRoutine.parallelInvoke()).result();
mInputChannel = streamingChannel;
} else {
mOutputChannel = streamingChannel.passTo(mAfterRoutine.syncInvoke()).result();
mInputChannel = streamingChannel;
}
}
public void onInput(final IN input, @NotNull final ResultChannel result) {
final OutputChannel channel = mOutputChannel;
if (!channel.isBound()) {
channel.passTo(result);
}
mInputChannel.pass(input);
}
public void onResult(@NotNull final ResultChannel result) {
final OutputChannel channel = mOutputChannel;
if (!channel.isBound()) {
channel.passTo(result);
}
mInputChannel.close();
}
public void onTerminate() {
mInputChannel = null;
mOutputChannel = null;
}
}
@NotNull
@Override
protected FunctionalRoutine andThen(
@NotNull final Routine super OUT, AFTER> routine,
@NotNull final DelegationType delegationType) {
return new AfterFunctionalRoutine(this, routine, delegationType);
}
}