/*
* Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/
package org.mule.runtime.core.internal.util.rx;
import org.mule.runtime.core.api.Event;
import java.util.function.BiConsumer;
import java.util.function.Function;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import reactor.core.publisher.Flux;
import reactor.core.publisher.SynchronousSink;
/**
* Reusable operators to be use with project reactor.
*/
public final class Operators {
private Operators() {}
/**
* Custom function to be used with {@link reactor.core.publisher.Flux#handle(BiConsumer)} when a map function may return
* {@code null} and this should be interpreted as empty rather than causing an error. If null is return by the function then the
* {@link org.mule.runtime.core.api.EventContext} is also completed.
*
* @param mapper map function
* @return custom operator {@link BiConsumer} to be used with {@link reactor.core.publisher.Flux#handle(BiConsumer)}.
*/
public static BiConsumer<Event, SynchronousSink<Event>> nullSafeMap(Function<Event, Event> mapper) {
return (event, sink) -> {
if (event != null) {
Event result = mapper.apply(event);
if (result != null) {
sink.next(result);
} else {
event.getContext().success();
}
}
};
}
/**
* Custom function to be used with {@link reactor.core.publisher.Flux#handle(BiConsumer)} when a map function may return
* {@code null} and this should be interpreted by echoing the incoming event rather than causing an error.
*
* @param mapper map function
* @return custom operator {@link BiConsumer} to be used with {@link reactor.core.publisher.Flux#handle(BiConsumer)}.
*/
public static BiConsumer<Event, SynchronousSink<Event>> echoOnNullMap(Function<Event, Event> mapper) {
return (event, sink) -> {
if (event != null) {
Event result = mapper.apply(event);
if (result != null) {
sink.next(result);
} else {
sink.next(event);
}
}
};
}
/**
* Return a singleton {@link Subscriber} that does not check for double onSubscribe and purely request Long.MAX. Unlike using
* {@link Flux#subscribe()} directly this will not throw an exception if an error occurs.
*
* @return a new {@link Subscriber} whose sole purpose is to request Long.MAX
*/
@SuppressWarnings("unchecked")
public static <T> Subscriber<T> requestUnbounded() {
return (Subscriber<T>) RequstMaxSubscriber.INSTANCE;
}
final static class RequstMaxSubscriber<T> implements Subscriber<T> {
static final RequstMaxSubscriber INSTANCE = new RequstMaxSubscriber();
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE);
}
@Override
public void onNext(Object o) {
}
@Override
public void onError(Throwable t) {}
@Override
public void onComplete() {
}
}
}