blob: 57ac13af798db9d8144cd639f2c8a2b347d444b6 [file] [log] [blame]
/*
* Copyright 2008 Google Inc.
*
* 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.google.gwt.user.client.impl;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.AsyncProxy;
import java.util.ArrayList;
import java.util.List;
/**
* The base implementation for AsyncProxy instances.
*
* @param <T> the type to be returned from the GWT.create call
*/
public abstract class AsyncProxyBase<T> implements AsyncProxy<T> {
/**
* Simple parameterized command type.
*
* @param <T> as above
*/
protected interface ParamCommand<T> {
void execute(T instance);
}
/*
* These fields are package-protected to allow for easier testing.
*/
private List<ParamCommand<T>> commands = new ArrayList<ParamCommand<T>>();
private boolean hasAsyncBeenIssued = false;
private boolean hasAsyncFailed = false;
private boolean hasAsyncReturned = false;
private T instance = null;
/**
* Testing method to enable enqueue0 from firing the runAsync call.
*/
public void enableLoadForTest0() {
hasAsyncBeenIssued = false;
hasAsyncFailed = false;
hasAsyncReturned = false;
}
public final T getProxiedInstance() {
return instance;
}
/**
* To be implemented by the subtype.
*/
public abstract void setProxyCallback(ProxyCallback<T> callback);
/**
* Testing method to prevent enqueue0 from actually firing the runAsync call.
*/
public void suppressLoadForTest0() {
hasAsyncBeenIssued = true;
hasAsyncFailed = false;
hasAsyncReturned = false;
}
/**
* To be implemented by the subtype to give the code-splitter a new starting
* point.
*/
protected abstract void doAsync0();
/**
* Called by the generated subtype if the runAsync invocation fails.
*/
protected final void doFailure0(Throwable t) {
hasAsyncFailed = true;
getCallback0().onFailure(t);
}
/**
* Called by the generated subtype to enqueue an action for later replay.
*/
protected final void enqueue0(ParamCommand<T> cmd) {
try {
if (hasAsyncFailed) {
throw new IllegalStateException("runAsync load previously failed");
} else if (!hasAsyncBeenIssued) {
hasAsyncBeenIssued = true;
commands.add(cmd);
doAsync0();
} else if (hasAsyncReturned) {
assert instance != null;
cmd.execute(instance);
} else {
assert instance == null;
commands.add(cmd);
}
} catch (Throwable t) {
if (getCallback0() != null) {
getCallback0().onFailure(t);
} else {
GWT.reportUncaughtException(t);
}
}
}
/**
* The callback is maintained by the generated subtype to take advantage of
* type-tightening.
*/
protected abstract ProxyCallback<T> getCallback0();
/**
* Called by the generated subtype with the new instance of the object.
*/
protected final void setInstance0(T instance) {
assert commands != null : "No commands";
assert hasAsyncBeenIssued : "async request not yet started";
hasAsyncReturned = true;
this.instance = instance;
List<ParamCommand<T>> localCommands = commands;
commands = null;
// Can fail below
if (getCallback0() != null) {
getCallback0().onInit(instance);
}
for (ParamCommand<T> cmd : localCommands) {
cmd.execute(instance);
}
if (getCallback0() != null) {
getCallback0().onComplete(instance);
}
}
}