| /* |
| * 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); |
| } |
| } |
| } |