abs.api.DefaultOpener Maven / Gradle / Ivy
package abs.api;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.Future;
/**
* An implementation of opener that resolves the message in the
* following order
*
* - if the message is an instance of {@link java.lang.Runnable}
*
- if the message is an instance of
* {@link java.util.concurrent.Callable}
*
- if the message is a method invocation encapsulated by an
* instance of {@link abs.api.MethodReference}
*
- if the recipient of the message is an instance of
* {@link abs.api.Behavior} then opens the envelope by running the
* messages inside the recipient object.
*
*
* @see QueueOpener
*
* @author Behrooz Nobakht
* @since 1.0
*/
public class DefaultOpener implements Opener {
private final ConcurrentMap methodCache = new ConcurrentSkipListMap<>(
MethodReference.COMPARATOR);
private final Map methodHandleCache = new LinkedHashMap<>(1024,
0.75f, true);
/** {@inheritDoc} */
@Override
public Future open(final Envelope envelope, final Object target) {
return execute(envelope, target);
}
/**
*
* execute.
*
*
* @param envelope
* a {@link abs.api.Envelope} object.
* @param target
* a {@link java.lang.Object} object.
* @param
* a V object.
* @return a {@link java.util.concurrent.Future} object.
*/
protected Response execute(final Envelope envelope, final Object target) {
final Response response = envelope.response();
Runnable task = createEnvelopeTask(envelope, target);
if (task == null) {
response.completeExceptionally(new IllegalArgumentException("Invalid message: "
+ envelope.message()));
} else {
try {
executeEnvelopeTask(task);
} catch (Throwable e) {
response.completeExceptionally(e);
}
}
return response;
}
/**
*
* executeEnvelopeTask.
*
*
* @param task
* a {@link java.lang.Runnable} object.
*/
protected void executeEnvelopeTask(Runnable task) {
task.run();
}
/**
*
* createEnvelopeTask.
*
*
* @param envelope
* a {@link abs.api.Envelope} object.
* @param target
* a {@link java.lang.Object} object.
* @return a {@link java.lang.Runnable} object.
*/
protected Runnable createEnvelopeTask(final Envelope envelope, final Object target) {
final Object msg = envelope.message();
if (msg instanceof Runnable) {
return createEnvelopeRunner(envelope);
} else if (msg instanceof Callable) {
return createEnvelopeRunner(envelope);
} else if (target instanceof Behavior) {
return fromActorEnvelope(envelope, (Behavior) target);
} else if (msg instanceof MethodReference) {
return fromMethodReferenceEnvelope(envelope, target);
}
return null;
}
/**
*
* fromCallableEnvelope.
*
*
* @param envelope
* a {@link abs.api.Envelope} object.
* @return a {@link java.lang.Runnable} object.
*/
protected Runnable createEnvelopeRunner(final Envelope envelope) {
return new EnveloperRunner(envelope);
}
/**
*
* fromMethodReferenceEnvelope.
*
*
* @param envelope
* a {@link abs.api.Envelope} object.
* @param target
* a {@link java.lang.Object} object.
* @return a {@link java.lang.Runnable} object.
*/
protected Runnable fromMethodReferenceEnvelope(final Envelope envelope, final Object target) {
return () -> {
final Response