/* * Quasar: lightweight threads and actors for the JVM. * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved. * * This program and the accompanying materials are dual-licensed under * either the terms of the Eclipse Public License v1.0 as published by * the Eclipse Foundation * * or (per the licensee's choosing) * * under the terms of the GNU Lesser General Public License version 3.0 * as published by the Free Software Foundation. */ package co.paralleluniverse.strands.channels; import co.paralleluniverse.common.util.Function2; import co.paralleluniverse.fibers.FiberFactory; import co.paralleluniverse.strands.SuspendableAction2; import com.google.common.base.Function; import com.google.common.base.Predicate; /** * A {@link SendPort} with additional functional-transform operations, usually wrapping a plain {@link SendPort}. * * @author pron */ public class TransformingSendPort<T> extends DelegatingSendPort<T> { TransformingSendPort(SendPort<T> target) { super(target); } /** * Returns a {@link TransformingSendPort} that filters messages that satisfy a predicate before sending to this channel. * Messages that don't satisfy the predicate will be silently discarded when sent. * <p/> * The returned {@code SendPort} has the same {@link Object#hashCode() hashCode} as {@code channel} and is {@link Object#equals(Object) equal} to it. * * @param pred the filtering predicate * @return A {@link TransformingSendPort} that will send only those messages which satisfy the predicate (i.e. the predicate returns {@code true}) to the given channel. */ public TransformingSendPort<T> filter(Predicate<T> pred) { return Channels.transformSend(Channels.filterSend(this, pred)); } /** * Returns a {@link TransformingSendPort} that transforms messages by applying a given mapping function before sending this channel. * <p/> * The returned {@code TransformingSendPort} has the same {@link Object#hashCode() hashCode} as {@code channel} and is {@link Object#equals(Object) equal} to it. * * @param f the mapping function * @return a {@link TransformingSendPort} that passes messages to the given channel after transforming them by applying the mapping function. */ public <S> TransformingSendPort<S> map(Function<S, T> f) { return Channels.transformSend(Channels.mapSend(this, f)); } /** * Returns a {@link TransformingSendPort} to which sending messages that are transformed towards a channel by a reduction function. * <p/> * The returned {@code TransformingSendPort} has the same {@link Object#hashCode() hashCode} as {@code channel} and is {@link Object#equals(Object) equal} to it. * * @param f The reduction function. * @param init The initial input to the reduction function. * @return a {@link ReceivePort} that returns messages that are the result of applying the reduction function to the messages received on the given channel. */ public <S> TransformingSendPort<S> reduce(Function2<T, S, T> f, T init) { return Channels.transformSend(Channels.reduceSend(this, f, init)); } /** * Returns a {@link SendPort} that sends messages that are transformed by a given flat-mapping function into this channel. * Unlike {@link #map(Function) map}, the mapping function does not returns a single output message for every input message, but * a new {@code ReceivePort}. All the returned ports are concatenated and sent to the channel. * <p/> * To return a single value the mapping function can make use of {@link Channels#singletonReceivePort(Object)}. To return a collection, * it can make use of {@link Channels#toReceivePort(Iterable)}. To emit no values, the function can return {@link Channels#emptyReceivePort()} * or {@code null}. * <p/> * If multiple producers send messages into the channel, the messages from the {@code ReceivePort}s returned by the mapping function * may be interleaved with other messages. * <p/> * The returned {@code SendPort} has the same {@link Object#hashCode() hashCode} as {@code channel} and is {@link Object#equals(Object) equal} to it. * * @param pipe an intermediate channel used in the flat-mapping operation. Messages are first sent to this channel before being transformed. * @param f the mapping function * @return a {@link ReceivePort} that returns messages that are the result of applying the mapping function to the messages received on the given channel. */ public <S> TransformingSendPort<S> flatMap(Channel<S> pipe, Function<S, ReceivePort<T>> f) { return Channels.transformSend(Channels.flatMapSend(pipe, this, f)); } /** * Spawns a fiber that transforms values read from the {@code in} channel and writes values to this channel. * <p/> * When the transformation terminates. the output channel is automatically closed. If the transformation terminates abnormally * (throws an exception), this channel is {@link SendPort#close(Throwable) closed with that exception}. * * @param in the input channel * @param transformer the transforming operation * * @return A {@link TransformingSendPort} wrapping the {@code in} channel. */ public <U> TransformingSendPort<U> fiberTransform(SuspendableAction2<? extends ReceivePort<? super U>, ? extends SendPort<? extends T>> transformer, Channel<U> in) { Channels.fiberTransform(in, this, transformer); return Channels.transformSend(in); } /** * Spawns a fiber that transforms values read from the {@code in} channel and writes values to this channel. * <p/> * When the transformation terminates. the output channel is automatically closed. If the transformation terminates abnormally * (throws an exception), this channel is {@link SendPort#close(Throwable) closed with that exception}. * * @param fiberFactory will be used to create the fiber * @param in the input channel * @param transformer the transforming operation * * @return A {@link TransformingSendPort} wrapping the {@code in} channel. */ public <U> TransformingSendPort<U> fiberTransform(FiberFactory fiberFactory, SuspendableAction2<? extends ReceivePort<? super U>, ? extends SendPort<? extends T>> transformer, Channel<U> in) { Channels.fiberTransform(fiberFactory, in, this, transformer); return Channels.transformSend(in); } }