Nobody's using this here, it's not very well documented, and I want to make
something better anyway. Let's get it out of the way. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@6701 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,289 +0,0 @@
|
||||
//
|
||||
// $Id$
|
||||
|
||||
package com.threerings.util;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import com.samskivert.util.ArrayUtil;
|
||||
import com.samskivert.util.IntResultListener;
|
||||
import com.samskivert.util.Invoker;
|
||||
import com.samskivert.util.Logger;
|
||||
import com.samskivert.util.ResultListener;
|
||||
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
import com.threerings.presents.data.InvocationCodes;
|
||||
import com.threerings.presents.server.InvocationException;
|
||||
|
||||
import static com.threerings.NaryaLog.log;
|
||||
|
||||
/**
|
||||
* A chainable ResultListener, InvocationListener, and Invoker.Unit all in one.
|
||||
*
|
||||
* TODO: add some examples of different usages.
|
||||
*/
|
||||
public class Resulting<T> extends Invoker.Unit
|
||||
implements ResultListener<T>,
|
||||
InvocationService.ConfirmListener, InvocationService.ResultListener
|
||||
{
|
||||
/** A handy Object->Void function for when you wish to chain to a ResultListener<Void>. */
|
||||
public static final Function<Object, Void> TO_VOID =
|
||||
new Function<Object, Void>() {
|
||||
public Void apply (Object o) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
public Resulting (String name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
|
||||
public Resulting (String name, Resulting<T> chain)
|
||||
{
|
||||
this(name, (ResultListener<T>)chain);
|
||||
}
|
||||
|
||||
public Resulting (Resulting<T> chain)
|
||||
{
|
||||
this(chain.toString(), chain);
|
||||
}
|
||||
|
||||
public Resulting (String name, ResultListener<T> chain)
|
||||
{
|
||||
this(name);
|
||||
_chain = chain;
|
||||
}
|
||||
|
||||
public Resulting (ResultListener<T> chain)
|
||||
{
|
||||
this(chain.toString(), chain);
|
||||
}
|
||||
|
||||
public Resulting (String name, InvocationService.InvocationListener chain)
|
||||
{
|
||||
this(name);
|
||||
_invChain = chain;
|
||||
}
|
||||
|
||||
public Resulting (InvocationService.InvocationListener chain)
|
||||
{
|
||||
this(chain.toString(), chain);
|
||||
}
|
||||
|
||||
public <Q> Resulting (
|
||||
String name, final ResultListener<Q> chain, final Function<? super T, ? extends Q> xform)
|
||||
{
|
||||
this(name, new ResultListener<T>() {
|
||||
public void requestCompleted (T result) {
|
||||
chain.requestCompleted(xform.apply(result));
|
||||
}
|
||||
public void requestFailed (Exception cause) {
|
||||
chain.requestFailed(cause);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public <Q> Resulting (ResultListener<Q> chain, Function<? super T, ? extends Q> xform)
|
||||
{
|
||||
this(chain.toString(), chain, xform);
|
||||
}
|
||||
|
||||
public Resulting (String name, Logger log, Object... logArgs)
|
||||
{
|
||||
this(name);
|
||||
_log = log;
|
||||
_logArgs = logArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct your Resulting<Integer>, overriding what you need to,
|
||||
* then call this to adapt it.
|
||||
*/
|
||||
public final IntResultListener asIntResultListener ()
|
||||
{
|
||||
return new IntResultListener() {
|
||||
public void requestCompleted (int result) {
|
||||
// call the invocation method and it will do the unsafe cast for us.
|
||||
Resulting.this.requestProcessed((Object)result);
|
||||
}
|
||||
public void requestFailed (Exception cause) {
|
||||
Resulting.this.requestFailed(cause);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: Maybe we don't extend Invoker.Unit
|
||||
// public Invoker.Unit asUnit (Callable<T> callable)
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// public Invoker.Unit asUnit ()
|
||||
// {
|
||||
// }
|
||||
//
|
||||
/**
|
||||
* Override this if you are using a Resulting as an Invoker unit.
|
||||
*/
|
||||
public T invokePersist ()
|
||||
throws Exception
|
||||
{
|
||||
// please to be overriding
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean invoke ()
|
||||
{
|
||||
try {
|
||||
_result = invokePersist();
|
||||
|
||||
} catch (StopException se) {
|
||||
return false;
|
||||
|
||||
} catch (Exception e) {
|
||||
_error = e;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this from your invokePersist() to suppress returning to the dobj thread.
|
||||
* @throws StopException every time.
|
||||
*/
|
||||
protected final T stop ()
|
||||
throws StopException
|
||||
{
|
||||
throw STOP.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handleResult ()
|
||||
{
|
||||
if (_error != null) {
|
||||
requestFailed(_error);
|
||||
} else {
|
||||
requestCompleted(_result);
|
||||
}
|
||||
}
|
||||
|
||||
// from InvocationService.InvocationListener
|
||||
public final void requestFailed (String error)
|
||||
{
|
||||
requestFailed(INV_EX.get().setMessage(error));
|
||||
}
|
||||
|
||||
// from InvocationService.ConfirmListener
|
||||
public final void requestProcessed ()
|
||||
{
|
||||
requestCompleted(null);
|
||||
}
|
||||
|
||||
// from InvocationService.ResultListener
|
||||
public final void requestProcessed (Object result)
|
||||
{
|
||||
@SuppressWarnings("unchecked") T casted = (T)result;
|
||||
requestCompleted(casted);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this to handle a request failed in your own way.
|
||||
*/
|
||||
public void requestFailed (Exception cause)
|
||||
{
|
||||
if (_chain != null) {
|
||||
_chain.requestFailed(cause);
|
||||
|
||||
} else if (_invChain != null) {
|
||||
_invChain.requestFailed((cause instanceof InvocationException)
|
||||
? cause.getMessage()
|
||||
: InvocationCodes.INTERNAL_ERROR);
|
||||
|
||||
} else {
|
||||
Object[] logArgs = Objects.firstNonNull(_logArgs, ArrayUtil.EMPTY_OBJECT);
|
||||
Object[] args;
|
||||
if (cause instanceof InvocationException) {
|
||||
args = new Object[logArgs.length + 4];
|
||||
args[args.length - 2] = "error";
|
||||
args[args.length - 1] = cause.getMessage();
|
||||
|
||||
} else {
|
||||
args = new Object[logArgs.length + 3];
|
||||
args[args.length - 1] = cause;
|
||||
}
|
||||
args[0] = "Resulting";
|
||||
args[1] = this;
|
||||
System.arraycopy(logArgs, 0, args, 2, logArgs.length);
|
||||
Objects.firstNonNull(_log, log).warning("Request failed", args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this to handle a request completion in your own way.
|
||||
*/
|
||||
public void requestCompleted (T result)
|
||||
{
|
||||
if (_chain != null) {
|
||||
_chain.requestCompleted(result);
|
||||
|
||||
} else if (_invChain instanceof InvocationService.ResultListener) {
|
||||
((InvocationService.ResultListener)_invChain).requestProcessed(result);
|
||||
|
||||
} else if (_invChain instanceof InvocationService.ConfirmListener) {
|
||||
((InvocationService.ConfirmListener)_invChain).requestProcessed();
|
||||
}
|
||||
}
|
||||
|
||||
/** Our invocation chain, if any. */
|
||||
protected InvocationService.InvocationListener _invChain;
|
||||
|
||||
protected ResultListener<T> _chain;
|
||||
|
||||
protected Logger _log;
|
||||
|
||||
protected Object[] _logArgs;
|
||||
|
||||
protected T _result;
|
||||
|
||||
protected Exception _error;
|
||||
|
||||
protected static final ThreadLocal<ReusableInvocationException> INV_EX =
|
||||
new ThreadLocal<ReusableInvocationException>() {
|
||||
@Override protected ReusableInvocationException initialValue () {
|
||||
return new ReusableInvocationException();
|
||||
}
|
||||
};
|
||||
|
||||
protected static class ReusableInvocationException extends InvocationException
|
||||
{
|
||||
public ReusableInvocationException ()
|
||||
{
|
||||
super("");
|
||||
}
|
||||
|
||||
public ReusableInvocationException setMessage (String msg)
|
||||
{
|
||||
_msg = msg;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override public String getMessage ()
|
||||
{
|
||||
return _msg;
|
||||
}
|
||||
|
||||
protected String _msg;
|
||||
}
|
||||
|
||||
protected static final ThreadLocal<StopException> STOP =
|
||||
new ThreadLocal<StopException>() {
|
||||
@Override protected StopException initialValue () {
|
||||
return new StopException();
|
||||
}
|
||||
};
|
||||
|
||||
protected static class StopException extends RuntimeException
|
||||
{
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user