com.github.dm.jrt.JRoutine Maven / Gradle / Ivy
Show all versions of jroutine-lib Show documentation
/*
* Copyright 2016 Davide Maestroni
*
* 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;
import com.github.dm.jrt.channel.Channels;
import com.github.dm.jrt.core.JRoutineCore;
import com.github.dm.jrt.core.builder.ChannelBuilder;
import com.github.dm.jrt.core.builder.RoutineBuilder;
import com.github.dm.jrt.core.channel.Channel;
import com.github.dm.jrt.core.invocation.CommandInvocation;
import com.github.dm.jrt.core.invocation.Invocation;
import com.github.dm.jrt.core.invocation.InvocationFactory;
import com.github.dm.jrt.core.invocation.MappingInvocation;
import com.github.dm.jrt.core.util.ClassToken;
import com.github.dm.jrt.core.util.ConstantConditions;
import com.github.dm.jrt.function.BiConsumer;
import com.github.dm.jrt.function.Consumer;
import com.github.dm.jrt.function.Function;
import com.github.dm.jrt.function.Predicate;
import com.github.dm.jrt.function.Supplier;
import com.github.dm.jrt.object.InvocationTarget;
import com.github.dm.jrt.stream.JRoutineStream;
import com.github.dm.jrt.stream.builder.StreamBuilder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import static com.github.dm.jrt.core.invocation.InvocationFactory.factoryOf;
import static com.github.dm.jrt.function.Functions.consumerCall;
import static com.github.dm.jrt.function.Functions.consumerCommand;
import static com.github.dm.jrt.function.Functions.consumerMapping;
import static com.github.dm.jrt.function.Functions.functionCall;
import static com.github.dm.jrt.function.Functions.functionMapping;
import static com.github.dm.jrt.function.Functions.predicateFilter;
import static com.github.dm.jrt.function.Functions.supplierCommand;
import static com.github.dm.jrt.function.Functions.supplierFactory;
import static com.github.dm.jrt.object.InvocationTarget.classOfType;
import static com.github.dm.jrt.object.InvocationTarget.instance;
/**
* Class acting as a façade of all the JRoutine library features.
*
* Created by davide-maestroni on 02/29/2016.
*/
@SuppressWarnings("WeakerAccess")
public class JRoutine extends Channels {
/**
* Avoid explicit instantiation.
*/
protected JRoutine() {
ConstantConditions.avoid();
}
/**
* Returns a channel builder.
*
* @return the channel builder instance.
*/
@NotNull
public static ChannelBuilder io() {
return JRoutineCore.io();
}
/**
* Returns a routine builder based on an invocation factory creating instances of the specified
* class.
*
* @param invocationClass the invocation class.
* @param the input data type.
* @param the output data type.
* @return the routine builder instance.
* @throws java.lang.IllegalArgumentException if no default constructor was found.
*/
@NotNull
public static RoutineBuilder with(
@NotNull final Class extends Invocation> invocationClass) {
return with(factoryOf(invocationClass));
}
/**
* Returns a routine builder based on an invocation factory creating instances of the specified
* class by passing the specified arguments to the class constructor.
*
* Note that inner and anonymous classes can be passed as well. Remember however that Java
* creates synthetic constructors for such classes, so be sure to specify the correct arguments
* to guarantee proper instantiation. In fact, inner classes always have the outer instance as
* first constructor parameter, and anonymous classes have both the outer instance and all the
* variables captured in the closure.
*
* @param invocationClass the invocation class.
* @param args the invocation constructor arguments.
* @param the input data type.
* @param the output data type.
* @return the routine builder instance.
* @throws java.lang.IllegalArgumentException if no constructor taking the specified objects as
* parameters was found.
*/
@NotNull
public static RoutineBuilder with(
@NotNull final Class extends Invocation> invocationClass,
@Nullable final Object... args) {
return with(factoryOf(invocationClass, args));
}
/**
* Returns a routine builder based on an invocation factory creating instances of the specified
* class token.
*
* @param invocationToken the invocation class token.
* @param the input data type.
* @param the output data type.
* @return the routine builder instance.
* @throws java.lang.IllegalArgumentException if no default constructor was found.
*/
@NotNull
public static RoutineBuilder with(
@NotNull final ClassToken extends Invocation> invocationToken) {
return with(factoryOf(invocationToken));
}
/**
* Returns a routine builder based on an invocation factory creating instances of the specified
* class token by passing the specified arguments to the class constructor.
*
* Note that class tokens of inner and anonymous classes can be passed as well. Remember however
* that Java creates synthetic constructors for such classes, so be sure to specify the correct
* arguments to guarantee proper instantiation. In fact, inner classes always have the outer
* instance as first constructor parameter, and anonymous classes have both the outer instance
* and all the variables captured in the closure.
*
* @param invocationToken the invocation class token.
* @param args the invocation constructor arguments.
* @param the input data type.
* @param the output data type.
* @return the routine builder instance.
* @throws java.lang.IllegalArgumentException if no constructor taking the specified objects as
* parameters was found.
*/
@NotNull
public static RoutineBuilder with(
@NotNull final ClassToken extends Invocation> invocationToken,
@Nullable final Object... args) {
return with(factoryOf(invocationToken, args));
}
/**
* Returns a routine builder based on the specified command invocation.
*
* @param invocation the command invocation instance.
* @param the output data type.
* @return the routine builder instance.
*/
@NotNull
public static RoutineBuilder with(
@NotNull final CommandInvocation invocation) {
return with((InvocationFactory) invocation);
}
/**
* Returns a routine builder based on an invocation factory creating instances of the specified
* object.
*
* @param invocation the invocation instance.
* @param the input data type.
* @param the output data type.
* @return the routine builder instance.
* @throws java.lang.IllegalArgumentException if no default constructor was found.
*/
@NotNull
public static RoutineBuilder with(
@NotNull final Invocation invocation) {
return with(factoryOf(invocation));
}
/**
* Returns a routine builder based on an invocation factory creating instances of the specified
* object by passing the specified arguments to the class constructor.
*
* Note that inner and anonymous objects can be passed as well. Remember however that Java
* creates synthetic constructors for such classes, so be sure to specify the correct arguments
* to guarantee proper instantiation. In fact, inner classes always have the outer instance as
* first constructor parameter, and anonymous classes have both the outer instance and all the
* variables captured in the closure.
*
* @param invocation the invocation instance.
* @param args the invocation constructor arguments.
* @param the input data type.
* @param the output data type.
* @return the routine builder instance.
* @throws java.lang.IllegalArgumentException if no constructor taking the specified objects as
* parameters was found.
*/
@NotNull
public static RoutineBuilder with(
@NotNull final Invocation invocation, @Nullable final Object... args) {
return with(factoryOf(invocation, args));
}
/**
* Returns a routine builder based on the specified invocation factory.
*
* In order to prevent undesired leaks, the class of the specified factory should have a static
* scope.
*
* @param factory the invocation factory.
* @param the input data type.
* @param the output data type.
* @return the routine builder instance.
*/
@NotNull
public static RoutineBuilder with(
@NotNull final InvocationFactory factory) {
return JRoutineCore.with(factory);
}
/**
* Returns a routine builder wrapping the specified target.
*
* Note that it is responsibility of the caller to retain a strong reference to the target
* instance to prevent it from being garbage collected.
*
* Note also that the invocation input data will be cached, and the results will be produced
* only after the invocation channel is closed, so be sure to avoid streaming inputs in order to
* prevent starvation or out of memory errors.
*
* @param target the invocation target.
* @return the routine builder instance.
* @throws java.lang.IllegalArgumentException if the specified object class represents an
* interface.
*/
@NotNull
public static ObjectProxyRoutineBuilder with(@NotNull final InvocationTarget> target) {
return new DefaultObjectProxyRoutineBuilder(target);
}
/**
* Returns a routine builder based on the specified mapping invocation.
*
* @param invocation the mapping invocation instance.
* @param the input data type.
* @param the output data type.
* @return the routine builder instance.
*/
@NotNull
public static RoutineBuilder with(
@NotNull final MappingInvocation invocation) {
return with((InvocationFactory) invocation);
}
/**
* Returns a routine builder wrapping the specified object.
*
* The invocation target will be automatically chosen based on whether the specified object is
* a class or an instance.
*
* Note that it is responsibility of the caller to retain a strong reference to the target
* instance to prevent it from being garbage collected.
*
* Note also that the invocation input data will be cached, and the results will be produced
* only after the invocation channel is closed, so be sure to avoid streaming inputs in order to
* prevent starvation or out of memory errors.
*
* @param object the target object.
* @return the routine builder instance.
* @throws java.lang.IllegalArgumentException if the specified object class represents an
* interface.
*/
@NotNull
public static ObjectProxyRoutineBuilder with(@NotNull final Object object) {
return (object instanceof Class) ? withClassOfType((Class>) object) : withInstance(object);
}
/**
* Returns a routine builder based on a call invocation factory backed by the specified function.
*
* @param function the function instance.
* @param the input data type.
* @param the output data type.
* @return the routine builder instance.
*/
@NotNull
public static RoutineBuilder withCall(
@NotNull final Function super List, ? extends OUT> function) {
return with(functionCall(function));
}
/**
* Returns a routine builder based on a call invocation factory backed by the specified consumer.
*
* @param consumer the consumer instance.
* @param the input data type.
* @param the output data type.
* @return the routine builder instance.
*/
@NotNull
public static RoutineBuilder withCallConsumer(
@NotNull final BiConsumer super List, ? super Channel> consumer) {
return with(consumerCall(consumer));
}
/**
* Returns a routine builder wrapping the specified class.
*
* Note that it is responsibility of the caller to retain a strong reference to the target
* instance to prevent it from being garbage collected.
*
* Note also that the invocation input data will be cached, and the results will be produced
* only after the invocation channel is closed, so be sure to avoid streaming inputs in order to
* prevent starvation or out of memory errors.
*
* @param targetClass the target class.
* @return the routine builder instance.
* @throws java.lang.IllegalArgumentException if the specified class represents an interface.
*/
@NotNull
public static ObjectProxyRoutineBuilder withClassOfType(@NotNull final Class> targetClass) {
return with(classOfType(targetClass));
}
/**
* Returns a routine builder based on a command invocation backed by the specified supplier.
*
* @param supplier the supplier instance.
* @param the output data type.
* @return the routine builder instance.
*/
@NotNull
public static RoutineBuilder withCommand(
@NotNull final Supplier extends OUT> supplier) {
return with(supplierCommand(supplier));
}
/**
* Returns a routine builder based on a command invocation backed by the specified consumer.
*
* @param consumer the consumer instance.
* @param the output data type.
* @return the routine builder instance.
*/
@NotNull
public static RoutineBuilder withCommandConsumer(
@NotNull final Consumer super Channel> consumer) {
return with(consumerCommand(consumer));
}
/**
* Returns a routine builder based on an invocation factory backed by the specified supplier.
*
* @param supplier the supplier instance.
* @param the input data type.
* @param the output data type.
* @return the routine builder instance.
*/
@NotNull
public static RoutineBuilder withFactory(
@NotNull final Supplier extends Invocation super IN, ? extends OUT>> supplier) {
return with(supplierFactory(supplier));
}
/**
* Returns a routine builder based on a operation invocation backed by the specified predicate.
*
* @param predicate the predicate instance.
* @param the input data type.
* @return the routine builder instance.
*/
@NotNull
public static RoutineBuilder withFilter(
@NotNull final Predicate super IN> predicate) {
return with(predicateFilter(predicate));
}
/**
* Returns a routine builder wrapping the specified object.
*
* Note that it is responsibility of the caller to retain a strong reference to the target
* instance to prevent it from being garbage collected.
*
* Note also that the invocation input data will be cached, and the results will be produced
* only after the invocation channel is closed, so be sure to avoid streaming inputs in order to
* prevent starvation or out of memory errors.
*
* @param object the target object.
* @return the routine builder instance.
*/
@NotNull
public static ObjectProxyRoutineBuilder withInstance(@NotNull final Object object) {
return with(instance(object));
}
/**
* Returns a routine builder based on a mapping invocation backed by the specified function.
*
* @param function the function instance.
* @param the input data type.
* @param the output data type.
* @return the routine builder instance.
*/
@NotNull
public static RoutineBuilder withMapping(
@NotNull final Function super IN, ? extends OUT> function) {
return with(functionMapping(function));
}
/**
* Returns a routine builder based on a mapping invocation backed by the specified consumer.
*
* @param consumer the consumer instance.
* @param the input data type.
* @param the output data type.
* @return the routine builder instance.
*/
@NotNull
public static RoutineBuilder withMappingConsumer(
@NotNull final BiConsumer super IN, ? super Channel> consumer) {
return with(consumerMapping(consumer));
}
/**
* Returns a stream routine builder.
*
* @param the input data type.
* @return the routine builder instance.
*/
@NotNull
public static StreamBuilder withStream() {
return JRoutineStream.withStream();
}
/**
* Returns a stream routine builder producing only the inputs passed by the specified consumer.
*
* The data will be produced only when the invocation completes.
*
* If any other input is passed to the built routine, the invocation will be aborted with an
* {@link java.lang.IllegalStateException}.
*
* @param consumer the consumer instance.
* @param the input data type.
* @return the routine builder instance.
*/
@NotNull
public static StreamBuilder withStreamAccept(
@NotNull final Consumer> consumer) {
return JRoutineStream.withStreamAccept(consumer);
}
/**
* Returns a stream routine builder producing only the inputs passed by the specified consumer.
*
* The data will be produced by calling the consumer {@code count} number of times only when the
* invocation completes.
*
* If any other input is passed to the built routine, the invocation will be aborted with an
* {@link java.lang.IllegalStateException}.
*
* @param count the number of times the consumer is called.
* @param consumer the consumer instance.
* @param the input data type.
* @return the routine builder instance.
* @throws java.lang.IllegalArgumentException if the specified count number is 0 or negative.
*/
@NotNull
public static StreamBuilder withStreamAccept(final int count,
@NotNull final Consumer> consumer) {
return JRoutineStream.withStreamAccept(count, consumer);
}
/**
* Returns a stream routine builder producing only the inputs returned by the specified supplier.
*
* The data will be produced only when the invocation completes.
*
* If any other input is passed to the built routine, the invocation will be aborted with an
* {@link java.lang.IllegalStateException}.
*
* @param supplier the supplier instance.
* @param the input data type.
* @return the routine builder instance.
*/
@NotNull
public static StreamBuilder withStreamGet(@NotNull final Supplier supplier) {
return JRoutineStream.withStreamGet(supplier);
}
/**
* Returns a stream routine builder producing only the inputs returned by the specified supplier.
*
* The data will be produced by calling the supplier {@code count} number of times only when the
* invocation completes.
*
* If any other input is passed to the built routine, the invocation will be aborted with an
* {@link java.lang.IllegalStateException}.
*
* @param count the number of times the supplier is called.
* @param supplier the supplier instance.
* @param the input data type.
* @return the routine builder instance.
* @throws java.lang.IllegalArgumentException if the specified count number is 0 or negative.
*/
@NotNull
public static StreamBuilder withStreamGet(final int count,
@NotNull final Supplier supplier) {
return JRoutineStream.withStreamGet(count, supplier);
}
/**
* Returns a stream routine builder producing only the specified input.
*
* The data will be produced only when the invocation completes.
*
* If any other input is passed to the built routine, the invocation will be aborted with an
* {@link java.lang.IllegalStateException}.
*
* @param input the input.
* @param the input data type.
* @return the routine builder instance.
*/
@NotNull
public static StreamBuilder withStreamOf(@Nullable final IN input) {
return JRoutineStream.withStreamOf(input);
}
/**
* Returns a stream routine builder producing only the specified inputs.
*
* The data will be produced only when the invocation completes.
*
* If any other input is passed to the built routine, the invocation will be aborted with an
* {@link java.lang.IllegalStateException}.
*
* @param inputs the input data.
* @param the input data type.
* @return the routine builder instance.
*/
@NotNull
public static StreamBuilder withStreamOf(@Nullable final IN... inputs) {
return JRoutineStream.withStreamOf(inputs);
}
/**
* Returns a stream routine builder producing only the inputs returned by the specified iterable.
*
* The data will be produced only when the invocation completes.
*
* If any other input is passed to the built routine, the invocation will be aborted with an
* {@link java.lang.IllegalStateException}.
*
* @param inputs the inputs iterable.
* @param the input data type.
* @return the routine builder instance.
*/
@NotNull
public static StreamBuilder withStreamOf(
@Nullable final Iterable extends IN> inputs) {
return JRoutineStream.withStreamOf(inputs);
}
/**
* Returns a stream routine builder producing only the inputs returned by the specified channel.
*
* The data will be produced only when the invocation completes.
*
* If any other input is passed to the built routine, the invocation will be aborted with an
* {@link java.lang.IllegalStateException}.
*
* Note that the passed channel will be bound as a result of the call, so, in order to support
* multiple invocations, consider wrapping the channel in a replayable one, by calling the
* {@link Channels#replay(Channel)} utility method.
*
* @param channel the input channel.
* @param the input data type.
* @return the routine builder instance.
*/
@NotNull
public static StreamBuilder withStreamOf(
@Nullable final Channel, ? extends IN> channel) {
return JRoutineStream.withStreamOf(channel);
}
}