package com.google.gwt.gwtpages.gin.client.page.loader;
import java.util.HashMap;
import java.util.Iterator;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.RunAsyncCallback;
import com.google.gwt.gwtpages.client.message.exceptions.PageNotFoundException;
import com.google.gwt.gwtpages.client.page.LoadedPageContainer;
import com.google.gwt.gwtpages.client.page.Page;
import com.google.gwt.gwtpages.client.page.PageAttributes;
import com.google.gwt.gwtpages.client.page.loader.AbstractPageLoader;
import com.google.gwt.gwtpages.client.page.loader.PageLoadCallback;
public abstract class AsyncGinPageLoader extends AbstractPageLoader implements GinPageLoader {
public static enum LoadType {
INDIVIDUAL, COMPLETE;
}
private HashMap<String, Boolean> loadedPageFlag = new HashMap<String, Boolean>();
private HashMap<String, Page> newPages = new HashMap<String, Page>();
private LoadType loadType = LoadType.INDIVIDUAL;
/**
* All pages registered with this loader will, by default, use a separate
* async call to load each individual page
*/
public AsyncGinPageLoader() {
}
/**
* Set the load type:
*
* @param loadType
* : LoadType.INDIVIDUAL will load each page with a separate
* async call; LoadType.COMPLETE will use a single async call for
* all pages registered with this loader
*/
public AsyncGinPageLoader setLoadType(LoadType loadType) {
this.loadType = loadType;
return this;
}
public void getPage(final String pageToken,
final PageLoadCallback pageLoadCallback) {
// has the page been loaded?
if (null != loadedPageFlag.get(pageToken)) {
// don't do an async load
if (null != newPages.get(pageToken)) {
// have we created the page during a async load for a differnet
// page
try {
pageLoadCallback
.onPageFound(new LoadedPageContainer(pageToken,
newPages.get(pageToken),
getPageAttributes(pageToken),
AsyncGinPageLoader.this));
} catch (PageNotFoundException e) {
// we know the page is here
pageLoadCallback.onPageFound(new LoadedPageContainer(
pageToken, newPages.get(pageToken), null,
AsyncGinPageLoader.this));
}
newPages.remove(pageToken);
} else {
// create a new page
Page page = null;
PageAttributes attributes = null;
try {
page = newInstance(pageToken);
attributes = getPageAttributes(pageToken);
} catch (PageNotFoundException e) {
// we know the page exists because it was loaded before
}
pageLoadCallback.onPageFound(new LoadedPageContainer(pageToken,
page, attributes, AsyncGinPageLoader.this));
}
}
// do an async load
if (isValidPageToken(pageToken)) {
if (null == loadType || loadType == LoadType.INDIVIDUAL) {
// only load a single page
GWT.runAsync(new RunAsyncCallback() {
public void onSuccess() {
try {
Page page = newInstance(pageToken);
pageLoadCallback
.onPageFound(new LoadedPageContainer(
pageToken, page,
getPageAttributes(pageToken),
AsyncGinPageLoader.this));
loadedPageFlag.put(pageToken, Boolean.TRUE);
} catch (Throwable e) {
pageLoadCallback.onPageLoadFailure(pageToken, e);
}
}
public void onFailure(Throwable reason) {
pageLoadCallback.onPageLoadFailure(pageToken, reason);
}
});
} else {
// load all pages at once
GWT.runAsync(new RunAsyncCallback() {
public void onSuccess() {
Throwable pageException = null;
LoadedPageContainer rtn = null;
Iterator<String> pageTokens = getValidPageTokens();
while (pageTokens.hasNext()) {
String key = pageTokens.next();
try {
Page page = newInstance(key);
loadedPageFlag.put(pageToken, Boolean.TRUE);
if (key.equals(pageToken)) {
// this is the page we are looking for
rtn = new LoadedPageContainer(pageToken,
page, getPageAttributes(pageToken),
AsyncGinPageLoader.this);
} else {
newPages.put(pageToken, page);
}
} catch (Throwable e) {
if (key.equals(pageToken)) {
pageException = e;
}
}
}
if (null != rtn) {
pageLoadCallback.onPageFound(rtn);
} else {
pageLoadCallback.onPageLoadFailure(pageToken,
pageException);
}
}
public void onFailure(Throwable reason) {
pageLoadCallback.onPageLoadFailure(pageToken, reason);
}
});
}
} else {
// the page wasn't found
pageLoadCallback.onPageNotFound(pageToken);
}
}
}