Adding Gwt 2.1.0 RC1 changes from trunk.
git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/2.1@8955 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/build.xml b/dev/build.xml
index 2a16924..00a5c2b 100755
--- a/dev/build.xml
+++ b/dev/build.xml
@@ -100,7 +100,7 @@
<include name="htmlunit/htmlunit-r5940/htmlunit-r5940.jar" />
<include name="htmlunit/htmlunit-r5940/htmlunit-core-js-r5940.jar" />
<include name="nekohtml/nekohtml-1.9.13.jar" />
- <include name="streamhtmlparser/streamhtmlparser-jsilver-r10/streamhtmlparser-jsilver-r10-rebased.jar" />
+ <include name="streamhtmlparser/streamhtmlparser-jsilver-r10/streamhtmlparser-jsilver-r10-1.5-rebased.jar" />
<include name="xalan/xalan-2.7.1.jar" />
<include name="xerces/xerces-2_9_1/serializer.jar" />
<include name="xerces/xerces-2_9_1/xercesImpl-NoMetaInf.jar" />
@@ -124,7 +124,7 @@
<zipfileset src="${gwt.tools.lib}/jetty/jetty-6.1.11.jar" />
<zipfileset src="${gwt.tools.lib}/icu4j/icu4j-4_4_1.jar" />
<zipfileset src="${gwt.tools.lib}/protobuf/protobuf-2.2.0/protobuf-java-rebased-2.2.0.jar" />
- <zipfileset src="${gwt.tools.lib}/streamhtmlparser/streamhtmlparser-jsilver-r10/streamhtmlparser-jsilver-r10-rebased.jar" />
+ <zipfileset src="${gwt.tools.lib}/streamhtmlparser/streamhtmlparser-jsilver-r10/streamhtmlparser-jsilver-r10-1.5-rebased.jar" />
<zipfileset src="${gwt.tools.lib}/tomcat/ant-launcher-1.6.5.jar" />
<zipfileset src="${gwt.tools.lib}/tomcat/catalina-1.0.jar" />
<zipfileset src="${gwt.tools.lib}/tomcat/catalina-optional-1.0.jar" />
diff --git a/doc/build.xml b/doc/build.xml
index 1770d9d..6b40bb8 100644
--- a/doc/build.xml
+++ b/doc/build.xml
@@ -29,6 +29,9 @@
<pathelement location="${gwt.user.jar}" />
<pathelement location="${gwt.dev.jar}" />
<pathelement location="${gwt.tools.lib}/junit/junit-3.8.1.jar" />
+ <pathelement location="${gwt.tools}/redist/json/r2_20080312/json-1.5.jar" />
+ <pathelement location="${gwt.tools.lib}/javax/validation/validation-api-1.0.0.GA.jar" />
+ <pathelement location="${gwt.tools.lib}/javax/validation/validation-api-1.0.0.GA-sources.jar" />
<pathelement location="${gwt.tools.lib}/jfreechart/jfreechart-1.0.3.jar" />
</path>
diff --git a/eclipse/samples/DynaTableRf/.classpath b/eclipse/samples/DynaTableRf/.classpath
index c0fb748..f2c5ce7 100644
--- a/eclipse/samples/DynaTableRf/.classpath
+++ b/eclipse/samples/DynaTableRf/.classpath
@@ -6,6 +6,6 @@
<classpathentry combineaccessrules="false" kind="src" path="/gwt-user"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/javax/validation/validation-api-1.0.0.GA.jar" sourcepath="/GWT_TOOLS/lib/javax/validation/validation-api-1.0.0.GA-sources.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/javax/validation/validation-api-1.0.0.GA-sources.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/redist/json/r2_20080312/json.jar"/>
+ <classpathentry kind="var" path="GWT_TOOLS/redist/json/r2_20080312/json-1.5.jar"/>
<classpathentry kind="output" path="war/WEB-INF/classes"/>
</classpath>
diff --git a/eclipse/user/.classpath b/eclipse/user/.classpath
index 85deb35..605bfdf 100644
--- a/eclipse/user/.classpath
+++ b/eclipse/user/.classpath
@@ -40,6 +40,6 @@
<classpathentry exported="true" kind="var" path="GWT_TOOLS/lib/javax/validation/validation-api-1.0.0.GA-sources.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/jetty/jetty-6.1.11.jar" sourcepath="/GWT_TOOLS/lib/jetty/jetty-6.1.11-src.zip"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/guava/guava-r06/guava-r06-rebased.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/streamhtmlparser/streamhtmlparser-jsilver-r10/streamhtmlparser-jsilver-r10-rebased.jar"/>
+ <classpathentry kind="var" path="GWT_TOOLS/lib/streamhtmlparser/streamhtmlparser-jsilver-r10/streamhtmlparser-jsilver-r10-1.5-rebased.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/DynaTableRf.gwt.xml b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/DynaTableRf.gwt.xml
index 932bfe6..4dd6e1d 100644
--- a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/DynaTableRf.gwt.xml
+++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/DynaTableRf.gwt.xml
@@ -18,7 +18,6 @@
<inherits name='com.google.gwt.user.User' />
<inherits name='com.google.gwt.editor.Editor' />
- <inherits name='com.google.gwt.app.App' />
<inherits name='com.google.gwt.requestfactory.RequestFactory' />
<inherits name='com.google.gwt.logging.Logging'/>
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/AddressEditor.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/AddressEditor.java
index 56d6936..3a210a2 100644
--- a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/AddressEditor.java
+++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/AddressEditor.java
@@ -17,7 +17,7 @@
import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.Editor;
-import com.google.gwt.editor.client.ui.ValueBoxEditorDecorator;
+import com.google.gwt.editor.ui.client.ValueBoxEditorDecorator;
import com.google.gwt.sample.dynatablerf.shared.AddressProxy;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/AddressEditor.ui.xml b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/AddressEditor.ui.xml
index 4db5bc7..52c2792 100644
--- a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/AddressEditor.ui.xml
+++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/AddressEditor.ui.xml
@@ -1,5 +1,6 @@
-<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'
- xmlns:a='urn:import:com.google.gwt.app.client' xmlns:e='urn:import:com.google.gwt.editor.client.ui'>
+<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
+ xmlns:g='urn:import:com.google.gwt.user.client.ui'
+ xmlns:e='urn:import:com.google.gwt.editor.ui.client'>
<ui:style src="../common.css">
</ui:style>
@@ -33,7 +34,7 @@
<e:ValueBoxEditorDecorator ui:field="zip"
stylePrimaryName="{style.editField}">
<e:valuebox>
- <a:IntegerBox stylePrimaryName="{style.editField}" />
+ <g:IntegerBox stylePrimaryName="{style.editField}" />
</e:valuebox>
</e:ValueBoxEditorDecorator>
<br />
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/MentorSelector.ui.xml b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/MentorSelector.ui.xml
index 7fbb781..5d365e6 100644
--- a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/MentorSelector.ui.xml
+++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/MentorSelector.ui.xml
@@ -1,6 +1,6 @@
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:dt='urn:import:com.google.gwt.sample.dynatablerf.client.widgets'
- xmlns:e='urn:import:com.google.gwt.editor.client.ui'>
+ xmlns:e='urn:import:com.google.gwt.editor.ui.client'>
<ui:style src="../common.css" />
<g:FlowPanel>
<dt:NameLabel ui:field="nameLabel" stylePrimaryName="{style.editField}" />
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/PersonEditor.java b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/PersonEditor.java
index 658ec32..0ecdd4b 100644
--- a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/PersonEditor.java
+++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/PersonEditor.java
@@ -19,7 +19,7 @@
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.editor.client.Editor;
-import com.google.gwt.editor.client.ui.ValueBoxEditorDecorator;
+import com.google.gwt.editor.ui.client.ValueBoxEditorDecorator;
import com.google.gwt.sample.dynatablerf.shared.DynaTableRequestFactory;
import com.google.gwt.sample.dynatablerf.shared.PersonProxy;
import com.google.gwt.uibinder.client.UiBinder;
diff --git a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/PersonEditor.ui.xml b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/PersonEditor.ui.xml
index 0c450e3..3b29ba3 100644
--- a/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/PersonEditor.ui.xml
+++ b/samples/dynatablerf/src/com/google/gwt/sample/dynatablerf/client/widgets/PersonEditor.ui.xml
@@ -1,6 +1,6 @@
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:dt='urn:import:com.google.gwt.sample.dynatablerf.client.widgets'
- xmlns:e='urn:import:com.google.gwt.editor.client.ui'>
+ xmlns:e='urn:import:com.google.gwt.editor.ui.client'>
<ui:style src="../common.css">
</ui:style>
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/ExpensesCommon.gwt.xml b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/ExpensesCommon.gwt.xml
index e64917c..3b81103 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/ExpensesCommon.gwt.xml
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/ExpensesCommon.gwt.xml
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 0.0.999//EN" "http://google-web-toolkit.googlecode.com/svn/tags/0.0.999/distro-source/core/src/gwt-module.dtd">
<module>
- <inherits name='com.google.gwt.app.App' />
+ <inherits name='com.google.gwt.activity.Activity' />
+ <inherits name='com.google.gwt.place.Place' />
<inherits name='com.google.gwt.requestfactory.RequestFactory'/>
<!-- <inherits name='com.google.gwt.sample.expenses.client.style.Style'/> -->
<inherits name='com.google.gwt.mobile.Mobile'/>
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/Expenses.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/Expenses.java
index f29dec2..a7bc579 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/Expenses.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/Expenses.java
@@ -19,11 +19,11 @@
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.SimpleEventBus;
-import com.google.gwt.requestfactory.client.AuthenticationFailureHandler;
-import com.google.gwt.requestfactory.client.LoginWidget;
import com.google.gwt.requestfactory.shared.Receiver;
import com.google.gwt.requestfactory.shared.RequestEvent;
import com.google.gwt.requestfactory.shared.UserInformationProxy;
+import com.google.gwt.requestfactory.ui.client.AuthenticationFailureHandler;
+import com.google.gwt.requestfactory.ui.client.LoginWidget;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobile.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobile.java
index 3c87354..24ec2f4 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobile.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobile.java
@@ -19,11 +19,11 @@
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.SimpleEventBus;
-import com.google.gwt.requestfactory.client.AuthenticationFailureHandler;
-import com.google.gwt.requestfactory.client.LoginWidget;
import com.google.gwt.requestfactory.shared.Receiver;
import com.google.gwt.requestfactory.shared.RequestEvent;
import com.google.gwt.requestfactory.shared.UserInformationProxy;
+import com.google.gwt.requestfactory.ui.client.AuthenticationFailureHandler;
+import com.google.gwt.requestfactory.ui.client.LoginWidget;
import com.google.gwt.sample.expenses.client.request.EmployeeProxy;
import com.google.gwt.sample.expenses.client.request.ExpensesRequestFactory;
import com.google.gwt.user.client.Window;
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobileShell.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobileShell.java
index e2416d4..cd848fc 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobileShell.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobileShell.java
@@ -19,7 +19,7 @@
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.shared.EventBus;
-import com.google.gwt.requestfactory.client.LoginWidget;
+import com.google.gwt.requestfactory.ui.client.LoginWidget;
import com.google.gwt.sample.expenses.client.request.EmployeeProxy;
import com.google.gwt.sample.expenses.client.request.ExpenseProxy;
import com.google.gwt.sample.expenses.client.request.ExpensesRequestFactory;
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobileShell.ui.xml b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobileShell.ui.xml
index cfb495b..6a392fd 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobileShell.ui.xml
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesMobileShell.ui.xml
@@ -2,7 +2,7 @@
<ui:UiBinder
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:m='urn:import:com.google.gwt.mobile.client'
- xmlns:r='urn:import:com.google.gwt.requestfactory.client'
+ xmlns:r='urn:import:com.google.gwt.requestfactory.ui.client'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<ui:style field='mobile' src='mobile.css'/>
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesShell.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesShell.java
index 67e5d19..9d80fa8 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesShell.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesShell.java
@@ -21,7 +21,7 @@
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.layout.client.Layout;
import com.google.gwt.layout.client.Layout.Layer;
-import com.google.gwt.requestfactory.client.LoginWidget;
+import com.google.gwt.requestfactory.ui.client.LoginWidget;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesShell.ui.xml b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesShell.ui.xml
index aea7ece..0ec4a00 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesShell.ui.xml
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/ExpensesShell.ui.xml
@@ -3,7 +3,7 @@
xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:m='urn:import:com.google.gwt.mobile.client'
- xmlns:r='urn:import:com.google.gwt.requestfactory.client'
+ xmlns:r='urn:import:com.google.gwt.requestfactory.ui.client'
xmlns:e='urn:import:com.google.gwt.sample.expenses.client'>
<ui:with field='styles' type='com.google.gwt.sample.expenses.client.style.Styles' />
diff --git a/user/src/com/google/gwt/app/place/AbstractProxyEditActivity.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/AbstractProxyEditActivity.java
similarity index 87%
rename from user/src/com/google/gwt/app/place/AbstractProxyEditActivity.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/AbstractProxyEditActivity.java
index db9793c..a2c8ada 100644
--- a/user/src/com/google/gwt/app/place/AbstractProxyEditActivity.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/AbstractProxyEditActivity.java
@@ -13,10 +13,11 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.sample.expenses.client.place;
-import com.google.gwt.app.place.ProxyPlace.Operation;
+import com.google.gwt.activity.shared.Activity;
import com.google.gwt.event.shared.EventBus;
+import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.requestfactory.client.RequestFactoryEditorDriver;
import com.google.gwt.requestfactory.shared.EntityProxy;
import com.google.gwt.requestfactory.shared.EntityProxyId;
@@ -24,18 +25,18 @@
import com.google.gwt.requestfactory.shared.RequestContext;
import com.google.gwt.requestfactory.shared.ServerFailure;
import com.google.gwt.requestfactory.shared.Violation;
+import com.google.gwt.sample.expenses.client.place.ProxyPlace.Operation;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import java.util.Set;
/**
+ * Abstract activity for editing a record. Subclasses must provide access to the
+ * request that will be fired when Save is clicked.
* <p>
- * <span style="color:red">Experimental API: This class is still under rapid
- * development, and is very likely to be deleted. Use it at your own risk.
- * </span>
- * </p>
- * Abstract activity for editing a record.
+ * Instances are not reusable. Once an activity is stoped, it cannot be
+ * restarted.
*
* @param <P> the type of Proxy being edited
*/
@@ -63,8 +64,7 @@
}
public String mayStop() {
- if (isWaiting()
- || (editorDriver != null && editorDriver.flush().isChanged())) {
+ if (isWaiting() || changed()) {
return "Are you sure you want to abandon your changes?";
}
@@ -76,10 +76,15 @@
}
public void onStop() {
+ view.setDelegate(null);
editorDriver = null;
}
public void saveClicked() {
+ if (!changed()) {
+ return;
+ }
+
setWaiting(true);
editorDriver.flush().fire(new Receiver<Void>() {
/*
@@ -158,6 +163,10 @@
return (EntityProxyId<P>) getProxy().stableId();
}
+ private boolean changed() {
+ return editorDriver != null && editorDriver.flush().isChanged();
+ }
+
/**
* @return true if we're waiting for an rpc response.
*/
diff --git a/user/src/com/google/gwt/app/place/AbstractProxyListActivity.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/AbstractProxyListActivity.java
similarity index 93%
rename from user/src/com/google/gwt/app/place/AbstractProxyListActivity.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/AbstractProxyListActivity.java
index deb1db8..5058fa1 100644
--- a/user/src/com/google/gwt/app/place/AbstractProxyListActivity.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/AbstractProxyListActivity.java
@@ -13,17 +13,21 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.sample.expenses.client.place;
-import com.google.gwt.app.place.ProxyPlace.Operation;
+import com.google.gwt.activity.shared.Activity;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.place.shared.Place;
+import com.google.gwt.place.shared.PlaceChangeEvent;
+import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.requestfactory.shared.EntityProxy;
import com.google.gwt.requestfactory.shared.EntityProxyChange;
import com.google.gwt.requestfactory.shared.EntityProxyId;
import com.google.gwt.requestfactory.shared.Receiver;
import com.google.gwt.requestfactory.shared.Request;
import com.google.gwt.requestfactory.shared.WriteOperation;
+import com.google.gwt.sample.expenses.client.place.ProxyPlace.Operation;
import com.google.gwt.user.cellview.client.AbstractHasData;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.view.client.HasData;
@@ -39,22 +43,19 @@
import java.util.Map;
/**
- * <p>
- * <span style="color:red">Experimental API: This class is still under rapid
- * development, and is very likely to be deleted. Use it at your own risk.
- * </span>
- * </p>
- * Abstract activity for requesting and displaying a list of {@link EntityProxy}
- * .
+ * Abstract activity for displaying a list of {@link EntityProxy}. These
+ * activities are not re-usable. Once they are stopped, they cannot be
+ * restarted.
* <p>
* Subclasses must:
*
* <ul>
- * <li>implement methods to provide a full count, and request a specific
* <li>provide a {@link ProxyListView}
+ * <li>implement method to request a full count
+ * <li>implement method to find a range of entities
* <li>respond to "show details" commands
* </ul>
- *
+ * <p>
* Only the properties required by the view will be requested.
*
* @param <P> the type of {@link EntityProxy} listed
@@ -185,6 +186,7 @@
}
public void start(AcceptsOneWidget display, EventBus eventBus) {
+ view.setDelegate(this);
EntityProxyChange.registerForProxyType(eventBus, proxyClass,
new EntityProxyChange.Handler<P>() {
public void onProxyChange(EntityProxyChange<P> event) {
diff --git a/user/src/com/google/gwt/app/place/AbstractProxyListView.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/AbstractProxyListView.java
similarity index 89%
rename from user/src/com/google/gwt/app/place/AbstractProxyListView.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/AbstractProxyListView.java
index ea51991..c05fdd8 100644
--- a/user/src/com/google/gwt/app/place/AbstractProxyListView.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/AbstractProxyListView.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.sample.expenses.client.place;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
@@ -24,11 +24,8 @@
import com.google.gwt.view.client.HasData;
/**
- * <p>
- * <span style="color:red">Experimental API: This class is still under rapid
- * development, and is very likely to be deleted. Use it at your own risk.
- * </span>
- *
+ * Abstract implementation of ProxyListView.
+ *
* @param <P> the type of the proxy
*/
public abstract class AbstractProxyListView<P extends EntityProxy> extends
@@ -61,6 +58,7 @@
});
}
+ @Override
protected void initWidget(Widget widget) {
throw new UnsupportedOperationException(
"AbstractRecordListView must be initialized via "
diff --git a/user/src/com/google/gwt/app/place/CreateAndEditProxy.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/CreateAndEditProxy.java
similarity index 82%
rename from user/src/com/google/gwt/app/place/CreateAndEditProxy.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/CreateAndEditProxy.java
index e5d91c7..e8fed9b 100644
--- a/user/src/com/google/gwt/app/place/CreateAndEditProxy.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/CreateAndEditProxy.java
@@ -13,32 +13,36 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.sample.expenses.client.place;
import com.google.gwt.event.shared.EventBus;
+import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.requestfactory.shared.EntityProxy;
import com.google.gwt.requestfactory.shared.RequestContext;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
/**
- * Extends {@link AbstractProxyEditActivity} to first create an instance to edit
+ * Extends {@link AbstractProxyEditActivity} to first create an instance to
+ * edit.
*
* @param <P> the type of proxy to create and edit
*/
public abstract class CreateAndEditProxy<P extends EntityProxy> extends AbstractProxyEditActivity<P> {
- private AcceptsOneWidget display;
private final P proxy;
+ private final PlaceController placeController;
+ private Class<P> proxyClass;
public CreateAndEditProxy(Class<P> proxyClass, RequestContext request,
ProxyEditView<P, ?> view, PlaceController placeController) {
super(view, placeController);
this.proxy = request.create(proxyClass);
+ this.placeController = placeController;
+ this.proxyClass = proxyClass;
}
@Override
public void start(AcceptsOneWidget display, EventBus eventBus) {
- this.display = display;
super.start(display, eventBus);
}
@@ -51,10 +55,10 @@
@Override
protected void exit(boolean saved) {
if (!saved) {
- display.setWidget(null);
+ placeController.goTo(new ProxyListPlace(proxyClass));
+ } else {
+ super.exit(saved);
}
-
- super.exit(saved);
}
@Override
diff --git a/user/src/com/google/gwt/app/place/FindAndEditProxy.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/FindAndEditProxy.java
similarity index 90%
rename from user/src/com/google/gwt/app/place/FindAndEditProxy.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/FindAndEditProxy.java
index e478456..a86ba0c 100644
--- a/user/src/com/google/gwt/app/place/FindAndEditProxy.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/FindAndEditProxy.java
@@ -13,9 +13,10 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.sample.expenses.client.place;
import com.google.gwt.event.shared.EventBus;
+import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.requestfactory.shared.EntityProxy;
import com.google.gwt.requestfactory.shared.EntityProxyId;
import com.google.gwt.requestfactory.shared.Receiver;
@@ -23,7 +24,8 @@
import com.google.gwt.user.client.ui.AcceptsOneWidget;
/**
- * Extends {@link AbstractProxyEditActivity} to work from a {@link EntityProxyId}
+ * Extends {@link AbstractProxyEditActivity} to work from a
+ * {@link EntityProxyId}.
*
* @param <P> the type of proxy to find and edit
*/
diff --git a/user/src/com/google/gwt/app/place/ProxyDetailsView.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyDetailsView.java
similarity index 83%
rename from user/src/com/google/gwt/app/place/ProxyDetailsView.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyDetailsView.java
index 94111d1..2b660d4 100644
--- a/user/src/com/google/gwt/app/place/ProxyDetailsView.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyDetailsView.java
@@ -13,17 +13,12 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.sample.expenses.client.place;
import com.google.gwt.user.client.TakesValue;
import com.google.gwt.user.client.ui.IsWidget;
/**
- * <p>
- * <span style="color:red">Experimental API: This class is still under rapid
- * development, and is very likely to be deleted. Use it at your own risk.
- * </span>
- * </p>
* Implemented by views that show the details of an object.
*
* @param <P> the type of object to show
diff --git a/user/src/com/google/gwt/app/place/ProxyEditView.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyEditView.java
similarity index 87%
rename from user/src/com/google/gwt/app/place/ProxyEditView.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyEditView.java
index 987efa5..70e9c6d 100644
--- a/user/src/com/google/gwt/app/place/ProxyEditView.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyEditView.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.sample.expenses.client.place;
import com.google.gwt.editor.client.HasEditorErrors;
import com.google.gwt.requestfactory.client.RequestFactoryEditorDriver;
@@ -21,11 +21,6 @@
import com.google.gwt.user.client.ui.IsWidget;
/**
- * <p>
- * <span style="color:red">Experimental API: This class is still under rapid
- * development, and is very likely to be deleted. Use it at your own risk.
- * </span>
- * </p>
* Implemented by views that edit {@link EntityProxy}s.
*
* @param <P> the type of the proxy
diff --git a/user/src/com/google/gwt/app/place/ProxyListPlace.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyListPlace.java
similarity index 88%
rename from user/src/com/google/gwt/app/place/ProxyListPlace.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyListPlace.java
index 25b4066..8167386 100644
--- a/user/src/com/google/gwt/app/place/ProxyListPlace.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyListPlace.java
@@ -13,14 +13,16 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.sample.expenses.client.place;
+import com.google.gwt.place.shared.Place;
+import com.google.gwt.place.shared.PlaceTokenizer;
+import com.google.gwt.place.shared.Prefix;
import com.google.gwt.requestfactory.shared.EntityProxy;
import com.google.gwt.requestfactory.shared.RequestFactory;
/**
- * A place in the app that deals with lists of {@link RequestFactory}
- * proxy objects.
+ * A place in the app that deals with lists of {@link EntityProxy}.
*/
public class ProxyListPlace extends Place {
diff --git a/user/src/com/google/gwt/app/place/ProxyListPlacePicker.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyListPlacePicker.java
similarity index 93%
rename from user/src/com/google/gwt/app/place/ProxyListPlacePicker.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyListPlacePicker.java
index 9dc11eb..0f1d3c6 100644
--- a/user/src/com/google/gwt/app/place/ProxyListPlacePicker.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyListPlacePicker.java
@@ -13,12 +13,14 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.sample.expenses.client.place;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.place.shared.PlaceChangeEvent;
+import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.user.client.ui.HasConstrainedValue;
/**
diff --git a/user/src/com/google/gwt/app/place/ProxyListView.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyListView.java
similarity index 90%
rename from user/src/com/google/gwt/app/place/ProxyListView.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyListView.java
index 2e0387c..6156ff3 100644
--- a/user/src/com/google/gwt/app/place/ProxyListView.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyListView.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.sample.expenses.client.place;
import com.google.gwt.requestfactory.shared.EntityProxy;
import com.google.gwt.user.client.ui.IsWidget;
@@ -25,8 +25,8 @@
* development, and is very likely to be deleted. Use it at your own risk.
* </span>
* </p>
- * A view of a list of {@link EntityProxy}s, which declares which properties it is
- * able to display.
+ * A view of a list of {@link EntityProxy}s, which declares which properties it
+ * is able to display.
* <p>
* It is expected that such views will typically (eventually) be defined largely
* in ui.xml files which declare the properties of interest, which is why the
@@ -45,9 +45,12 @@
}
HasData<P> asHasData();
-
+
+ /**
+ * @return the set of properties this view displays
+ */
String[] getPaths();
-
+
/**
* Sets the delegate.
*/
diff --git a/user/src/com/google/gwt/app/place/ProxyPlace.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyPlace.java
similarity index 95%
rename from user/src/com/google/gwt/app/place/ProxyPlace.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyPlace.java
index a66ae66..fdb0af8 100644
--- a/user/src/com/google/gwt/app/place/ProxyPlace.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyPlace.java
@@ -13,8 +13,11 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.sample.expenses.client.place;
+import com.google.gwt.place.shared.Place;
+import com.google.gwt.place.shared.PlaceTokenizer;
+import com.google.gwt.place.shared.Prefix;
import com.google.gwt.requestfactory.shared.EntityProxy;
import com.google.gwt.requestfactory.shared.EntityProxyId;
import com.google.gwt.requestfactory.shared.RequestFactory;
diff --git a/user/src/com/google/gwt/app/place/ProxyPlaceToListPlace.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyPlaceToListPlace.java
similarity index 78%
rename from user/src/com/google/gwt/app/place/ProxyPlaceToListPlace.java
rename to samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyPlaceToListPlace.java
index 038c321..7b15f3c 100644
--- a/user/src/com/google/gwt/app/place/ProxyPlaceToListPlace.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/place/ProxyPlaceToListPlace.java
@@ -13,16 +13,19 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.sample.expenses.client.place;
+
+import com.google.gwt.activity.shared.FilteredActivityMapper;
+import com.google.gwt.place.shared.Place;
/**
- * Converts a {@link #ProxyPlace} to a {@link ProxyListPlace}.
+ * Converts a {@link ProxyPlace} to a {@link ProxyListPlace}.
*/
public class ProxyPlaceToListPlace implements FilteredActivityMapper.Filter {
/**
- * Required by {@link FilteredActivityMapper.Filter}, calls
- * {@link #proxyListPlaceFor()}.
+ * Required by {@link com.google.gwt.app.place.FilteredActivityMapper.Filter}, calls
+ * {@link #proxyListPlaceFor}.
*/
public Place filter(Place place) {
return proxyListPlaceFor(place);
diff --git a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ReportRequest.java b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ReportRequest.java
index 08dcc10..160f277 100644
--- a/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ReportRequest.java
+++ b/samples/expenses/src/main/java/com/google/gwt/sample/expenses/client/request/ReportRequest.java
@@ -41,8 +41,8 @@
/**
* @return a request object
*/
- Request<Long> countReportsBySearch(Long employeeId,
- String department, String startsWith);
+ Request<Long> countReportsBySearch(Long employeeId, String department,
+ String startsWith);
/**
* @return a request object
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/ContentWidget.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/ContentWidget.java
index ca97c30..2610237 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/ContentWidget.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/ContentWidget.java
@@ -198,7 +198,7 @@
String className = this.getClass().getName();
className = className.substring(className.lastIndexOf(".") + 1);
sendSourceRequest(
- rc, ShowcaseConstants.DST_SOURCE_RAW + "/" + filename + ".html");
+ rc, ShowcaseConstants.DST_SOURCE_RAW + filename + ".html");
}
}
@@ -264,7 +264,7 @@
String className = this.getClass().getName();
className = className.substring(className.lastIndexOf(".") + 1);
sendSourceRequest(
- rc, ShowcaseConstants.DST_SOURCE_EXAMPLE + "/" + className + ".html");
+ rc, ShowcaseConstants.DST_SOURCE_EXAMPLE + className + ".html");
}
}
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/MainMenuTreeViewModel.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/MainMenuTreeViewModel.java
index c864ce9..3c47105 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/MainMenuTreeViewModel.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/MainMenuTreeViewModel.java
@@ -70,8 +70,10 @@
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* The {@link TreeViewModel} used by the main menu.
@@ -249,6 +251,21 @@
}
/**
+ * Get the set of all {@link ContentWidget}s used in the model.
+ *
+ * @return the {@link ContentWidget}s
+ */
+ Set<ContentWidget> getAllContentWidgets() {
+ Set<ContentWidget> widgets = new HashSet<ContentWidget>();
+ for (Category category : categories.getList()) {
+ for (ContentWidget example : category.examples.getList()) {
+ widgets.add(example);
+ }
+ }
+ return widgets;
+ }
+
+ /**
* Initialize the top level categories in the tree.
*/
private void initializeTree(ShowcaseConstants constants) {
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/Showcase.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/Showcase.java
index 75a3a0f..63c4fb9 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/Showcase.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/Showcase.java
@@ -26,17 +26,22 @@
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.i18n.client.LocaleInfo;
+import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
+import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.sample.showcase.client.MainMenuTreeViewModel.Category;
import com.google.gwt.user.cellview.client.CellTree;
import com.google.gwt.user.cellview.client.TreeNode;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootLayoutPanel;
+import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
/**
* Entry point classes define <code>onModuleLoad()</code>.
@@ -99,6 +104,7 @@
final SingleSelectionModel<ContentWidget> selectionModel = new SingleSelectionModel<ContentWidget>();
final MainMenuTreeViewModel treeModel = new MainMenuTreeViewModel(
constants, selectionModel);
+ Set<ContentWidget> contentWidgets = treeModel.getAllContentWidgets();
shell = new ShowcaseShell(treeModel);
RootLayoutPanel.get().add(shell);
@@ -176,9 +182,31 @@
ContentWidget content = (ContentWidget) category.getChildValue(0);
selectionModel.setSelected(content, true);
}
+
+ // Generate a site map.
+ createSiteMap(contentWidgets);
}
/**
+ * Create a hidden site map for crawlability.
+ *
+ * @param contentWidgets the {@link ContentWidget}s used in Showcase
+ */
+ private void createSiteMap(Set<ContentWidget> contentWidgets) {
+ SafeHtmlBuilder sb = new SafeHtmlBuilder();
+ for (ContentWidget cw : contentWidgets) {
+ String token = getContentWidgetToken(cw);
+ sb.append(SafeHtmlUtils.fromTrustedString("<a href=\"#" + token + "\">"
+ + token + "</a>"));
+ }
+
+ // Add the site map to the page.
+ HTML siteMap = new HTML(sb.toSafeHtml());
+ siteMap.setVisible(false);
+ RootPanel.get().add(siteMap, 0, 0);
+ }
+
+ /**
* Set the content to the {@link ContentWidget}.
*
* @param content the {@link ContentWidget} to display
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseShell.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseShell.java
index 6561ae8..418c02d 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseShell.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/ShowcaseShell.java
@@ -255,7 +255,15 @@
tabStyle.setVisible(content.hasStyle());
tabSource.setVisible(true);
- // Show the list of raw source files if there are any.
+ /*
+ * Show the list of raw source files if there are any. We need to add at
+ * least one option to the list for crawlability. If we do not, HtmlUnit
+ * innerHtml will close the select tag in the open tag (ie, use a forward
+ * slash instead of a separate close tag) which most browsers parse
+ * incorrectly.
+ */
+ tabSourceList.clear();
+ tabSourceList.addItem("Example");
List<String> rawFilenames = content.getRawSourceFilenames();
if (rawFilenames.size() > 0) {
String text = tabSource.getText();
@@ -263,8 +271,6 @@
tabSource.setText(text + ":");
}
tabSourceList.setVisible(true);
- tabSourceList.clear();
- tabSourceList.addItem("Example");
for (String filename : rawFilenames) {
tabSourceList.addItem(filename);
}
diff --git a/user/javadoc/com/google/gwt/examples/cell/CellExample.java b/user/javadoc/com/google/gwt/examples/cell/CellExample.java
new file mode 100644
index 0000000..2c8317c
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/cell/CellExample.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2010 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.examples.cell;
+
+import com.google.gwt.cell.client.AbstractCell;
+import com.google.gwt.cell.client.Cell;
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.safehtml.shared.SafeHtml;
+import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
+import com.google.gwt.safehtml.shared.SafeHtmlUtils;
+import com.google.gwt.user.cellview.client.CellList;
+import com.google.gwt.user.client.ui.RootPanel;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Example of creating a custom {@link Cell}.
+ */
+public class CellExample implements EntryPoint {
+
+ /**
+ * A custom {@link Cell} used to render a string that contains the name of a
+ * color.
+ */
+ private static class ColorCell extends AbstractCell<String> {
+
+ @Override
+ public void render(String value, Object key, SafeHtmlBuilder sb) {
+ /*
+ * Always do a null check on the value. Cell widgets can pass null to
+ * cells if the underlying data contains a null, or if the data arrives
+ * out of order.
+ */
+ if (value == null) {
+ return;
+ }
+
+ // If the value comes from the user, we escape it to avoid XSS attacks.
+ SafeHtml safeValue = SafeHtmlUtils.fromString(value);
+
+ // Append some HTML that sets the text color.
+ sb.appendHtmlConstant("<div style=\"color:" + safeValue.asString()
+ + "\">");
+ sb.append(safeValue);
+ sb.appendHtmlConstant("</div>");
+ }
+ }
+
+ /**
+ * The list of data to display.
+ */
+ private static final List<String> COLORS = Arrays.asList("red", "green",
+ "blue", "violet", "black", "gray");
+
+ public void onModuleLoad() {
+ // Create a cell to render each value.
+ ColorCell cell = new ColorCell();
+
+ // Use the cell in a CellList.
+ CellList<String> cellList = new CellList<String>(cell);
+
+ // Push the data into the widget.
+ cellList.setRowData(0, COLORS);
+
+ // Add it to the root panel.
+ RootPanel.get().add(cellList);
+ }
+}
\ No newline at end of file
diff --git a/user/javadoc/com/google/gwt/examples/cell/EditableCellExample.java b/user/javadoc/com/google/gwt/examples/cell/EditableCellExample.java
new file mode 100644
index 0000000..024a01b
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/cell/EditableCellExample.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2010 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.examples.cell;
+
+import com.google.gwt.cell.client.AbstractCell;
+import com.google.gwt.cell.client.Cell;
+import com.google.gwt.cell.client.ValueUpdater;
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.InputElement;
+import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.dom.client.TableCellElement;
+import com.google.gwt.dom.client.TableElement;
+import com.google.gwt.dom.client.TableRowElement;
+import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
+import com.google.gwt.user.cellview.client.CellList;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.RootPanel;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Example of creating an editable {@link Cell}. This example creates a cell
+ * that displays a Contact with a checkbox that indicates whether the contact is
+ * a favorite or not.
+ */
+public class EditableCellExample implements EntryPoint {
+
+ /**
+ * A simple data type that represents a contact.
+ */
+ private static class Contact {
+ private final String address;
+ private final String name;
+
+ public Contact(String name, String address) {
+ this.name = name;
+ this.address = address;
+ }
+ }
+
+ /**
+ * A custom {@link Cell} used to render a {@link Contact}. We extend
+ * {@link AbstractCell} because it provides reasonable implementations of
+ * methods that work for most use cases.
+ */
+ private class ContactCell extends AbstractCell<Contact> {
+
+ public ContactCell() {
+ // Our cell responds to change events and keydown events.
+ super("change", "keydown");
+ }
+
+ @Override
+ public void onBrowserEvent(Element parent, Contact value, Object key,
+ NativeEvent event, ValueUpdater<Contact> valueUpdater) {
+ // Check that the value is not null.
+ if (value == null) {
+ return;
+ }
+
+ // Call the super handler, which handlers the enter key.
+ super.onBrowserEvent(parent, value, key, event, valueUpdater);
+
+ // Handle click events.
+ if ("change".equals(event.getType())) {
+ updateFavorites(parent, value);
+ showCurrentFavorites();
+ }
+ }
+
+ @Override
+ public void render(Contact value, Object key, SafeHtmlBuilder sb) {
+ /*
+ * Always do a null check on the value. Cell widgets can pass null to
+ * cells if the underlying data contains a null, or if the data arrives
+ * out of order.
+ */
+ if (value == null) {
+ return;
+ }
+
+ // Add a checkbox. If the contact is a favorite, the box will be checked.
+ sb.appendHtmlConstant("<table><tr><td valign=\"top\">");
+ if (favorites.contains(value)) {
+ sb.appendHtmlConstant("<input type=\"checkbox\" checked=checked/>");
+ } else {
+ sb.appendHtmlConstant("<input type=\"checkbox\" />");
+ }
+ sb.appendHtmlConstant("</td><td>");
+
+ // Display the name in big letters.
+ sb.appendHtmlConstant("<div style=\"size:200%;font-weight:bold;\">");
+ sb.appendEscaped(value.name);
+ sb.appendHtmlConstant("</div>");
+
+ // Display the address in normal text.
+ sb.appendHtmlConstant("<div style=\"padding-left:10px;\">");
+ sb.appendEscaped(value.address);
+ sb.appendHtmlConstant("</div>");
+
+ sb.appendHtmlConstant("</td></tr></table>");
+ }
+
+ /**
+ * By convention, cells that respond to user events should handle the enter
+ * key. This provides a consistent user experience when users use keyboard
+ * navigation in the widget. Our cell will toggle the checkbox on Enter.
+ */
+ @Override
+ protected void onEnterKeyDown(Element parent, Contact value, Object key,
+ NativeEvent event, ValueUpdater<Contact> valueUpdater) {
+ // Toggle the checkbox.
+ InputElement input = getInputElement(parent);
+ input.setChecked(!input.isChecked());
+
+ // Update the favorites based on the new state.
+ updateFavorites(parent, value);
+
+ // Show the new list of favorites.
+ showCurrentFavorites();
+ }
+
+ /**
+ * Get the checkbox input element from the parent element that wraps our
+ * cell.
+ *
+ * @param parent the parent element
+ * @return the checkbox
+ */
+ private InputElement getInputElement(Element parent) {
+ // We need to navigate down to our input element.
+ TableElement table = parent.getFirstChildElement().cast();
+ TableRowElement tr = table.getRows().getItem(0);
+ TableCellElement td = tr.getCells().getItem(0);
+ InputElement input = td.getFirstChildElement().cast();
+ return input;
+ }
+
+ /**
+ * Update the favorites list based on the state of the input element.
+ */
+ private void updateFavorites(Element parent, Contact value) {
+ // Get the input element.
+ InputElement input = getInputElement(parent);
+
+ // Update the favorites based on the checked state.
+ if (input.isChecked()) {
+ favorites.add(value);
+ } else {
+ favorites.remove(value);
+ }
+ }
+ }
+
+ /**
+ * The list of data to display.
+ */
+ private static final List<Contact> CONTACTS = Arrays.asList(new Contact(
+ "John", "123 Fourth Avenue"), new Contact("Joe", "22 Lance Ln"),
+ new Contact("Michael", "1283 Berry Blvd"), new Contact("Sarah",
+ "100 Hundred St."), new Contact("George", "1600 Pennsylvania Avenue"));
+
+ /**
+ * Our list of favorite contacts.
+ */
+ private final List<Contact> favorites = new ArrayList<EditableCellExample.Contact>();
+
+ public void onModuleLoad() {
+ // Create a cell to render each value.
+ ContactCell contactCell = new ContactCell();
+
+ // Use the cell in a CellList.
+ CellList<Contact> cellList = new CellList<Contact>(contactCell);
+
+ // Push the data into the widget.
+ cellList.setRowData(0, CONTACTS);
+
+ // Add it to the root panel.
+ RootPanel.get().add(cellList);
+ }
+
+ /**
+ * Show the list of favorites.
+ */
+ private void showCurrentFavorites() {
+ if (favorites.size() > 0) {
+ String text = "You favorite contacts are ";
+ boolean first = true;
+ for (Contact contact : favorites) {
+ if (!first) {
+ text += ", ";
+ } else {
+ first = false;
+ }
+ text += contact.name;
+ }
+ Window.alert(text);
+ } else {
+ Window.alert("You have not selected any favorites.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/user/javadoc/com/google/gwt/examples/cell/InteractionCellExample.java b/user/javadoc/com/google/gwt/examples/cell/InteractionCellExample.java
new file mode 100644
index 0000000..ceaa7a3
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/cell/InteractionCellExample.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2010 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.examples.cell;
+
+import com.google.gwt.cell.client.AbstractCell;
+import com.google.gwt.cell.client.Cell;
+import com.google.gwt.cell.client.ValueUpdater;
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.i18n.client.DateTimeFormat;
+import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
+import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
+import com.google.gwt.safehtml.shared.SafeHtmlUtils;
+import com.google.gwt.user.cellview.client.CellList;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.RootPanel;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Example of creating a custom {@link Cell} that responds to events. This
+ * example creates a cell that displays a Contact in a custom format.
+ */
+public class InteractionCellExample implements EntryPoint {
+
+ /**
+ * A simple data type that represents a contact.
+ */
+ private static class Contact {
+ private final String address;
+ private final Date birthday;
+ private final String name;
+
+ public Contact(String name, Date birthday, String address) {
+ this.name = name;
+ this.birthday = birthday;
+ this.address = address;
+ }
+ }
+
+ /**
+ * A custom {@link Cell} used to render a {@link Contact}. We extend
+ * {@link AbstractCell} because it provides reasonable implementations of
+ * methods that work for most use cases.
+ */
+ private static class ContactCell extends AbstractCell<Contact> {
+
+ /**
+ * The {@link DateTimeFormat} used to format the birthday. Since our render
+ * method is called for every value in the list, we want to move heavy
+ * weight work, such as creating a formatter, out of it to speed up
+ * rendering as much as possible.
+ */
+ private DateTimeFormat dateFormat = DateTimeFormat.getFormat(PredefinedFormat.DATE_LONG);
+
+ public ContactCell() {
+ /*
+ * Let the parent class know that our cell responds to click events and
+ * keydown events.
+ */
+ super("click", "keydown");
+ }
+
+ @Override
+ public void onBrowserEvent(Element parent, Contact value, Object key,
+ NativeEvent event, ValueUpdater<Contact> valueUpdater) {
+ // Check that the value is not null.
+ if (value == null) {
+ return;
+ }
+
+ // Call the super handler, which handlers the enter key.
+ super.onBrowserEvent(parent, value, key, event, valueUpdater);
+
+ // On click, perform the same action that we perform on enter.
+ if ("click".equals(event.getType())) {
+ this.onEnterKeyDown(parent, value, key, event, valueUpdater);
+ }
+ }
+
+ @Override
+ public void render(Contact value, Object key, SafeHtmlBuilder sb) {
+ /*
+ * Always do a null check on the value. Cell widgets can pass null to
+ * cells if the underlying data contains a null, or if the data arrives
+ * out of order.
+ */
+ if (value == null) {
+ return;
+ }
+
+ // Display the name in big letters.
+ sb.appendHtmlConstant("<div style=\"size:200%;font-weight:bold;\">");
+ sb.appendEscaped(value.name);
+ sb.appendHtmlConstant("</div>");
+
+ // Display the address in normal text.
+ sb.appendHtmlConstant("<div style=\"padding-left:10px;\">");
+ sb.appendEscaped(value.address);
+ sb.appendHtmlConstant("</div>");
+
+ // Format that birthday and display it in light gray.
+ sb.appendHtmlConstant("<div style=\"padding-left:10px;color:#aaa;\">");
+ sb.append(SafeHtmlUtils.fromTrustedString("Born: "));
+ sb.appendEscaped(dateFormat.format(value.birthday));
+ sb.appendHtmlConstant("</div>");
+ }
+
+ /**
+ * By convention, cells that respond to user events should handle the enter
+ * key. This provides a consistent user experience when users use keyboard
+ * navigation in the widget.
+ */
+ @Override
+ protected void onEnterKeyDown(Element parent, Contact value, Object key,
+ NativeEvent event, ValueUpdater<Contact> valueUpdater) {
+ Window.alert("You clicked " + value.name);
+ }
+ }
+
+ /**
+ * The list of data to display.
+ */
+ private static final List<Contact> CONTACTS = Arrays.asList(new Contact(
+ "John", new Date(80, 4, 12), "123 Fourth Avenue"), new Contact("Joe",
+ new Date(85, 2, 22), "22 Lance Ln"), new Contact("Michael", new Date(80,
+ 1, 2), "1283 Berry Blvd"), new Contact("Sarah", new Date(67, 10, 28),
+ "100 Hundred St."), new Contact("George", new Date(46, 6, 6),
+ "1600 Pennsylvania Avenue"));
+
+ public void onModuleLoad() {
+ // Create a cell to render each value.
+ ContactCell contactCell = new ContactCell();
+
+ // Use the cell in a CellList.
+ CellList<Contact> cellList = new CellList<Contact>(contactCell);
+
+ // Push the data into the widget.
+ cellList.setRowData(0, CONTACTS);
+
+ // Add it to the root panel.
+ RootPanel.get().add(cellList);
+ }
+}
\ No newline at end of file
diff --git a/user/javadoc/com/google/gwt/examples/cellview/CellBrowserExample.java b/user/javadoc/com/google/gwt/examples/cellview/CellBrowserExample.java
new file mode 100644
index 0000000..225f607
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/cellview/CellBrowserExample.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2010 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.examples.cellview;
+
+import com.google.gwt.cell.client.TextCell;
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.user.cellview.client.CellBrowser;
+import com.google.gwt.user.client.ui.RootLayoutPanel;
+import com.google.gwt.view.client.ListDataProvider;
+import com.google.gwt.view.client.TreeViewModel;
+
+/**
+ * Example of {@link CellBrowser}. This example shows a Browser consisting of
+ * strings.
+ */
+public class CellBrowserExample implements EntryPoint {
+
+ /**
+ * The model that defines the nodes in the tree.
+ */
+ private static class CustomTreeModel implements TreeViewModel {
+
+ /**
+ * Get the {@link NodeInfo} that provides the children of the specified
+ * value.
+ */
+ public <T> NodeInfo<?> getNodeInfo(T value) {
+ /*
+ * Create some data in a data provider. Use the parent value as a prefix
+ * for the next level.
+ */
+ ListDataProvider<String> dataProvider = new ListDataProvider<String>();
+ for (int i = 0; i < 2; i++) {
+ dataProvider.getList().add(value + "." + String.valueOf(i));
+ }
+
+ // Return a node info that pairs the data with a cell.
+ return new DefaultNodeInfo<String>(dataProvider, new TextCell());
+ }
+
+ /**
+ * Check if the specified value represents a leaf node. Leaf nodes cannot be
+ * opened.
+ */
+ public boolean isLeaf(Object value) {
+ // The maximum length of a value is ten characters.
+ return value.toString().length() > 10;
+ }
+ }
+
+ public void onModuleLoad() {
+ // Create a model for the browser.
+ TreeViewModel model = new CustomTreeModel();
+
+ /*
+ * Create the browser using the model. We specify the default value of the
+ * hidden root node as "Item 1".
+ */
+ CellBrowser tree = new CellBrowser(model, "Item 1");
+
+ // Add the tree to the root layout panel.
+ RootLayoutPanel.get().add(tree);
+ }
+}
diff --git a/user/javadoc/com/google/gwt/examples/cellview/CellBrowserExample2.java b/user/javadoc/com/google/gwt/examples/cellview/CellBrowserExample2.java
new file mode 100644
index 0000000..af538a9
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/cellview/CellBrowserExample2.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2010 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.examples.cellview;
+
+import com.google.gwt.cell.client.AbstractCell;
+import com.google.gwt.cell.client.Cell;
+import com.google.gwt.cell.client.TextCell;
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
+import com.google.gwt.user.cellview.client.CellBrowser;
+import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
+import com.google.gwt.user.client.ui.RootLayoutPanel;
+import com.google.gwt.view.client.ListDataProvider;
+import com.google.gwt.view.client.SingleSelectionModel;
+import com.google.gwt.view.client.TreeViewModel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Example of {@link CellBrowser}. This example shows a browser consisting of
+ * composers and the compositions they created.
+ */
+public class CellBrowserExample2 implements EntryPoint {
+
+ /**
+ * A list of songs.
+ */
+ private static class Playlist {
+ private final String name;
+ private final List<String> songs = new ArrayList<String>();
+
+ public Playlist(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Add a song to the playlist.
+ *
+ * @param name the name of the song
+ */
+ public void addSong(String name) {
+ songs.add(name);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return the list of songs in the playlist
+ */
+ public List<String> getSongs() {
+ return songs;
+ }
+ }
+
+ /**
+ * A composer of classical music.
+ */
+ private static class Composer {
+ private final String name;
+ private final List<Playlist> playlists = new ArrayList<Playlist>();
+
+ public Composer(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Add a playlist to the composer.
+ *
+ * @param playlist the playlist to add
+ */
+ public Playlist addPlaylist(Playlist playlist) {
+ playlists.add(playlist);
+ return playlist;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return the rockin' playlist for this composter
+ */
+ public List<Playlist> getPlaylists() {
+ return playlists;
+ }
+ }
+
+ /**
+ * The model that defines the nodes in the tree.
+ */
+ private static class CustomTreeModel implements TreeViewModel {
+
+ private final List<Composer> composers;
+
+ /**
+ * This selection model is shared across all leaf nodes. A selection model
+ * can also be shared across all nodes in the tree, or each set of child
+ * nodes can have its own instance. This gives you flexibility to determine
+ * how nodes are selected.
+ */
+ private final SingleSelectionModel<String> selectionModel = new SingleSelectionModel<String>();
+
+ public CustomTreeModel() {
+ // Create a database of information.
+ composers = new ArrayList<Composer>();
+
+ // Add compositions by Beethoven.
+ {
+ Composer beethoven = new Composer("Beethoven");
+ composers.add(beethoven);
+
+ Playlist concertos = beethoven.addPlaylist(new Playlist("Concertos"));
+ concertos.addSong("No. 1 - C");
+ concertos.addSong("No. 2 - B-Flat Major");
+ concertos.addSong("No. 3 - C Minor");
+ concertos.addSong("No. 4 - G Major");
+ concertos.addSong("No. 5 - E-Flat Major");
+
+ Playlist quartets = beethoven.addPlaylist(new Playlist("Quartets"));
+ quartets.addSong("Six String Quartets");
+ quartets.addSong("Three String Quartets");
+ quartets.addSong("Grosse Fugue for String Quartets");
+
+ Playlist sonatas = beethoven.addPlaylist(new Playlist("Sonatas"));
+ sonatas.addSong("Sonata in A Minor");
+ sonatas.addSong("Sonata in F Major");
+
+ Playlist symphonies = beethoven.addPlaylist(new Playlist("Symphonies"));
+ symphonies.addSong("No. 2 - D Major");
+ symphonies.addSong("No. 2 - D Major");
+ symphonies.addSong("No. 3 - E-Flat Major");
+ symphonies.addSong("No. 4 - B-Flat Major");
+ symphonies.addSong("No. 5 - C Minor");
+ symphonies.addSong("No. 6 - F Major");
+ symphonies.addSong("No. 7 - A Major");
+ symphonies.addSong("No. 8 - F Major");
+ symphonies.addSong("No. 9 - D Minor");
+ }
+
+ // Add compositions by Brahms.
+ {
+ Composer brahms = new Composer("Brahms");
+ composers.add(brahms);
+ Playlist concertos = brahms.addPlaylist(new Playlist("Concertos"));
+ concertos.addSong("Violin Concerto");
+ concertos.addSong("Double Concerto - A Minor");
+ concertos.addSong("Piano Concerto No. 1 - D Minor");
+ concertos.addSong("Piano Concerto No. 2 - B-Flat Major");
+
+ Playlist quartets = brahms.addPlaylist(new Playlist("Quartets"));
+ quartets.addSong("Piano Quartet No. 1 - G Minor");
+ quartets.addSong("Piano Quartet No. 2 - A Major");
+ quartets.addSong("Piano Quartet No. 3 - C Minor");
+ quartets.addSong("String Quartet No. 3 - B-Flat Minor");
+
+ Playlist sonatas = brahms.addPlaylist(new Playlist("Sonatas"));
+ sonatas.addSong("Two Sonatas for Clarinet - F Minor");
+ sonatas.addSong("Two Sonatas for Clarinet - E-Flat Major");
+
+ Playlist symphonies = brahms.addPlaylist(new Playlist("Symphonies"));
+ symphonies.addSong("No. 1 - C Minor");
+ symphonies.addSong("No. 2 - D Minor");
+ symphonies.addSong("No. 3 - F Major");
+ symphonies.addSong("No. 4 - E Minor");
+ }
+
+ // Add compositions by Mozart.
+ {
+ Composer mozart = new Composer("Mozart");
+ composers.add(mozart);
+ Playlist concertos = mozart.addPlaylist(new Playlist("Concertos"));
+ concertos.addSong("Piano Concerto No. 12");
+ concertos.addSong("Piano Concerto No. 17");
+ concertos.addSong("Clarinet Concerto");
+ concertos.addSong("Violin Concerto No. 5");
+ concertos.addSong("Violin Concerto No. 4");
+ }
+ }
+
+ /**
+ * Get the {@link NodeInfo} that provides the children of the specified
+ * value.
+ */
+ public <T> NodeInfo<?> getNodeInfo(T value) {
+ if (value == null) {
+ // LEVEL 0.
+ // We passed null as the root value. Return the composers.
+
+ // Create a data provider that contains the list of composers.
+ ListDataProvider<Composer> dataProvider = new ListDataProvider<CellBrowserExample2.Composer>(
+ composers);
+
+ // Create a cell to display a composer.
+ Cell<Composer> cell = new AbstractCell<Composer>() {
+ @Override
+ public void render(Composer value, Object key, SafeHtmlBuilder sb) {
+ if (value != null) {
+ sb.appendEscaped(value.getName());
+ }
+ }
+ };
+
+ // Return a node info that pairs the data provider and the cell.
+ return new DefaultNodeInfo<Composer>(dataProvider, cell);
+ } else if (value instanceof Composer) {
+ // LEVEL 1.
+ // We want the children of the composer. Return the playlists.
+ ListDataProvider<Playlist> dataProvider = new ListDataProvider<Playlist>(
+ ((Composer) value).getPlaylists());
+ Cell<Playlist> cell = new AbstractCell<Playlist>() {
+ @Override
+ public void render(Playlist value, Object key, SafeHtmlBuilder sb) {
+ if (value != null) {
+ sb.appendEscaped(value.getName());
+ }
+ }
+ };
+ return new DefaultNodeInfo<Playlist>(dataProvider, cell);
+ } else if (value instanceof Playlist) {
+ // LEVEL 2 - LEAF.
+ // We want the children of the playlist. Return the songs.
+ ListDataProvider<String> dataProvider = new ListDataProvider<String>(
+ ((Playlist) value).getSongs());
+
+ // Use the shared selection model.
+ return new DefaultNodeInfo<String>(dataProvider, new TextCell(),
+ selectionModel, null);
+ }
+
+ return null;
+ }
+
+ /**
+ * Check if the specified value represents a leaf node. Leaf nodes cannot be
+ * opened.
+ */
+ public boolean isLeaf(Object value) {
+ // The leaf nodes are the songs, which are Strings.
+ if (value instanceof String) {
+ return true;
+ }
+ return false;
+ }
+
+ }
+
+ public void onModuleLoad() {
+ // Create a model for the browser.
+ TreeViewModel model = new CustomTreeModel();
+
+ /*
+ * Create the browser using the model. We use <code>null</code> as the
+ * default value of the root node. The default value will be passed to
+ * CustomTreeModel#getNodeInfo();
+ */
+ CellBrowser browser = new CellBrowser(model, null);
+ browser.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
+
+ // Add the browser to the root layout panel.
+ RootLayoutPanel.get().add(browser);
+ }
+}
diff --git a/user/javadoc/com/google/gwt/examples/cellview/CellListExample.java b/user/javadoc/com/google/gwt/examples/cellview/CellListExample.java
new file mode 100644
index 0000000..a75b009
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/cellview/CellListExample.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2010 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.examples.cellview;
+
+import com.google.gwt.cell.client.TextCell;
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.user.cellview.client.CellList;
+import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.view.client.SelectionChangeEvent;
+import com.google.gwt.view.client.SingleSelectionModel;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Example of {@link CellList}. This example shows a list of the days of the
+ * week.
+ */
+public class CellListExample implements EntryPoint {
+
+ /**
+ * The list of data to display.
+ */
+ private static final List<String> DAYS = Arrays.asList("Sunday", "Monday",
+ "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday");
+
+ public void onModuleLoad() {
+ // Create a cell to render each value.
+ TextCell textCell = new TextCell();
+
+ // Create a CellList that uses the cell.
+ CellList<String> cellList = new CellList<String>(textCell);
+ cellList.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
+
+ // Add a selection model to handle user selection.
+ final SingleSelectionModel<String> selectionModel = new SingleSelectionModel<String>();
+ cellList.setSelectionModel(selectionModel);
+ selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
+ public void onSelectionChange(SelectionChangeEvent event) {
+ String selected = selectionModel.getSelectedObject();
+ if (selected != null) {
+ Window.alert("You selected: " + selected);
+ }
+ }
+ });
+
+ // Set the total row count. This isn't strictly necessary, but it affects
+ // paging calculations, so its good habit to keep the row count up to date.
+ cellList.setRowCount(DAYS.size(), true);
+
+ // Push the data into the widget.
+ cellList.setRowData(0, DAYS);
+
+ // Add it to the root panel.
+ RootPanel.get().add(cellList);
+ }
+}
\ No newline at end of file
diff --git a/user/javadoc/com/google/gwt/examples/cellview/CellListValueUpdaterExample.java b/user/javadoc/com/google/gwt/examples/cellview/CellListValueUpdaterExample.java
new file mode 100644
index 0000000..b700ecc
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/cellview/CellListValueUpdaterExample.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2010 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.examples.cellview;
+
+import com.google.gwt.cell.client.TextInputCell;
+import com.google.gwt.cell.client.ValueUpdater;
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.user.cellview.client.CellList;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.RootPanel;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Example of using a {@link ValueUpdater} with a {@link CellList}.
+ */
+public class CellListValueUpdaterExample implements EntryPoint {
+
+ /**
+ * The list of data to display.
+ */
+ private static final List<String> DAYS = Arrays.asList("Sunday", "Monday",
+ "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday");
+
+ public void onModuleLoad() {
+ // Create a cell that will interact with a value updater.
+ TextInputCell inputCell = new TextInputCell();
+
+ // Create a CellList that uses the cell.
+ CellList<String> cellList = new CellList<String>(inputCell);
+
+ // Create a value updater that will be called when the value in a cell
+ // changes.
+ ValueUpdater<String> valueUpdater = new ValueUpdater<String>() {
+ public void update(String newValue) {
+ Window.alert("You typed: " + newValue);
+ }
+ };
+
+ // Add the value updater to the cellList.
+ cellList.setValueUpdater(valueUpdater);
+
+ // Set the total row count. This isn't strictly necessary, but it affects
+ // paging calculations, so its good habit to keep the row count up to date.
+ cellList.setRowCount(DAYS.size(), true);
+
+ // Push the data into the widget.
+ cellList.setRowData(0, DAYS);
+
+ // Add it to the root panel.
+ RootPanel.get().add(cellList);
+ }
+}
\ No newline at end of file
diff --git a/user/javadoc/com/google/gwt/examples/cellview/CellTableExample.java b/user/javadoc/com/google/gwt/examples/cellview/CellTableExample.java
new file mode 100644
index 0000000..46a7b87
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/cellview/CellTableExample.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2010 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.examples.cellview;
+
+import com.google.gwt.cell.client.DateCell;
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.user.cellview.client.CellTable;
+import com.google.gwt.user.cellview.client.Column;
+import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
+import com.google.gwt.user.cellview.client.TextColumn;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.view.client.SelectionChangeEvent;
+import com.google.gwt.view.client.SingleSelectionModel;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Example of {@link CellTable}. This example shows a table containing contact
+ * information.
+ */
+public class CellTableExample implements EntryPoint {
+
+ /**
+ * A simple data type that represents a contact.
+ */
+ private static class Contact {
+ private final String address;
+ private final Date birthday;
+ private final String name;
+
+ public Contact(String name, Date birthday, String address) {
+ this.name = name;
+ this.birthday = birthday;
+ this.address = address;
+ }
+ }
+
+ /**
+ * The list of data to display.
+ */
+ private static final List<Contact> CONTACTS = Arrays.asList(
+ new Contact("John", new Date(80, 4, 12), "123 Fourth Avenue"),
+ new Contact("Joe", new Date(85, 2, 22), "22 Lance Ln"),
+ new Contact("George", new Date(46, 6, 6), "1600 Pennsylvania Avenue"));
+
+ public void onModuleLoad() {
+ // Create a CellTable.
+ CellTable<Contact> table = new CellTable<Contact>();
+ table.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
+
+ // Add a text column to show the name.
+ TextColumn<Contact> nameColumn = new TextColumn<Contact>() {
+ @Override
+ public String getValue(Contact object) {
+ return object.name;
+ }
+ };
+ table.addColumn(nameColumn, "Name");
+
+ // Add a date column to show the birthday.
+ DateCell dateCell = new DateCell();
+ Column<Contact, Date> dateColumn = new Column<Contact, Date>(dateCell) {
+ @Override
+ public Date getValue(Contact object) {
+ return object.birthday;
+ }
+ };
+ table.addColumn(dateColumn, "Birthday");
+
+ // Add a text column to show the address.
+ TextColumn<Contact> addressColumn = new TextColumn<Contact>() {
+ @Override
+ public String getValue(Contact object) {
+ return object.address;
+ }
+ };
+ table.addColumn(addressColumn, "Address");
+
+ // Add a selection model to handle user selection.
+ final SingleSelectionModel<Contact> selectionModel = new SingleSelectionModel<Contact>();
+ table.setSelectionModel(selectionModel);
+ selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
+ public void onSelectionChange(SelectionChangeEvent event) {
+ Contact selected = selectionModel.getSelectedObject();
+ if (selected != null) {
+ Window.alert("You selected: " + selected.name);
+ }
+ }
+ });
+
+ // Set the total row count. This isn't strictly necessary, but it affects
+ // paging calculations, so its good habit to keep the row count up to date.
+ table.setRowCount(CONTACTS.size(), true);
+
+ // Push the data into the widget.
+ table.setRowData(0, CONTACTS);
+
+ // Add it to the root panel.
+ RootPanel.get().add(table);
+ }
+}
\ No newline at end of file
diff --git a/user/javadoc/com/google/gwt/examples/cellview/CellTableFieldUpdaterExample.java b/user/javadoc/com/google/gwt/examples/cellview/CellTableFieldUpdaterExample.java
new file mode 100644
index 0000000..5ef66b7
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/cellview/CellTableFieldUpdaterExample.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2010 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.examples.cellview;
+
+import com.google.gwt.cell.client.DatePickerCell;
+import com.google.gwt.cell.client.FieldUpdater;
+import com.google.gwt.cell.client.TextInputCell;
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.i18n.client.DateTimeFormat;
+import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
+import com.google.gwt.user.cellview.client.CellTable;
+import com.google.gwt.user.cellview.client.Column;
+import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
+import com.google.gwt.user.cellview.client.TextColumn;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.view.client.ProvidesKey;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Example of using a {@link FieldUpdater} with a {@link CellTable}.
+ */
+public class CellTableFieldUpdaterExample implements EntryPoint {
+
+ /**
+ * A simple data type that represents a contact with a unique ID.
+ */
+ private static class Contact {
+ private static int nextId = 0;
+
+ private final int id;
+ private final String address;
+ private Date birthday;
+ private String name;
+
+ public Contact(String name, Date birthday, String address) {
+ nextId++;
+ this.id = nextId;
+ this.name = name;
+ this.birthday = birthday;
+ this.address = address;
+ }
+ }
+
+ /**
+ * The list of data to display.
+ */
+ private static final List<Contact> CONTACTS = Arrays.asList(
+ new Contact("John", new Date(80, 4, 12), "123 Fourth Avenue"),
+ new Contact("Joe", new Date(85, 2, 22), "22 Lance Ln"),
+ new Contact("George", new Date(46, 6, 6), "1600 Pennsylvania Avenue"));
+
+ /**
+ * The key provider that allows us to identify Contacts even if a field
+ * changes. We identify contacts by their unique ID.
+ */
+ private static final ProvidesKey<Contact> KEY_PROVIDER = new ProvidesKey<CellTableFieldUpdaterExample.Contact>() {
+ public Object getKey(Contact item) {
+ return item.id;
+ }
+ };
+
+ public void onModuleLoad() {
+ // Create a CellTable with a key provider.
+ final CellTable<Contact> table = new CellTable<Contact>(KEY_PROVIDER);
+ table.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
+
+ // Add a text input column to edit the name.
+ final TextInputCell nameCell = new TextInputCell();
+ Column<Contact, String> nameColumn = new Column<Contact, String>(nameCell) {
+ @Override
+ public String getValue(Contact object) {
+ return object.name;
+ }
+ };
+ table.addColumn(nameColumn, "Name");
+
+ // Add a field updater to be notified when the user enters a new name.
+ nameColumn.setFieldUpdater(new FieldUpdater<Contact, String>() {
+ public void update(int index, Contact object, String value) {
+ // Validate the data.
+ if (value.length() < 3) {
+ Window.alert("Names must be at least three characters long.");
+
+ /*
+ * Clear the view data. The view data contains the pending change and
+ * allows the table to render with the pending value until the data is
+ * committed. If the data is committed into the object, the view data
+ * is automatically cleared out. If the data is not committed because
+ * it is invalid, you must delete.
+ */
+ nameCell.clearViewData(KEY_PROVIDER.getKey(object));
+
+ // Redraw the table.
+ table.redraw();
+ return;
+ }
+
+ // Inform the user of the change.
+ Window.alert("You changed the name of " + object.name + " to " + value);
+
+ // Push the changes into the Contact. At this point, you could send an
+ // asynchronous request to the server to update the database.
+ object.name = value;
+
+ // Redraw the table with the new data.
+ table.redraw();
+ }
+ });
+
+ // Add a date column to show the birthday.
+ Column<Contact, Date> dateColumn = new Column<Contact, Date>(
+ new DatePickerCell()) {
+ @Override
+ public Date getValue(Contact object) {
+ return object.birthday;
+ }
+ };
+ table.addColumn(dateColumn, "Birthday");
+
+ // Add a field updater to be notified when the user enters a new birthday.
+ dateColumn.setFieldUpdater(new FieldUpdater<Contact, Date>() {
+ public void update(int index, Contact object, Date value) {
+ Window.alert("You changed the birthday of "
+ + object.name
+ + " to "
+ + DateTimeFormat.getFormat(PredefinedFormat.DATE_LONG).format(value));
+
+ // Push the changes into the Contact.
+ object.birthday = value;
+
+ // Redraw the table with the new data.
+ table.redraw();
+ }
+ });
+ // Add a text column to show the address.
+ TextColumn<Contact> addressColumn = new TextColumn<Contact>() {
+ @Override
+ public String getValue(Contact object) {
+ return object.address;
+ }
+ };
+ table.addColumn(addressColumn, "Address");
+
+ // Set the total row count. This isn't strictly necessary, but it affects
+ // paging calculations, so its good habit to keep the row count up to date.
+ table.setRowCount(CONTACTS.size(), true);
+
+ // Push the data into the widget.
+ table.setRowData(0, CONTACTS);
+
+ // Add it to the root panel.
+ RootPanel.get().add(table);
+ }
+}
\ No newline at end of file
diff --git a/user/javadoc/com/google/gwt/examples/cellview/CellTreeExample.java b/user/javadoc/com/google/gwt/examples/cellview/CellTreeExample.java
new file mode 100644
index 0000000..777baa2
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/cellview/CellTreeExample.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2010 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.examples.cellview;
+
+import com.google.gwt.cell.client.TextCell;
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.user.cellview.client.CellTree;
+import com.google.gwt.user.client.ui.RootLayoutPanel;
+import com.google.gwt.view.client.ListDataProvider;
+import com.google.gwt.view.client.TreeViewModel;
+
+/**
+ * Example of {@link CellTree}. This example shows a Tree consisting of strings.
+ */
+public class CellTreeExample implements EntryPoint {
+
+ /**
+ * The model that defines the nodes in the tree.
+ */
+ private static class CustomTreeModel implements TreeViewModel {
+
+ /**
+ * Get the {@link NodeInfo} that provides the children of the specified
+ * value.
+ */
+ public <T> NodeInfo<?> getNodeInfo(T value) {
+ /*
+ * Create some data in a data provider. Use the parent value as a prefix
+ * for the next level.
+ */
+ ListDataProvider<String> dataProvider = new ListDataProvider<String>();
+ for (int i = 0; i < 2; i++) {
+ dataProvider.getList().add(value + "." + String.valueOf(i));
+ }
+
+ // Return a node info that pairs the data with a cell.
+ return new DefaultNodeInfo<String>(dataProvider, new TextCell());
+ }
+
+ /**
+ * Check if the specified value represents a leaf node. Leaf nodes cannot be
+ * opened.
+ */
+ public boolean isLeaf(Object value) {
+ // The maximum length of a value is ten characters.
+ return value.toString().length() > 10;
+ }
+ }
+
+ public void onModuleLoad() {
+ // Create a model for the tree.
+ TreeViewModel model = new CustomTreeModel();
+
+ /*
+ * Create the tree using the model. We specify the default value of the
+ * hidden root node as "Item 1".
+ */
+ CellTree tree = new CellTree(model, "Item 1");
+
+ // Add the tree to the root layout panel.
+ RootLayoutPanel.get().add(tree);
+ }
+}
diff --git a/user/javadoc/com/google/gwt/examples/cellview/CellTreeExample2.java b/user/javadoc/com/google/gwt/examples/cellview/CellTreeExample2.java
new file mode 100644
index 0000000..f51dbec
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/cellview/CellTreeExample2.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2010 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.examples.cellview;
+
+import com.google.gwt.cell.client.AbstractCell;
+import com.google.gwt.cell.client.Cell;
+import com.google.gwt.cell.client.TextCell;
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
+import com.google.gwt.user.cellview.client.CellTree;
+import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
+import com.google.gwt.user.cellview.client.TreeNode;
+import com.google.gwt.user.client.ui.RootLayoutPanel;
+import com.google.gwt.view.client.ListDataProvider;
+import com.google.gwt.view.client.SingleSelectionModel;
+import com.google.gwt.view.client.TreeViewModel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Example of {@link CellTree}. This example shows a Tree consisting of
+ * composers and the compositions they created.
+ */
+public class CellTreeExample2 implements EntryPoint {
+
+ /**
+ * A list of songs.
+ */
+ private static class Playlist {
+ private final String name;
+ private final List<String> songs = new ArrayList<String>();
+
+ public Playlist(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Add a song to the playlist.
+ *
+ * @param name the name of the song
+ */
+ public void addSong(String name) {
+ songs.add(name);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return the list of songs in the playlist
+ */
+ public List<String> getSongs() {
+ return songs;
+ }
+ }
+
+ /**
+ * A composer of classical music.
+ */
+ private static class Composer {
+ private final String name;
+ private final List<Playlist> playlists = new ArrayList<Playlist>();
+
+ public Composer(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Add a playlist to the composer.
+ *
+ * @param playlist the playlist to add
+ */
+ public Playlist addPlaylist(Playlist playlist) {
+ playlists.add(playlist);
+ return playlist;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return the rockin' playlist for this composter
+ */
+ public List<Playlist> getPlaylists() {
+ return playlists;
+ }
+ }
+
+ /**
+ * The model that defines the nodes in the tree.
+ */
+ private static class CustomTreeModel implements TreeViewModel {
+
+ private final List<Composer> composers;
+
+ /**
+ * This selection model is shared across all leaf nodes. A selection model
+ * can also be shared across all nodes in the tree, or each set of child
+ * nodes can have its own instance. This gives you flexibility to determine
+ * how nodes are selected.
+ */
+ private final SingleSelectionModel<String> selectionModel = new SingleSelectionModel<String>();
+
+ public CustomTreeModel() {
+ // Create a database of information.
+ composers = new ArrayList<Composer>();
+
+ // Add compositions by Beethoven.
+ {
+ Composer beethoven = new Composer("Beethoven");
+ composers.add(beethoven);
+
+ Playlist concertos = beethoven.addPlaylist(new Playlist("Concertos"));
+ concertos.addSong("No. 1 - C");
+ concertos.addSong("No. 2 - B-Flat Major");
+ concertos.addSong("No. 3 - C Minor");
+ concertos.addSong("No. 4 - G Major");
+ concertos.addSong("No. 5 - E-Flat Major");
+
+ Playlist quartets = beethoven.addPlaylist(new Playlist("Quartets"));
+ quartets.addSong("Six String Quartets");
+ quartets.addSong("Three String Quartets");
+ quartets.addSong("Grosse Fugue for String Quartets");
+
+ Playlist sonatas = beethoven.addPlaylist(new Playlist("Sonatas"));
+ sonatas.addSong("Sonata in A Minor");
+ sonatas.addSong("Sonata in F Major");
+
+ Playlist symphonies = beethoven.addPlaylist(new Playlist("Symphonies"));
+ symphonies.addSong("No. 2 - D Major");
+ symphonies.addSong("No. 2 - D Major");
+ symphonies.addSong("No. 3 - E-Flat Major");
+ symphonies.addSong("No. 4 - B-Flat Major");
+ symphonies.addSong("No. 5 - C Minor");
+ symphonies.addSong("No. 6 - F Major");
+ symphonies.addSong("No. 7 - A Major");
+ symphonies.addSong("No. 8 - F Major");
+ symphonies.addSong("No. 9 - D Minor");
+ }
+
+ // Add compositions by Brahms.
+ {
+ Composer brahms = new Composer("Brahms");
+ composers.add(brahms);
+ Playlist concertos = brahms.addPlaylist(new Playlist("Concertos"));
+ concertos.addSong("Violin Concerto");
+ concertos.addSong("Double Concerto - A Minor");
+ concertos.addSong("Piano Concerto No. 1 - D Minor");
+ concertos.addSong("Piano Concerto No. 2 - B-Flat Major");
+
+ Playlist quartets = brahms.addPlaylist(new Playlist("Quartets"));
+ quartets.addSong("Piano Quartet No. 1 - G Minor");
+ quartets.addSong("Piano Quartet No. 2 - A Major");
+ quartets.addSong("Piano Quartet No. 3 - C Minor");
+ quartets.addSong("String Quartet No. 3 - B-Flat Minor");
+
+ Playlist sonatas = brahms.addPlaylist(new Playlist("Sonatas"));
+ sonatas.addSong("Two Sonatas for Clarinet - F Minor");
+ sonatas.addSong("Two Sonatas for Clarinet - E-Flat Major");
+
+ Playlist symphonies = brahms.addPlaylist(new Playlist("Symphonies"));
+ symphonies.addSong("No. 1 - C Minor");
+ symphonies.addSong("No. 2 - D Minor");
+ symphonies.addSong("No. 3 - F Major");
+ symphonies.addSong("No. 4 - E Minor");
+ }
+
+ // Add compositions by Mozart.
+ {
+ Composer mozart = new Composer("Mozart");
+ composers.add(mozart);
+ Playlist concertos = mozart.addPlaylist(new Playlist("Concertos"));
+ concertos.addSong("Piano Concerto No. 12");
+ concertos.addSong("Piano Concerto No. 17");
+ concertos.addSong("Clarinet Concerto");
+ concertos.addSong("Violin Concerto No. 5");
+ concertos.addSong("Violin Concerto No. 4");
+ }
+ }
+
+ /**
+ * Get the {@link NodeInfo} that provides the children of the specified
+ * value.
+ */
+ public <T> NodeInfo<?> getNodeInfo(T value) {
+ if (value == null) {
+ // LEVEL 0.
+ // We passed null as the root value. Return the composers.
+
+ // Create a data provider that contains the list of composers.
+ ListDataProvider<Composer> dataProvider = new ListDataProvider<CellTreeExample2.Composer>(
+ composers);
+
+ // Create a cell to display a composer.
+ Cell<Composer> cell = new AbstractCell<Composer>() {
+ @Override
+ public void render(Composer value, Object key, SafeHtmlBuilder sb) {
+ if (value != null) {
+ sb.appendEscaped(value.getName());
+ }
+ }
+ };
+
+ // Return a node info that pairs the data provider and the cell.
+ return new DefaultNodeInfo<Composer>(dataProvider, cell);
+ } else if (value instanceof Composer) {
+ // LEVEL 1.
+ // We want the children of the composer. Return the playlists.
+ ListDataProvider<Playlist> dataProvider = new ListDataProvider<Playlist>(
+ ((Composer) value).getPlaylists());
+ Cell<Playlist> cell = new AbstractCell<Playlist>() {
+ @Override
+ public void render(Playlist value, Object key, SafeHtmlBuilder sb) {
+ if (value != null) {
+ sb.appendEscaped(value.getName());
+ }
+ }
+ };
+ return new DefaultNodeInfo<Playlist>(dataProvider, cell);
+ } else if (value instanceof Playlist) {
+ // LEVEL 2 - LEAF.
+ // We want the children of the playlist. Return the songs.
+ ListDataProvider<String> dataProvider = new ListDataProvider<String>(
+ ((Playlist) value).getSongs());
+
+ // Use the shared selection model.
+ return new DefaultNodeInfo<String>(dataProvider, new TextCell(),
+ selectionModel, null);
+ }
+
+ return null;
+ }
+
+ /**
+ * Check if the specified value represents a leaf node. Leaf nodes cannot be
+ * opened.
+ */
+ public boolean isLeaf(Object value) {
+ // The leaf nodes are the songs, which are Strings.
+ if (value instanceof String) {
+ return true;
+ }
+ return false;
+ }
+
+ }
+
+ public void onModuleLoad() {
+ // Create a model for the tree.
+ TreeViewModel model = new CustomTreeModel();
+
+ /*
+ * Create the tree using the model. We use <code>null</code> as the default
+ * value of the root node. The default value will be passed to
+ * CustomTreeModel#getNodeInfo();
+ */
+ CellTree tree = new CellTree(model, null);
+ tree.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
+
+ // Open the first playlist by default.
+ TreeNode rootNode = tree.getRootTreeNode();
+ TreeNode firstPlaylist = rootNode.setChildOpen(0, true);
+ firstPlaylist.setChildOpen(0, true);
+
+ // Add the tree to the root layout panel.
+ RootLayoutPanel.get().add(tree);
+ }
+}
diff --git a/user/javadoc/com/google/gwt/examples/cellview/SimplePagerExample.java b/user/javadoc/com/google/gwt/examples/cellview/SimplePagerExample.java
new file mode 100644
index 0000000..26c272a
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/cellview/SimplePagerExample.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2010 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.examples.cellview;
+
+import com.google.gwt.cell.client.TextCell;
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.user.cellview.client.CellList;
+import com.google.gwt.user.cellview.client.SimplePager;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.view.client.ListDataProvider;
+
+import java.util.List;
+
+/**
+ * Example of {@link SimplePager}.
+ */
+public class SimplePagerExample implements EntryPoint {
+
+ public void onModuleLoad() {
+ // Create a CellList.
+ CellList<String> cellList = new CellList<String>(new TextCell());
+
+ // Add a cellList to a data provider.
+ ListDataProvider<String> dataProvider = new ListDataProvider<String>();
+ List<String> data = dataProvider.getList();
+ for (int i = 0; i < 200; i++) {
+ data.add("Item " + i);
+ }
+ dataProvider.addDataDisplay(cellList);
+
+ // Create a SimplePager.
+ SimplePager pager = new SimplePager();
+
+ // Set the cellList as the display.
+ pager.setDisplay(cellList);
+
+ // Add the pager and list to the page.
+ VerticalPanel vPanel = new VerticalPanel();
+ vPanel.add(pager);
+ vPanel.add(cellList);
+ RootPanel.get().add(vPanel);
+ }
+}
\ No newline at end of file
diff --git a/user/javadoc/com/google/gwt/examples/view/AsyncDataProviderExample.java b/user/javadoc/com/google/gwt/examples/view/AsyncDataProviderExample.java
new file mode 100644
index 0000000..dea6fd6
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/view/AsyncDataProviderExample.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2010 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.examples.view;
+
+import com.google.gwt.cell.client.TextCell;
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.user.cellview.client.CellList;
+import com.google.gwt.user.cellview.client.SimplePager;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.view.client.AsyncDataProvider;
+import com.google.gwt.view.client.HasData;
+import com.google.gwt.view.client.Range;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Example of {@link AsyncDataProvider}.
+ */
+public class AsyncDataProviderExample implements EntryPoint {
+
+ /**
+ * A custom {@link AsyncDataProvider}.
+ */
+ private static class MyDataProvider extends AsyncDataProvider<String> {
+ /**
+ * {@link #onRangeChanged(HasData)} is called when the table requests a new
+ * range of data. You can push data back to the displays using
+ * {@link #updateRowData(int, List)}.
+ */
+ @Override
+ protected void onRangeChanged(HasData<String> display) {
+ // Get the new range.
+ final Range range = display.getVisibleRange();
+
+ /*
+ * Query the data asynchronously. If you are using a database, you can
+ * make an RPC call here. We'll use a Timer to simulate a delay.
+ */
+ new Timer() {
+ @Override
+ public void run() {
+ // We are creating fake data. Normally, the data will come from a
+ // server.
+ int start = range.getStart();
+ int length = range.getLength();
+ List<String> newData = new ArrayList<String>();
+ for (int i = start; i < start + length; i++) {
+ newData.add("Item " + i);
+ }
+
+ // Push the data to the displays. AsyncDataProvider will only update
+ // displays that are within range of the data.
+ updateRowData(start, newData);
+ }
+ }.schedule(3000);
+ }
+ }
+
+ public void onModuleLoad() {
+ // Create a CellList.
+ CellList<String> cellList = new CellList<String>(new TextCell());
+
+ // Create a data provider.
+ MyDataProvider dataProvider = new MyDataProvider();
+
+ // Add the cellList to the dataProvider.
+ dataProvider.addDataDisplay(cellList);
+
+ // Create paging controls.
+ SimplePager pager = new SimplePager();
+ pager.setDisplay(cellList);
+
+ // Add the widgets to the root panel.
+ VerticalPanel vPanel = new VerticalPanel();
+ vPanel.add(pager);
+ vPanel.add(cellList);
+ RootPanel.get().add(vPanel);
+ }
+}
\ No newline at end of file
diff --git a/user/javadoc/com/google/gwt/examples/view/KeyProviderExample.java b/user/javadoc/com/google/gwt/examples/view/KeyProviderExample.java
new file mode 100644
index 0000000..f3cfc89
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/view/KeyProviderExample.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2010 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.examples.view;
+
+import com.google.gwt.cell.client.AbstractCell;
+import com.google.gwt.cell.client.Cell;
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
+import com.google.gwt.user.cellview.client.CellList;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.view.client.ProvidesKey;
+import com.google.gwt.view.client.SelectionModel;
+import com.google.gwt.view.client.SingleSelectionModel;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Example of using a {@link ProvidesKey}.
+ */
+public class KeyProviderExample implements EntryPoint {
+
+ /**
+ * A simple data type that represents a contact.
+ */
+ private static class Contact {
+ private static int nextId = 0;
+
+ private final int id;
+ private String name;
+
+ public Contact(String name) {
+ nextId++;
+ this.id = nextId;
+ this.name = name;
+ }
+ }
+
+ /**
+ * A custom {@link Cell} used to render a {@link Contact}.
+ */
+ private static class ContactCell extends AbstractCell<Contact> {
+ @Override
+ public void render(Contact value, Object key, SafeHtmlBuilder sb) {
+ if (value != null) {
+ sb.appendEscaped(value.name);
+ }
+ }
+ }
+
+ /**
+ * The list of data to display.
+ */
+ private static final List<Contact> CONTACTS = Arrays.asList(new Contact(
+ "John"), new Contact("Joe"), new Contact("Michael"),
+ new Contact("Sarah"), new Contact("George"));
+
+ public void onModuleLoad() {
+ /*
+ * Define a key provider for a Contact. We use the unique ID as the key,
+ * which allows to maintain selection even if the name changes.
+ */
+ ProvidesKey<Contact> keyProvider = new ProvidesKey<Contact>() {
+ public Object getKey(Contact item) {
+ // Always do a null check.
+ return (item == null) ? null : item.id;
+ }
+ };
+
+ // Create a CellList using the keyProvider.
+ CellList<Contact> cellList = new CellList<Contact>(new ContactCell(),
+ keyProvider);
+
+ // Push data into the CellList.
+ cellList.setRowCount(CONTACTS.size(), true);
+ cellList.setRowData(0, CONTACTS);
+
+ // Add a selection model using the same keyProvider.
+ SelectionModel<Contact> selectionModel = new SingleSelectionModel<Contact>(
+ keyProvider);
+ cellList.setSelectionModel(selectionModel);
+
+ /*
+ * Select a contact. The selectionModel will select based on the ID because
+ * we used a keyProvider.
+ */
+ Contact sarah = CONTACTS.get(3);
+ selectionModel.setSelected(sarah, true);
+
+ // Modify the name of the contact.
+ sarah.name = "Sara";
+
+ /*
+ * Redraw the CellList. Sarah/Sara will still be selected because we
+ * identify her by ID. If we did not use a keyProvider, Sara would not be
+ * selected.
+ */
+ cellList.redraw();
+
+ // Add the widgets to the root panel.
+ RootPanel.get().add(cellList);
+ }
+}
\ No newline at end of file
diff --git a/user/javadoc/com/google/gwt/examples/view/ListDataProviderExample.java b/user/javadoc/com/google/gwt/examples/view/ListDataProviderExample.java
new file mode 100644
index 0000000..faf6c5a
--- /dev/null
+++ b/user/javadoc/com/google/gwt/examples/view/ListDataProviderExample.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2010 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.examples.view;
+
+import com.google.gwt.cell.client.TextCell;
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.cellview.client.CellList;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.client.ui.TextBox;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.view.client.ListDataProvider;
+
+import java.util.List;
+
+/**
+ * Example of {@link ListDataProvider}.
+ */
+public class ListDataProviderExample implements EntryPoint {
+
+ public void onModuleLoad() {
+ // Create a CellList.
+ CellList<String> cellList = new CellList<String>(new TextCell());
+
+ // Create a list data provider.
+ final ListDataProvider<String> dataProvider = new ListDataProvider<String>();
+
+ // Add the cellList to the dataProvider.
+ dataProvider.addDataDisplay(cellList);
+
+ // Create a form to add values to the data provider.
+ final TextBox valueBox = new TextBox();
+ valueBox.setText("Enter new value");
+ Button addButton = new Button("Add value", new ClickHandler() {
+ public void onClick(ClickEvent event) {
+ // Get the value from the text box.
+ String newValue = valueBox.getText();
+
+ // Get the underlying list from data dataProvider.
+ List<String> list = dataProvider.getList();
+
+ // Add the value to the list. The dataProvider will update the cellList.
+ list.add(newValue);
+ }
+ });
+
+ // Add the widgets to the root panel.
+ VerticalPanel vPanel = new VerticalPanel();
+ vPanel.add(valueBox);
+ vPanel.add(addButton);
+ vPanel.add(cellList);
+ RootPanel.get().add(vPanel);
+ }
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/activity/Activity.gwt.xml b/user/src/com/google/gwt/activity/Activity.gwt.xml
new file mode 100644
index 0000000..78b19d0
--- /dev/null
+++ b/user/src/com/google/gwt/activity/Activity.gwt.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 0.0.999//EN" "http://google-web-toolkit.googlecode.com/svn/tags/0.0.999/distro-source/core/src/gwt-module.dtd">
+<module>
+ <inherits name='com.google.gwt.user.User'/>
+ <inherits name='com.google.gwt.place.Place'/>
+
+ <source path="shared"/>
+</module>
diff --git a/user/src/com/google/gwt/app/place/AbstractActivity.java b/user/src/com/google/gwt/activity/shared/AbstractActivity.java
similarity index 96%
rename from user/src/com/google/gwt/app/place/AbstractActivity.java
rename to user/src/com/google/gwt/activity/shared/AbstractActivity.java
index 90c8777..a4cfd70 100644
--- a/user/src/com/google/gwt/app/place/AbstractActivity.java
+++ b/user/src/com/google/gwt/activity/shared/AbstractActivity.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.activity.shared;
/**
* <p>
diff --git a/user/src/com/google/gwt/app/place/Activity.java b/user/src/com/google/gwt/activity/shared/Activity.java
similarity index 89%
rename from user/src/com/google/gwt/app/place/Activity.java
rename to user/src/com/google/gwt/activity/shared/Activity.java
index 30590c4..e092e3f 100644
--- a/user/src/com/google/gwt/app/place/Activity.java
+++ b/user/src/com/google/gwt/activity/shared/Activity.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.activity.shared;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
@@ -26,7 +26,8 @@
* </p>
* Implemented by objects that control a piece of user interface, with a life
* cycle managed by an {@link ActivityManager}, in response to
- * {@link PlaceChangeEvent} events as the user navigates through the app.
+ * {@link com.google.gwt.place.shared.PlaceChangeEvent} events as the user
+ * navigates through the app.
*/
public interface Activity {
/**
@@ -52,8 +53,8 @@
/**
* Called when the Activity should ready its widget for the user. When the
* widget is ready (typically after an RPC response has been received),
- * receiver should present it by calling
- * {@link AcceptsOneWidget#setWidget()} on the given panel
+ * receiver should present it by calling {@link AcceptsOneWidget#setWidget()}
+ * on the given panel.
* <p>
* Any handlers attached to the provided event bus will be de-registered when
* the activity is stopped, so activities will rarely need to hold on to the
diff --git a/user/src/com/google/gwt/app/place/ActivityManager.java b/user/src/com/google/gwt/activity/shared/ActivityManager.java
similarity index 95%
rename from user/src/com/google/gwt/app/place/ActivityManager.java
rename to user/src/com/google/gwt/activity/shared/ActivityManager.java
index f3577ff..30626bf 100644
--- a/user/src/com/google/gwt/app/place/ActivityManager.java
+++ b/user/src/com/google/gwt/activity/shared/ActivityManager.java
@@ -13,12 +13,14 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.activity.shared;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.ResettableEventBus;
import com.google.gwt.event.shared.UmbrellaException;
+import com.google.gwt.place.shared.PlaceChangeEvent;
+import com.google.gwt.place.shared.PlaceChangeRequestEvent;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.user.client.ui.IsWidget;
@@ -77,8 +79,9 @@
/**
* Create an ActivityManager. Next call {@link #setDisplay}.
- *
- * @param mapper finds the {@link Activity} for a given {@link Place}
+ *
+ * @param mapper finds the {@link Activity} for a given
+ * {@link com.google.gwt.place.shared.Place}
* @param eventBus source of {@link PlaceChangeEvent} and
* {@link PlaceChangeRequestEvent} events.
*/
diff --git a/user/src/com/google/gwt/app/place/ActivityMapper.java b/user/src/com/google/gwt/activity/shared/ActivityMapper.java
similarity index 91%
rename from user/src/com/google/gwt/app/place/ActivityMapper.java
rename to user/src/com/google/gwt/activity/shared/ActivityMapper.java
index 114295b..d7fce27 100644
--- a/user/src/com/google/gwt/app/place/ActivityMapper.java
+++ b/user/src/com/google/gwt/activity/shared/ActivityMapper.java
@@ -13,7 +13,9 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.activity.shared;
+
+import com.google.gwt.place.shared.Place;
/**
* <p>
diff --git a/user/src/com/google/gwt/app/place/CachingActivityMapper.java b/user/src/com/google/gwt/activity/shared/CachingActivityMapper.java
similarity index 93%
rename from user/src/com/google/gwt/app/place/CachingActivityMapper.java
rename to user/src/com/google/gwt/activity/shared/CachingActivityMapper.java
index 2b234c3..a651649 100644
--- a/user/src/com/google/gwt/app/place/CachingActivityMapper.java
+++ b/user/src/com/google/gwt/activity/shared/CachingActivityMapper.java
@@ -13,7 +13,9 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.activity.shared;
+
+import com.google.gwt.place.shared.Place;
/**
* Wraps another {@link ActivityMapper} and caches the last activity it
diff --git a/user/src/com/google/gwt/app/place/FilteredActivityMapper.java b/user/src/com/google/gwt/activity/shared/FilteredActivityMapper.java
similarity index 81%
rename from user/src/com/google/gwt/app/place/FilteredActivityMapper.java
rename to user/src/com/google/gwt/activity/shared/FilteredActivityMapper.java
index 1ba484d..16b774c 100644
--- a/user/src/com/google/gwt/app/place/FilteredActivityMapper.java
+++ b/user/src/com/google/gwt/activity/shared/FilteredActivityMapper.java
@@ -1,39 +1,44 @@
/*
* Copyright 2010 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.app.place;
+package com.google.gwt.activity.shared;
+
+import com.google.gwt.place.shared.Place;
/**
- * Wraps an activity mapper and applies a filter to the place objects
- * that it sees.
+ * Wraps an activity mapper and applies a filter to the place objects that it
+ * sees.
*/
public class FilteredActivityMapper implements ActivityMapper {
- interface Filter {
+
+ /**
+ * Implemented by objects that want to interpret one place as another.
+ */
+ public interface Filter {
Place filter(Place place);
}
-
+
private final Filter filter;
private final ActivityMapper wrapped;
-
+
public FilteredActivityMapper(Filter filter, ActivityMapper wrapped) {
this.filter = filter;
this.wrapped = wrapped;
}
-
+
public Activity getActivity(Place place) {
return wrapped.getActivity(filter.filter(place));
}
-
}
diff --git a/user/src/com/google/gwt/app/App.gwt.xml b/user/src/com/google/gwt/app/App.gwt.xml
deleted file mode 100644
index 377ad4a..0000000
--- a/user/src/com/google/gwt/app/App.gwt.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 0.0.999//EN" "http://google-web-toolkit.googlecode.com/svn/tags/0.0.999/distro-source/core/src/gwt-module.dtd">
-<module>
- <inherits name='com.google.gwt.user.User'/>
- <inherits name='com.google.gwt.requestfactory.RequestFactory'/>
-
- <source path="place"/>
- <source path="client"/>
- <generate-with class="com.google.gwt.app.rebind.PlaceHistoryMapperGenerator">
- <when-type-assignable class="com.google.gwt.app.place.PlaceHistoryMapper"/>
- </generate-with>
-</module>
diff --git a/user/src/com/google/gwt/app/client/BooleanParser.java b/user/src/com/google/gwt/app/client/BooleanParser.java
deleted file mode 100644
index d9f064c..0000000
--- a/user/src/com/google/gwt/app/client/BooleanParser.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2010 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.app.client;
-
-import com.google.gwt.text.shared.Parser;
-
-/**
- * <span style="color:red">Experimental API: This class is still under rapid
- * development, and is very likely to be deleted. Use it at your own risk.
- * </span>
- * <p>
- * An unlocalized simple parser based on {@link Boolean#valueOf}.
- */
-public class BooleanParser implements Parser<Boolean> {
-
- private static BooleanParser INSTANCE;
-
- /**
- * @return the instance of the no-op renderer
- */
- public static Parser<Boolean> instance() {
- if (INSTANCE == null) {
- INSTANCE = new BooleanParser();
- }
- return INSTANCE;
- }
-
- protected BooleanParser() {
- }
-
- public Boolean parse(CharSequence object) {
- return Boolean.valueOf(object.toString());
- }
-}
diff --git a/user/src/com/google/gwt/app/client/BooleanRenderer.java b/user/src/com/google/gwt/app/client/BooleanRenderer.java
deleted file mode 100644
index 9ffea3b..0000000
--- a/user/src/com/google/gwt/app/client/BooleanRenderer.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2010 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.app.client;
-
-import com.google.gwt.text.shared.AbstractRenderer;
-import com.google.gwt.text.shared.Renderer;
-
-/**
- * <span style="color:red">Experimental API: This class is still under rapid
- * development, and is very likely to be deleted. Use it at your own risk.
- * </span>
- * <p>
- * Simple unlocalized renderer of Boolean values.
- */
-public class BooleanRenderer extends AbstractRenderer<Boolean> {
- private static BooleanRenderer INSTANCE;
-
- /**
- * @return the instance
- */
- public static Renderer<Boolean> instance() {
- if (INSTANCE == null) {
- INSTANCE = new BooleanRenderer();
- }
- return INSTANCE;
- }
-
- protected BooleanRenderer() {
- }
-
- public String render(Boolean object) {
- return toString(object);
- }
-}
diff --git a/user/src/com/google/gwt/app/client/package.html b/user/src/com/google/gwt/app/client/package.html
deleted file mode 100644
index 9f3bac1..0000000
--- a/user/src/com/google/gwt/app/client/package.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<html>
-<body>
-Client specific classes of the GWT application framework.
-
-<p><span style="color:red">Experimental API: All classes in this package are still under rapid development, and are very likely to be deleted or renamed. Use them at your own risk.
-</span></p>
-</body>
-</html>
diff --git a/user/src/com/google/gwt/app/package.html b/user/src/com/google/gwt/app/package.html
deleted file mode 100644
index c7deb8d..0000000
--- a/user/src/com/google/gwt/app/package.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<html>
-<body>
-Classes that frame an application architecture.
-
-<p><span style="color:red">Experimental API: All classes in this package are still under rapid development, and are very likely to be deleted or renamed. Use them at your own risk.
-</span></p>
-
-</body>
-</html>
diff --git a/user/src/com/google/gwt/app/place/package.html b/user/src/com/google/gwt/app/place/package.html
deleted file mode 100644
index f10479d..0000000
--- a/user/src/com/google/gwt/app/place/package.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<html>
-<body>
-Classes to define application workflow.
-<p><span style="color:red">Experimental API: All classes in this package are still under rapid development, and are very likely to be deleted or renamed. Use them at your own risk.
-</span></p>
-</body>
-</html>
diff --git a/user/src/com/google/gwt/cell/client/AbstractCell.java b/user/src/com/google/gwt/cell/client/AbstractCell.java
index 9bfa026..121d36b 100644
--- a/user/src/com/google/gwt/cell/client/AbstractCell.java
+++ b/user/src/com/google/gwt/cell/client/AbstractCell.java
@@ -28,7 +28,15 @@
* A default implementation of the {@link Cell} interface.
*
* <p>
- * Note: This class is new and its interface subject to change.
+ * <h3>Examples</h3>
+ * <dl>
+ * <dt>Read only cell</dt>
+ * <dd>TODO example com.google.gwt.examples.cell.CellExample</dd>
+ * <dt>Interactive cell</dt>
+ * <dd>TODO example com.google.gwt.examples.cell.InteractionCellExample</dd>
+ * <dt>Editable cell</dt>
+ * <dd>TODO example com.google.gwt.examples.cell.EditableCellExample</dd>
+ * </dl>
* </p>
*
* @param <C> the type that this Cell represents
diff --git a/user/src/com/google/gwt/cell/client/AbstractEditableCell.java b/user/src/com/google/gwt/cell/client/AbstractEditableCell.java
index b115413..90c26f9 100644
--- a/user/src/com/google/gwt/cell/client/AbstractEditableCell.java
+++ b/user/src/com/google/gwt/cell/client/AbstractEditableCell.java
@@ -26,7 +26,8 @@
* cells that need to save view data state for specific values.
*
* <p>
- * Note: This class is new and its interface subject to change.
+ * <h3>Example</h3>
+ * TODO example com.google.gwt.examples.cell.EditableCellExample
* </p>
*
* @param <C> the type that this Cell represents
diff --git a/user/src/com/google/gwt/cell/client/Cell.java b/user/src/com/google/gwt/cell/client/Cell.java
index bbe169b..12306f4 100644
--- a/user/src/com/google/gwt/cell/client/Cell.java
+++ b/user/src/com/google/gwt/cell/client/Cell.java
@@ -25,7 +25,8 @@
* A light weight representation of a renderable object.
*
* <p>
- * Note: This class is new and its interface subject to change.
+ * <h3>Example</h3>
+ * TODO example com.google.gwt.examples.cell.CellExample
* </p>
*
* @param <C> the type that this Cell represents
diff --git a/user/src/com/google/gwt/editor/Editor.gwt.xml b/user/src/com/google/gwt/editor/Editor.gwt.xml
index 3720f24..adda3ed 100644
--- a/user/src/com/google/gwt/editor/Editor.gwt.xml
+++ b/user/src/com/google/gwt/editor/Editor.gwt.xml
@@ -14,10 +14,14 @@
<!-- Editor framework support -->
<module>
<inherits name="com.google.gwt.core.Core" />
+
+ <source path="client"/>
+ <source path="ui/client"/>
+
<generate-with class="com.google.gwt.editor.rebind.AutoBeanFactoryGenerator">
<when-type-assignable class="com.google.gwt.editor.client.AutoBeanFactory" />
</generate-with>
<generate-with class="com.google.gwt.editor.rebind.SimpleBeanEditorDriverGenerator">
<when-type-assignable class="com.google.gwt.editor.client.SimpleBeanEditorDriver" />
</generate-with>
-</module>
\ No newline at end of file
+</module>
diff --git a/user/src/com/google/gwt/editor/rebind/model/ModelUtils.java b/user/src/com/google/gwt/editor/rebind/model/ModelUtils.java
index 5423da4..22b22d3 100644
--- a/user/src/com/google/gwt/editor/rebind/model/ModelUtils.java
+++ b/user/src/com/google/gwt/editor/rebind/model/ModelUtils.java
@@ -19,11 +19,13 @@
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
+import com.google.gwt.dev.util.collect.HashMap;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
/**
@@ -31,11 +33,27 @@
*/
public class ModelUtils {
+ static final Map<Class<?>, Class<?>> AUTOBOX_MAP;
+
static final Set<String> VALUE_TYPES = Collections.unmodifiableSet(new HashSet<String>(
Arrays.asList(Boolean.class.getName(), Character.class.getName(),
Class.class.getName(), Date.class.getName(), Enum.class.getName(),
Number.class.getName(), String.class.getName(), Void.class.getName())));
+ static {
+ Map<Class<?>, Class<?>> autoBoxMap = new HashMap<Class<?>, Class<?>>();
+ autoBoxMap.put(byte.class, Byte.class);
+ autoBoxMap.put(char.class, Character.class);
+ autoBoxMap.put(double.class, Double.class);
+ autoBoxMap.put(float.class, Float.class);
+ autoBoxMap.put(int.class, Integer.class);
+ autoBoxMap.put(long.class, Long.class);
+ autoBoxMap.put(short.class, Short.class);
+ autoBoxMap.put(void.class, Void.class);
+ AUTOBOX_MAP = Collections.unmodifiableMap(autoBoxMap);
+ }
+
+
public static JClassType[] findParameterizationOf(JClassType intfType,
JClassType subType) {
assert intfType.isAssignableFrom(subType) : subType.getParameterizedQualifiedSourceName()
@@ -70,6 +88,11 @@
return false;
}
+ public static Class<?> maybeAutobox(Class<?> domainType) {
+ Class<?> autoBoxType = AUTOBOX_MAP.get(domainType);
+ return autoBoxType == null ? domainType : autoBoxType;
+ }
+
private ModelUtils() {
}
}
diff --git a/user/src/com/google/gwt/editor/client/ui/ValueBoxEditorDecorator.java b/user/src/com/google/gwt/editor/ui/client/ValueBoxEditorDecorator.java
similarity index 95%
rename from user/src/com/google/gwt/editor/client/ui/ValueBoxEditorDecorator.java
rename to user/src/com/google/gwt/editor/ui/client/ValueBoxEditorDecorator.java
index 9132016..eb8551e 100644
--- a/user/src/com/google/gwt/editor/client/ui/ValueBoxEditorDecorator.java
+++ b/user/src/com/google/gwt/editor/ui/client/ValueBoxEditorDecorator.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.editor.client.ui;
+package com.google.gwt.editor.ui.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
@@ -21,7 +21,7 @@
import com.google.gwt.editor.client.EditorError;
import com.google.gwt.editor.client.HasEditorErrors;
import com.google.gwt.editor.client.IsEditor;
-import com.google.gwt.editor.client.adapters.ValueBoxEditor;
+import com.google.gwt.editor.ui.client.adapters.ValueBoxEditor;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiChild;
import com.google.gwt.uibinder.client.UiConstructor;
@@ -103,7 +103,7 @@
/**
* The default implementation will display, but not consume, received errors
* whose {@link EditorError#getEditor() getEditor()} method returns the Editor
- * passed into {@link #setEditor()}.
+ * passed into {@link #setEditor}.
*/
public void showErrors(List<EditorError> errors) {
StringBuilder sb = new StringBuilder();
diff --git a/user/src/com/google/gwt/editor/client/ui/ValueBoxEditorDecorator.ui.xml b/user/src/com/google/gwt/editor/ui/client/ValueBoxEditorDecorator.ui.xml
similarity index 100%
rename from user/src/com/google/gwt/editor/client/ui/ValueBoxEditorDecorator.ui.xml
rename to user/src/com/google/gwt/editor/ui/client/ValueBoxEditorDecorator.ui.xml
diff --git a/user/src/com/google/gwt/editor/client/adapters/HasTextEditor.java b/user/src/com/google/gwt/editor/ui/client/adapters/HasTextEditor.java
similarity index 95%
rename from user/src/com/google/gwt/editor/client/adapters/HasTextEditor.java
rename to user/src/com/google/gwt/editor/ui/client/adapters/HasTextEditor.java
index 2c75d88..00f3fe4 100644
--- a/user/src/com/google/gwt/editor/client/adapters/HasTextEditor.java
+++ b/user/src/com/google/gwt/editor/ui/client/adapters/HasTextEditor.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.editor.client.adapters;
+package com.google.gwt.editor.ui.client.adapters;
import com.google.gwt.editor.client.LeafValueEditor;
import com.google.gwt.user.client.ui.HasText;
diff --git a/user/src/com/google/gwt/editor/client/adapters/ValueBoxEditor.java b/user/src/com/google/gwt/editor/ui/client/adapters/ValueBoxEditor.java
similarity index 94%
rename from user/src/com/google/gwt/editor/client/adapters/ValueBoxEditor.java
rename to user/src/com/google/gwt/editor/ui/client/adapters/ValueBoxEditor.java
index 0433197..9dc6956 100644
--- a/user/src/com/google/gwt/editor/client/adapters/ValueBoxEditor.java
+++ b/user/src/com/google/gwt/editor/ui/client/adapters/ValueBoxEditor.java
@@ -13,10 +13,11 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.editor.client.adapters;
+package com.google.gwt.editor.ui.client.adapters;
import com.google.gwt.editor.client.EditorDelegate;
import com.google.gwt.editor.client.HasEditorDelegate;
+import com.google.gwt.editor.client.adapters.TakesValueEditor;
import com.google.gwt.user.client.ui.ValueBoxBase;
import java.text.ParseException;
diff --git a/user/src/com/google/gwt/place/Place.gwt.xml b/user/src/com/google/gwt/place/Place.gwt.xml
new file mode 100644
index 0000000..56fff20
--- /dev/null
+++ b/user/src/com/google/gwt/place/Place.gwt.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 0.0.999//EN" "http://google-web-toolkit.googlecode.com/svn/tags/0.0.999/distro-source/core/src/gwt-module.dtd">
+<module>
+ <inherits name='com.google.gwt.user.User'/>
+
+ <source path="shared"/>
+ <source path="impl"/>
+ <generate-with class="com.google.gwt.place.rebind.PlaceHistoryMapperGenerator">
+ <when-type-assignable class="com.google.gwt.place.shared.PlaceHistoryMapper"/>
+ </generate-with>
+</module>
diff --git a/user/src/com/google/gwt/app/place/impl/AbstractPlaceHistoryMapper.java b/user/src/com/google/gwt/place/impl/AbstractPlaceHistoryMapper.java
similarity index 92%
rename from user/src/com/google/gwt/app/place/impl/AbstractPlaceHistoryMapper.java
rename to user/src/com/google/gwt/place/impl/AbstractPlaceHistoryMapper.java
index 28e261f..1fb4ae2 100644
--- a/user/src/com/google/gwt/app/place/impl/AbstractPlaceHistoryMapper.java
+++ b/user/src/com/google/gwt/place/impl/AbstractPlaceHistoryMapper.java
@@ -13,11 +13,11 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place.impl;
+package com.google.gwt.place.impl;
-import com.google.gwt.app.place.Place;
-import com.google.gwt.app.place.PlaceHistoryMapperWithFactory;
-import com.google.gwt.app.place.PlaceTokenizer;
+import com.google.gwt.place.shared.Place;
+import com.google.gwt.place.shared.PlaceHistoryMapperWithFactory;
+import com.google.gwt.place.shared.PlaceTokenizer;
/**
* Abstract implementation of {@link PlaceHistoryMapper}.
diff --git a/user/src/com/google/gwt/app/rebind/MostToLeastDerivedPlaceTypeComparator.java b/user/src/com/google/gwt/place/rebind/MostToLeastDerivedPlaceTypeComparator.java
similarity index 96%
rename from user/src/com/google/gwt/app/rebind/MostToLeastDerivedPlaceTypeComparator.java
rename to user/src/com/google/gwt/place/rebind/MostToLeastDerivedPlaceTypeComparator.java
index 477de65..2a993cd 100644
--- a/user/src/com/google/gwt/app/rebind/MostToLeastDerivedPlaceTypeComparator.java
+++ b/user/src/com/google/gwt/place/rebind/MostToLeastDerivedPlaceTypeComparator.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.rebind;
+package com.google.gwt.place.rebind;
import com.google.gwt.core.ext.typeinfo.JClassType;
diff --git a/user/src/com/google/gwt/app/rebind/PlaceHistoryGeneratorContext.java b/user/src/com/google/gwt/place/rebind/PlaceHistoryGeneratorContext.java
similarity index 97%
rename from user/src/com/google/gwt/app/rebind/PlaceHistoryGeneratorContext.java
rename to user/src/com/google/gwt/place/rebind/PlaceHistoryGeneratorContext.java
index 62cdd00..9fa62ac 100644
--- a/user/src/com/google/gwt/app/rebind/PlaceHistoryGeneratorContext.java
+++ b/user/src/com/google/gwt/place/rebind/PlaceHistoryGeneratorContext.java
@@ -13,12 +13,8 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.rebind;
+package com.google.gwt.place.rebind;
-import com.google.gwt.app.place.PlaceHistoryMapperWithFactory;
-import com.google.gwt.app.place.PlaceTokenizer;
-import com.google.gwt.app.place.Prefix;
-import com.google.gwt.app.place.WithTokenizers;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
@@ -26,6 +22,10 @@
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
+import com.google.gwt.place.shared.PlaceHistoryMapperWithFactory;
+import com.google.gwt.place.shared.PlaceTokenizer;
+import com.google.gwt.place.shared.Prefix;
+import com.google.gwt.place.shared.WithTokenizers;
import java.util.ArrayList;
import java.util.Arrays;
diff --git a/user/src/com/google/gwt/app/rebind/PlaceHistoryMapperGenerator.java b/user/src/com/google/gwt/place/rebind/PlaceHistoryMapperGenerator.java
similarity index 93%
rename from user/src/com/google/gwt/app/rebind/PlaceHistoryMapperGenerator.java
rename to user/src/com/google/gwt/place/rebind/PlaceHistoryMapperGenerator.java
index 8c04432..18425b9 100644
--- a/user/src/com/google/gwt/app/rebind/PlaceHistoryMapperGenerator.java
+++ b/user/src/com/google/gwt/place/rebind/PlaceHistoryMapperGenerator.java
@@ -13,12 +13,8 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.rebind;
+package com.google.gwt.place.rebind;
-import com.google.gwt.app.place.Place;
-import com.google.gwt.app.place.PlaceTokenizer;
-import com.google.gwt.app.place.impl.AbstractPlaceHistoryMapper;
-import com.google.gwt.app.place.impl.AbstractPlaceHistoryMapper.PrefixAndToken;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
@@ -26,6 +22,10 @@
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
+import com.google.gwt.place.impl.AbstractPlaceHistoryMapper;
+import com.google.gwt.place.impl.AbstractPlaceHistoryMapper.PrefixAndToken;
+import com.google.gwt.place.shared.Place;
+import com.google.gwt.place.shared.PlaceTokenizer;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
@@ -38,7 +38,7 @@
* </span>
* </p>
* Generates implementations of
- * {@link com.google.gwt.app.place.PlaceHistoryMapper PlaceHistoryMapper}.
+ * {@link com.google.gwt.place.shared.PlaceHistoryMapper PlaceHistoryMapper}.
*/
public class PlaceHistoryMapperGenerator extends Generator {
private PlaceHistoryGeneratorContext context;
diff --git a/user/src/com/google/gwt/app/place/Place.java b/user/src/com/google/gwt/place/shared/Place.java
similarity index 96%
rename from user/src/com/google/gwt/app/place/Place.java
rename to user/src/com/google/gwt/place/shared/Place.java
index c8b0e2c..cd1af45 100644
--- a/user/src/com/google/gwt/app/place/Place.java
+++ b/user/src/com/google/gwt/place/shared/Place.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.place.shared;
/**
* <p>
diff --git a/user/src/com/google/gwt/app/place/PlaceChangeEvent.java b/user/src/com/google/gwt/place/shared/PlaceChangeEvent.java
similarity index 94%
rename from user/src/com/google/gwt/app/place/PlaceChangeEvent.java
rename to user/src/com/google/gwt/place/shared/PlaceChangeEvent.java
index 12a0127..5a4a081 100644
--- a/user/src/com/google/gwt/app/place/PlaceChangeEvent.java
+++ b/user/src/com/google/gwt/place/shared/PlaceChangeEvent.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.place.shared;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;
@@ -30,8 +30,6 @@
/**
* Implemented by handlers of PlaceChangeEvent.
- *
- * @param <P> the type of the new Place
*/
public interface Handler extends EventHandler {
void onPlaceChange(PlaceChangeEvent event);
diff --git a/user/src/com/google/gwt/app/place/PlaceChangeRequestEvent.java b/user/src/com/google/gwt/place/shared/PlaceChangeRequestEvent.java
similarity index 96%
rename from user/src/com/google/gwt/app/place/PlaceChangeRequestEvent.java
rename to user/src/com/google/gwt/place/shared/PlaceChangeRequestEvent.java
index d4d1830..fff23d1 100644
--- a/user/src/com/google/gwt/app/place/PlaceChangeRequestEvent.java
+++ b/user/src/com/google/gwt/place/shared/PlaceChangeRequestEvent.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.place.shared;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;
@@ -33,8 +33,6 @@
/**
* Implemented by handlers of PlaceChangeRequestEvent.
- *
- * @param <P> the type of the requested Place
*/
public interface Handler extends EventHandler {
void onPlaceChangeRequest(PlaceChangeRequestEvent event);
diff --git a/user/src/com/google/gwt/app/place/PlaceController.java b/user/src/com/google/gwt/place/shared/PlaceController.java
similarity index 98%
rename from user/src/com/google/gwt/app/place/PlaceController.java
rename to user/src/com/google/gwt/place/shared/PlaceController.java
index 0d84a07..a28a5d0 100644
--- a/user/src/com/google/gwt/app/place/PlaceController.java
+++ b/user/src/com/google/gwt/place/shared/PlaceController.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.place.shared;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.EventBus;
diff --git a/user/src/com/google/gwt/app/place/PlaceHistoryHandler.java b/user/src/com/google/gwt/place/shared/PlaceHistoryHandler.java
similarity index 98%
rename from user/src/com/google/gwt/app/place/PlaceHistoryHandler.java
rename to user/src/com/google/gwt/place/shared/PlaceHistoryHandler.java
index 895d496..274fd55 100644
--- a/user/src/com/google/gwt/app/place/PlaceHistoryHandler.java
+++ b/user/src/com/google/gwt/place/shared/PlaceHistoryHandler.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.place.shared;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
diff --git a/user/src/com/google/gwt/app/place/PlaceHistoryMapper.java b/user/src/com/google/gwt/place/shared/PlaceHistoryMapper.java
similarity index 96%
rename from user/src/com/google/gwt/app/place/PlaceHistoryMapper.java
rename to user/src/com/google/gwt/place/shared/PlaceHistoryMapper.java
index 59a27a1..d170761 100644
--- a/user/src/com/google/gwt/app/place/PlaceHistoryMapper.java
+++ b/user/src/com/google/gwt/place/shared/PlaceHistoryMapper.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.place.shared;
/**
* <p>
diff --git a/user/src/com/google/gwt/app/place/PlaceHistoryMapperWithFactory.java b/user/src/com/google/gwt/place/shared/PlaceHistoryMapperWithFactory.java
similarity index 95%
rename from user/src/com/google/gwt/app/place/PlaceHistoryMapperWithFactory.java
rename to user/src/com/google/gwt/place/shared/PlaceHistoryMapperWithFactory.java
index 22c0b02..4d0b6b7 100644
--- a/user/src/com/google/gwt/app/place/PlaceHistoryMapperWithFactory.java
+++ b/user/src/com/google/gwt/place/shared/PlaceHistoryMapperWithFactory.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.place.shared;
/**
* A PlaceHistoryMapper that can get its {@link PlaceTokenizer} instances from
diff --git a/user/src/com/google/gwt/app/place/PlaceTokenizer.java b/user/src/com/google/gwt/place/shared/PlaceTokenizer.java
similarity index 95%
rename from user/src/com/google/gwt/app/place/PlaceTokenizer.java
rename to user/src/com/google/gwt/place/shared/PlaceTokenizer.java
index 2e9628b..ebc2a71 100644
--- a/user/src/com/google/gwt/app/place/PlaceTokenizer.java
+++ b/user/src/com/google/gwt/place/shared/PlaceTokenizer.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.place.shared;
/**
* Implemented by objects responsible for text serialization and deserialization
diff --git a/user/src/com/google/gwt/app/place/Prefix.java b/user/src/com/google/gwt/place/shared/Prefix.java
similarity index 91%
rename from user/src/com/google/gwt/app/place/Prefix.java
rename to user/src/com/google/gwt/place/shared/Prefix.java
index ce68c3b..8f5a761 100644
--- a/user/src/com/google/gwt/app/place/Prefix.java
+++ b/user/src/com/google/gwt/place/shared/Prefix.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.place.shared;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -24,7 +24,7 @@
* Indicates the prefix to use when the token written by
* {@link PlaceTokenizer#getToken(Place)} is written to
* {@link com.google.gwt.user.client.History#newItem}.
- * {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator} looks
+ * {@code com.google.gwt.place.rebind.PlaceHistoryMapperGenerator} looks
* for this annotation on the factory methods that return a tokenizer, and on
* the tokenizer types themselves.
*/
diff --git a/user/src/com/google/gwt/app/place/WithTokenizers.java b/user/src/com/google/gwt/place/shared/WithTokenizers.java
similarity index 90%
rename from user/src/com/google/gwt/app/place/WithTokenizers.java
rename to user/src/com/google/gwt/place/shared/WithTokenizers.java
index d592055..d10bbd2 100644
--- a/user/src/com/google/gwt/app/place/WithTokenizers.java
+++ b/user/src/com/google/gwt/place/shared/WithTokenizers.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.place.shared;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -23,7 +23,7 @@
/**
* Indicates {@link PlaceTokenizer} types used by an implementation of
* {@link PlaceHistoryMapper} generated by
- * {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
+ * {@code com.google.gwt.place.rebind.PlaceHistoryMapperGenerator}.
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
diff --git a/user/src/com/google/gwt/requestfactory/RequestFactory.gwt.xml b/user/src/com/google/gwt/requestfactory/RequestFactory.gwt.xml
index 0c0dfc5..9ff3aba 100644
--- a/user/src/com/google/gwt/requestfactory/RequestFactory.gwt.xml
+++ b/user/src/com/google/gwt/requestfactory/RequestFactory.gwt.xml
@@ -23,6 +23,7 @@
<source path="client"/>
<source path="shared"/>
+ <source path="ui/client"/>
<generate-with
class="com.google.gwt.requestfactory.rebind.RequestFactoryEditorDriverGenerator">
<when-type-assignable
diff --git a/user/src/com/google/gwt/requestfactory/client/impl/AbstractRequestContext.java b/user/src/com/google/gwt/requestfactory/client/impl/AbstractRequestContext.java
index 2ebce34..2dbfd976 100644
--- a/user/src/com/google/gwt/requestfactory/client/impl/AbstractRequestContext.java
+++ b/user/src/com/google/gwt/requestfactory/client/impl/AbstractRequestContext.java
@@ -26,15 +26,16 @@
import com.google.gwt.requestfactory.shared.EntityProxyChange;
import com.google.gwt.requestfactory.shared.Receiver;
import com.google.gwt.requestfactory.shared.RequestContext;
+import com.google.gwt.requestfactory.shared.RequestTransport.TransportReceiver;
import com.google.gwt.requestfactory.shared.ServerFailure;
import com.google.gwt.requestfactory.shared.ValueCodex;
import com.google.gwt.requestfactory.shared.Violation;
import com.google.gwt.requestfactory.shared.WriteOperation;
-import com.google.gwt.requestfactory.shared.RequestTransport.TransportReceiver;
import com.google.gwt.requestfactory.shared.impl.Constants;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@@ -56,8 +57,13 @@
* Objects are placed into this map by being passed into {@link #edit} or as
* an invocation argument.
*/
- private final Map<SimpleEntityProxyId<?>, EntityProxy> seenProxies = new LinkedHashMap<SimpleEntityProxyId<?>, EntityProxy>();
+ private final Map<SimpleEntityProxyId<?>, AutoBean<?>> editedProxies = new LinkedHashMap<SimpleEntityProxyId<?>, AutoBean<?>>();
private Set<Violation> errors = new LinkedHashSet<Violation>();
+ /**
+ * A map that contains the canonical instance of an entity to return in the
+ * return graph, since this is built from scratch.
+ */
+ private final Map<SimpleEntityProxyId<?>, AutoBean<?>> returnedProxies = new HashMap<SimpleEntityProxyId<?>, AutoBean<?>>();
protected AbstractRequestContext(AbstractRequestFactory factory) {
this.requestFactory = factory;
@@ -71,7 +77,7 @@
AutoBean<T> created = requestFactory.createEntityProxy(clazz,
requestFactory.allocateId(clazz));
- return makeEdited(created);
+ return takeOwnership(created);
}
public <T extends EntityProxy> T edit(T object) {
@@ -80,25 +86,21 @@
checkLocked();
@SuppressWarnings("unchecked")
- T toReturn = (T) seenProxies.get(object.stableId());
- if (toReturn != null) {
+ AutoBean<T> previouslySeen = (AutoBean<T>) editedProxies.get(object.stableId());
+ if (previouslySeen != null && !previouslySeen.isFrozen()) {
/*
* If we've seen the object before, it might be because it was passed in
* as a method argument. This does not guarantee its mutability, so check
* that here before returning the cached object.
*/
- AutoBean<T> previouslySeen = AutoBeanUtils.getAutoBean(toReturn);
- if (!previouslySeen.isFrozen()) {
- return toReturn;
- }
+ return previouslySeen.as();
}
// Create editable copies
AutoBean<T> parent = bean;
bean = cloneBeanAndCollections(bean);
- toReturn = makeEdited(bean);
bean.setTag(PARENT_OBJECT, parent);
- return toReturn;
+ return takeOwnership(bean);
}
/**
@@ -146,13 +148,12 @@
* simple flag-check because of the possibility of "unmaking" a change, per
* the JavaDoc.
*/
- for (EntityProxy edited : seenProxies.values()) {
- AutoBean<EntityProxy> bean = AutoBeanUtils.getAutoBean(edited);
+ for (AutoBean<?> bean : editedProxies.values()) {
AutoBean<?> previous = bean.getTag(PARENT_OBJECT);
if (previous == null) {
// Compare to empty object
- previous = getRequestFactory().getAutoBeanFactory().create(
- edited.stableId().getProxyClass());
+ Class<?> proxyClass = ((EntityProxy) bean.as()).stableId().getProxyClass();
+ previous = getRequestFactory().getAutoBeanFactory().create(proxyClass);
}
if (!AutoBeanUtils.diff(previous, bean).isEmpty()) {
return true;
@@ -182,7 +183,7 @@
*/
protected void addInvocation(AbstractRequest<?> request) {
if (invocations.size() > 0) {
- // TODO(bobv): Upgrade wire protocal and server to handle chains
+ // TODO(bobv): Upgrade wire protocol and server to handle chains
throw new IllegalStateException("Method chaining not implemented");
}
invocations.add(request);
@@ -192,38 +193,35 @@
}
/**
- * Called by generated subclasses when decoding a request.
+ * Creates or retrieves a new canonical AutoBean to represent the given id in
+ * the returned payload.
*/
- EntityProxy getSeenEntityProxy(SimpleEntityProxyId<?> id) {
- return seenProxies.get(id);
+ <Q extends EntityProxy> AutoBean<Q> getProxyForReturnPayloadGraph(
+ SimpleEntityProxyId<Q> id) {
+ assert !id.isEphemeral();
+
+ @SuppressWarnings("unchecked")
+ AutoBean<Q> bean = (AutoBean<Q>) returnedProxies.get(id);
+ if (bean == null) {
+ Class<Q> proxyClass = id.getProxyClass();
+ bean = requestFactory.createEntityProxy(proxyClass, id);
+ returnedProxies.put(id, bean);
+ }
+
+ return bean;
}
/**
- * Apply the deltas in a ReturnRecord to an EntityProxy.
+ * Create a new EntityProxy from a snapshot in the return payload.
*
- * @param id the EntityProxyId of the object being mutated
+ * @param id the EntityProxyId of the object
* @param returnRecord the JSON map containing property/value pairs
* @param operations the WriteOperation eventns to broadcast over the EventBus
*/
<Q extends EntityProxy> Q processReturnRecord(SimpleEntityProxyId<Q> id,
final ReturnRecord returnRecord, WriteOperation... operations) {
- @SuppressWarnings("unchecked")
- Q proxy = (Q) seenProxies.get(id);
- AutoBean<Q> toMutate;
- if (proxy == null) {
- // The server is sending us an object that hasn't been seen before
- assert !id.isEphemeral();
- Class<Q> proxyClass = id.getProxyClass();
- toMutate = requestFactory.createEntityProxy(proxyClass, id);
- makeEdited(toMutate);
- } else {
- // Create a new copy of the object
- AutoBean<Q> original = AutoBeanUtils.getAutoBean(proxy);
- toMutate = cloneBeanAndCollections(original);
- }
-
- proxy = toMutate.as();
+ AutoBean<Q> toMutate = getProxyForReturnPayloadGraph(id);
// Apply updates
toMutate.accept(new AutoBeanVisitor() {
@@ -266,6 +264,7 @@
// Finished applying updates, freeze the bean
makeImmutable(toMutate);
+ Q proxy = toMutate.as();
/*
* Notify subscribers if the object differs from when it first came into the
@@ -394,8 +393,9 @@
if (errors.isEmpty()) {
receiver.onSuccess(null);
// After success, shut down the context
- seenProxies.clear();
+ editedProxies.clear();
invocations.clear();
+ returnedProxies.clear();
} else {
receiver.onViolation(errors);
}
@@ -411,24 +411,12 @@
* Set the frozen status of all EntityProxies owned by this context.
*/
private void freezeEntities(boolean frozen) {
- for (EntityProxy proxy : seenProxies.values()) {
- AutoBean<?> bean = AutoBeanUtils.getAutoBean(proxy);
+ for (AutoBean<?> bean : editedProxies.values()) {
bean.setFrozen(frozen);
}
}
/**
- * Make the EnityProxy bean edited and owned by this RequestContext.
- */
- private <T extends EntityProxy> T makeEdited(AutoBean<T> bean) {
- T toReturn = bean.as();
- seenProxies.put(EntityProxyCategory.stableId(bean), toReturn);
- bean.setTag(EntityProxyCategory.REQUEST_CONTEXT,
- AbstractRequestContext.this);
- return toReturn;
- }
-
- /**
* Make an EntityProxy immutable.
*/
private void makeImmutable(final AutoBean<? extends EntityProxy> toMutate) {
@@ -456,17 +444,16 @@
RequestContentData data = new RequestContentData();
// Compute deltas for each entity seen by the context
- for (EntityProxy proxy : seenProxies.values()) {
+ for (AutoBean<?> currentView : editedProxies.values()) {
boolean isPersist = false;
@SuppressWarnings("unchecked")
- SimpleEntityProxyId<EntityProxy> stableId = (SimpleEntityProxyId<EntityProxy>) proxy.stableId();
+ SimpleEntityProxyId<EntityProxy> stableId = EntityProxyCategory.stableId((AutoBean<EntityProxy>) currentView);
// Encoded string representations of the properties
Map<String, String> encoded = new LinkedHashMap<String, String>();
{
// Find the object to compare against
- AutoBean<?> currentView = AutoBeanUtils.getAutoBean(proxy);
AutoBean<?> parent = currentView.getTag(PARENT_OBJECT);
if (parent == null) {
// Newly-created object, use a blank object to compare against
@@ -546,4 +533,14 @@
edit((EntityProxy) arg);
}
}
+
+ /**
+ * Make the EnityProxy bean edited and owned by this RequestContext.
+ */
+ private <T extends EntityProxy> T takeOwnership(AutoBean<T> bean) {
+ editedProxies.put(EntityProxyCategory.stableId(bean), bean);
+ bean.setTag(EntityProxyCategory.REQUEST_CONTEXT,
+ AbstractRequestContext.this);
+ return bean.as();
+ }
}
diff --git a/user/src/com/google/gwt/requestfactory/client/impl/ClientRequestHelper.java b/user/src/com/google/gwt/requestfactory/client/impl/ClientRequestHelper.java
deleted file mode 100644
index dcd532a..0000000
--- a/user/src/com/google/gwt/requestfactory/client/impl/ClientRequestHelper.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2010 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.requestfactory.client.impl;
-
-import com.google.gwt.core.client.JavaScriptObject;
-
-import java.util.Map;
-
-/**
- * <p>
- * <span style="color:red">Experimental API: This class is still under rapid
- * development, and is very likely to be deleted. Use it at your own risk.
- * </span>
- * </p>
- * A convenience class to convert a Map<String, String> to a JSON string on the
- * client side.
- */
-public class ClientRequestHelper {
-
- private static class MyJSO extends JavaScriptObject {
- static native MyJSO create() /*-{
- return {};
- }-*/;
-
- @SuppressWarnings("unused")
- protected MyJSO() {
- }
-
- private native void put(String key, String value)/*-{
- // TODO(jgw): Find a better way to do this. Occasionally a js-wrapped
- // string ends up in 'value', which breaks the json2.js implementation
- // of JSON.stringify().
- this[key] = (value == null) ? null : String(value);
- }-*/;
-
- private native String toJsonString()/*-{
- var gwt = this.__gwt_ObjectId;
- delete this.__gwt_ObjectId;
- var rtn = $wnd.JSON.stringify(this);
- this.__gwt_ObjectId = gwt;
- return rtn;
- }-*/;
- }
-
- public static String getRequestString(Map<String, String> requestData) {
- MyJSO request = MyJSO.create();
- for (String key : requestData.keySet()) {
- request.put(key, requestData.get(key));
- }
- return request.toJsonString();
- }
-}
diff --git a/user/src/com/google/gwt/requestfactory/client/impl/EntityCodex.java b/user/src/com/google/gwt/requestfactory/client/impl/EntityCodex.java
index e809945..64e0a1f 100644
--- a/user/src/com/google/gwt/requestfactory/client/impl/EntityCodex.java
+++ b/user/src/com/google/gwt/requestfactory/client/impl/EntityCodex.java
@@ -79,7 +79,8 @@
if (requestContext.getRequestFactory().getTypeToken(type) != null) {
EntityProxyId<?> id = requestContext.getRequestFactory().getProxyId(
(String) jso);
- return requestContext.getSeenEntityProxy((SimpleEntityProxyId<?>) id);
+ return requestContext.getProxyForReturnPayloadGraph(
+ (SimpleEntityProxyId<?>) id).as();
}
// Fall back to values
diff --git a/user/src/com/google/gwt/requestfactory/client/impl/messages/RequestContentData.java b/user/src/com/google/gwt/requestfactory/client/impl/messages/RequestContentData.java
index 5a945eb..f955bf0 100644
--- a/user/src/com/google/gwt/requestfactory/client/impl/messages/RequestContentData.java
+++ b/user/src/com/google/gwt/requestfactory/client/impl/messages/RequestContentData.java
@@ -16,7 +16,6 @@
package com.google.gwt.requestfactory.client.impl.messages;
import com.google.gwt.core.client.JsonUtils;
-import com.google.gwt.requestfactory.client.impl.ClientRequestHelper;
import com.google.gwt.requestfactory.shared.WriteOperation;
import java.util.EnumMap;
@@ -33,6 +32,10 @@
*/
public static String flattenKeysToExpressions(
Map<String, String> keysToExpressions) {
+ if (keysToExpressions.isEmpty()) {
+ return "{}";
+ }
+
StringBuilder flattenedProperties = new StringBuilder();
for (Map.Entry<String, String> entry : keysToExpressions.entrySet()) {
flattenedProperties.append(",").append(
@@ -89,7 +92,7 @@
Map<String, String> toReturn = new LinkedHashMap<String, String>();
addToReturn(toReturn, WriteOperation.PERSIST);
addToReturn(toReturn, WriteOperation.UPDATE);
- return ClientRequestHelper.getRequestString(toReturn);
+ return flattenKeysToExpressions(toReturn);
}
/**
diff --git a/user/src/com/google/gwt/requestfactory/client/testing/MockRequestFactoryEditorDriver.java b/user/src/com/google/gwt/requestfactory/client/testing/MockRequestFactoryEditorDriver.java
index 1f57378..66e4675 100644
--- a/user/src/com/google/gwt/requestfactory/client/testing/MockRequestFactoryEditorDriver.java
+++ b/user/src/com/google/gwt/requestfactory/client/testing/MockRequestFactoryEditorDriver.java
@@ -61,7 +61,6 @@
/**
* Returns <code>null</code> or the last value recorded.
*/
- @SuppressWarnings("unchecked")
public RequestContext flush() {
return saveRequest;
}
diff --git a/user/src/com/google/gwt/requestfactory/rebind/model/RequestFactoryModel.java b/user/src/com/google/gwt/requestfactory/rebind/model/RequestFactoryModel.java
index 9576ffd..da5607f 100644
--- a/user/src/com/google/gwt/requestfactory/rebind/model/RequestFactoryModel.java
+++ b/user/src/com/google/gwt/requestfactory/rebind/model/RequestFactoryModel.java
@@ -20,6 +20,7 @@
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameter;
+import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.editor.rebind.model.ModelUtils;
@@ -32,6 +33,8 @@
import com.google.gwt.requestfactory.shared.RequestFactory;
import com.google.gwt.requestfactory.shared.Service;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -54,6 +57,10 @@
instanceRequestInterface.getSimpleSourceName());
}
+ static String poisonedMessage() {
+ return "Unable to create RequestFactoryModel model due to previous errors";
+ }
+
private final TreeLogger logger;
private final JClassType collectionInterface;
private final List<ContextMethod> contextMethods = new ArrayList<ContextMethod>();
@@ -118,10 +125,10 @@
}
if (poisoned) {
- die("Unable to complete due to previous errors");
+ die(poisonedMessage());
}
}
-
+
public Collection<EntityProxyModel> getAllProxyModels() {
return Collections.unmodifiableCollection(peers.values());
}
@@ -150,14 +157,15 @@
* Examine a RequestContext subtype to populate a ContextMethod.
*/
private void buildContextMethod(ContextMethod.Builder contextBuilder,
- JClassType contextType) {
+ JClassType contextType) throws UnableToCompleteException {
Service serviceAnnotation = contextType.getAnnotation(Service.class);
if (serviceAnnotation == null) {
poison("RequestContext subtype %s is missing a @%s annotation",
contextType.getQualifiedSourceName(), Service.class.getSimpleName());
return;
}
- contextBuilder.setServiceClass(serviceAnnotation.value());
+ Class<?> serviceClass = serviceAnnotation.value();
+ contextBuilder.setServiceClass(serviceClass);
List<RequestMethod> requestMethods = new ArrayList<RequestMethod>();
for (JMethod method : contextType.getInheritableMethods()) {
@@ -169,7 +177,7 @@
RequestMethod.Builder methodBuilder = new RequestMethod.Builder();
methodBuilder.setDeclarationMethod(method);
- if (!validateContextMethodAndSetDataType(methodBuilder, method)) {
+ if (!validateContextMethodAndSetDataType(methodBuilder, method, serviceClass)) {
continue;
}
@@ -184,7 +192,22 @@
throw new UnableToCompleteException();
}
- private EntityProxyModel getEntityProxyType(JClassType entityProxyType) {
+ /**
+ * Return a list of public methods that match the given methodName.
+ */
+ private List<Method> findMethods(Class<?> domainType, String methodName) {
+ List<Method> toReturn = new ArrayList<Method>();
+ for (Method method : domainType.getMethods()) {
+ if (methodName.equals(method.getName())
+ && (method.getModifiers() & Modifier.PUBLIC) != 0) {
+ toReturn.add(method);
+ }
+ }
+ return toReturn;
+ }
+
+ private EntityProxyModel getEntityProxyType(JClassType entityProxyType)
+ throws UnableToCompleteException {
EntityProxyModel toReturn = peers.get(entityProxyType);
if (toReturn == null) {
EntityProxyModel.Builder inProgress = peerBuilders.get(entityProxyType);
@@ -204,8 +227,12 @@
poison("The %s type does not have a @%s annotation",
entityProxyType.getQualifiedSourceName(),
ProxyFor.class.getSimpleName());
+ // early exit, because further processing causes NPEs in numerous spots
+ die(poisonedMessage());
} else {
- builder.setProxyFor(proxyFor.value());
+ Class<?> domainType = proxyFor.value();
+ builder.setProxyFor(domainType);
+ validateDomainType(domainType);
}
// Look at the methods declared on the EntityProxy
@@ -237,7 +264,10 @@
continue;
}
validateTransportableType(methodBuilder, transportedType, false);
- requestMethods.add(methodBuilder.build());
+ RequestMethod requestMethod = methodBuilder.build();
+ if (validateDomainBeanMethod(requestMethod, builder)) {
+ requestMethods.add(requestMethod);
+ }
}
builder.setRequestMethods(requestMethods);
@@ -248,6 +278,20 @@
return toReturn;
}
+ private boolean isStatic(Method domainMethod) {
+ return (domainMethod.getModifiers() & Modifier.STATIC) != 0;
+ }
+
+ private String methodLocation(Method domainMethod) {
+ return domainMethod.getDeclaringClass().getName() + "."
+ + domainMethod.getName();
+ }
+
+ private String methodLocation(JMethod proxyMethod) {
+ return proxyMethod.getEnclosingType().getName() + "."
+ + proxyMethod.getName();
+ }
+
private void poison(String message, Object... args) {
logger.log(TreeLogger.ERROR, String.format(message, args));
poisoned = true;
@@ -257,7 +301,8 @@
* Examine a RequestContext method to see if it returns a transportable type.
*/
private boolean validateContextMethodAndSetDataType(
- RequestMethod.Builder methodBuilder, JMethod method) {
+ RequestMethod.Builder methodBuilder, JMethod method, Class<?> serviceClass)
+ throws UnableToCompleteException {
JClassType requestReturnType = method.getReturnType().isInterface();
JClassType invocationReturnType;
if (requestReturnType == null) {
@@ -267,14 +312,44 @@
return false;
}
+ /*
+ * TODO: bad assumption
+ * Implicit assumption is that the Service and ProxyFor
+ * classes are the same. This is because an instance method should
+ * technically be looked up on the class that is the instance parameter,
+ * and not on the serviceClass, which consists of static service methods.
+ * Can't be fixed until it is fixed in JsonRequestProcessor.
+ */
+ Method domainMethod = validateExistsAndNotOverriden(method, serviceClass,
+ false);
+ if (domainMethod == null) {
+ return false;
+ }
+
+
if (instanceRequestInterface.isAssignableFrom(requestReturnType)) {
+ if (isStatic(domainMethod)) {
+ poison("Method %s.%s is an instance method, "
+ + "while the corresponding method on %s is static",
+ method.getEnclosingType().getName(),
+ method.getName(),
+ serviceClass.getName());
+ return false;
+ }
// Instance method invocation
JClassType[] params = ModelUtils.findParameterizationOf(
instanceRequestInterface, requestReturnType);
methodBuilder.setInstanceType(getEntityProxyType(params[0]));
invocationReturnType = params[1];
-
} else if (requestInterface.isAssignableFrom(requestReturnType)) {
+ if (!isStatic(domainMethod)) {
+ poison("Method %s.%s is a static method, "
+ + "while the corresponding method on %s is not",
+ method.getEnclosingType().getName(),
+ method.getName(),
+ serviceClass.getName());
+ return false;
+ }
// Static method invocation
JClassType[] params = ModelUtils.findParameterizationOf(requestInterface,
requestReturnType);
@@ -289,21 +364,168 @@
// Validate the parameters
boolean paramsOk = true;
- for (JParameter param : method.getParameters()) {
+ JParameter[] params = method.getParameters();
+ Class<?>[] domainParams = domainMethod.getParameterTypes();
+ if (params.length != domainParams.length) {
+ poison("Method %s.%s parameters do not match same method on %s",
+ method.getEnclosingType().getName(),
+ method.getName(),
+ serviceClass.getName());
+ }
+ for (int i = 0; i < params.length; ++i) {
+ JParameter param = params[i];
+ Class<?> domainParam = domainParams[i];
paramsOk = validateTransportableType(new RequestMethod.Builder(),
param.getType(), false)
&& paramsOk;
+ paramsOk = validateProxyAndDomainTypeEquals(param.getType(), domainParam, i,
+ methodLocation(method), methodLocation(domainMethod))
+ && paramsOk;
}
return validateTransportableType(methodBuilder, invocationReturnType, true)
+ && validateProxyAndDomainTypeEquals(invocationReturnType,
+ domainMethod.getReturnType(), -1, methodLocation(method),
+ methodLocation(domainMethod))
&& paramsOk;
}
/**
+ * Examine a domain method to see if it matches the proxy method.
+ */
+ private boolean validateDomainBeanMethod(RequestMethod requestMethod,
+ EntityProxyModel.Builder entityBuilder) throws UnableToCompleteException {
+ JMethod proxyMethod = requestMethod.getDeclarationMethod();
+ // check if method exists on domain object
+ Class<?> domainType = entityBuilder.peek().getProxyFor();
+ Method domainMethod = validateExistsAndNotOverriden(proxyMethod, domainType,
+ true);
+ if (domainMethod == null) {
+ return false;
+ }
+
+ boolean isGetter = proxyMethod.getName().startsWith("get");
+ if (isGetter) {
+ // compare return type of domain to proxy return type
+ String returnTypeName = domainMethod.getReturnType().getName();
+ // isEntityType() returns true for collections, but we want the Collection
+ String propertyTypeName =
+ requestMethod.isCollectionType() || requestMethod.isValueType() ?
+ requestMethod.getDataType().getQualifiedBinaryName() :
+ requestMethod.getEntityType().getProxyFor().getName();
+ if (!returnTypeName.equals(propertyTypeName)) {
+ poison("Method %s.%s return type %s does not match return type %s "
+ + " of method %s.%s", domainType.getName(),
+ domainMethod.getName(), returnTypeName,
+ propertyTypeName,
+ proxyMethod.getEnclosingType().getName(), proxyMethod.getName());
+ return false;
+ }
+ }
+ JParameter[] proxyParams = proxyMethod.getParameters();
+ Class<?>[] domainParams = domainMethod.getParameterTypes();
+ if (proxyParams.length != domainParams.length) {
+ poison("Method %s.%s parameter mismatch with %s.%s",
+ proxyMethod.getEnclosingType().getName(),
+ proxyMethod.getName(),
+ domainType.getName(),
+ domainMethod.getName());
+ return false;
+ }
+ for (int i = 0; i < proxyParams.length; i++) {
+ JType proxyParam = proxyParams[i].getType();
+ Class<?> domainParam = domainParams[i];
+ if (!validateProxyAndDomainTypeEquals(proxyParam, domainParam, i,
+ methodLocation(proxyMethod), methodLocation(domainMethod))) {
+ poison("Parameter %d of %s.%s doesn't match method %s.%s",
+ i, proxyMethod.getEnclosingType().getName(),
+ proxyMethod.getName(),
+ domainType.getName(),
+ domainMethod.getName());
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Examine a domain type and see if it includes a getId() method.
+ */
+ private boolean validateDomainType(Class<?> domainType) {
+ try {
+ domainType.getMethod("getId");
+ } catch (NoSuchMethodException e) {
+ poison("The class %s is missing method getId()", domainType.getName());
+ return false;
+ }
+ try {
+ domainType.getMethod("getVersion");
+ } catch (NoSuchMethodException e) {
+ poison("The class %s is missing method getVersion()", domainType.getName());
+ return false;
+ }
+ return true;
+ }
+
+ private Method validateExistsAndNotOverriden(JMethod clientMethod,
+ Class<?> serverType, boolean isGetterOrSetter) {
+ List<Method> domainMethods = findMethods(serverType, clientMethod.getName());
+ if (domainMethods.size() == 0) {
+ poison("Method %s.%s has no corresponding public method on %s",
+ clientMethod.getEnclosingType().getQualifiedBinaryName(),
+ clientMethod.getName(), serverType.getName());
+ return null;
+ }
+ if (domainMethods.size() > 1) {
+ poison("Method %s.%s is overloaded on %s",
+ clientMethod.getEnclosingType().getQualifiedBinaryName(),
+ clientMethod.getName(), serverType.getName());
+ return null;
+ }
+ Method domainMethod = domainMethods.get(0);
+ if (isGetterOrSetter && isStatic(domainMethod)) {
+ poison("Method %s.%s is declared static", serverType.getName(),
+ domainMethod.getName());
+ return null;
+ }
+ return domainMethod;
+ }
+
+ /**
+ * Compare type from Proxy and Domain.
+ */
+ private boolean validateProxyAndDomainTypeEquals(JType proxyType,
+ Class<?> domainType, int paramNumber, String clientMethod,
+ String serverMethod) throws UnableToCompleteException {
+ boolean matchOk = false;
+ if (ModelUtils.isValueType(oracle, proxyType)
+ || collectionInterface.isAssignableFrom(proxyType.isClassOrInterface())) {
+ // allow int to match int or Integer
+ matchOk = proxyType.getQualifiedSourceName().equals(
+ ModelUtils.maybeAutobox(domainType).getName())
+ || proxyType.getQualifiedSourceName().equals(domainType.getName());
+ } else {
+ matchOk = getEntityProxyType(
+ proxyType.isClassOrInterface()).getProxyFor().equals(domainType);
+ }
+ if (!matchOk) {
+ if (paramNumber < 0) {
+ poison("Return type of method %s does not match method %s", clientMethod,
+ serverMethod);
+ } else {
+ poison("Parameter %d of method %s does not match method %s",
+ paramNumber, clientMethod, serverMethod);
+ }
+ }
+ return matchOk;
+ }
+
+ /**
* Examines a type to see if it can be transported.
*/
private boolean validateTransportableType(
- RequestMethod.Builder methodBuilder, JType type, boolean requireObject) {
+ RequestMethod.Builder methodBuilder, JType type, boolean requireObject)
+ throws UnableToCompleteException {
JClassType transportedClass = type.isClassOrInterface();
if (transportedClass == null) {
if (requireObject) {
@@ -324,9 +546,14 @@
methodBuilder.setEntityType(getEntityProxyType(transportedClass));
} else if (collectionInterface.isAssignableFrom(transportedClass)) {
// Only allow certain collections for now
- if (listInterface.equals(transportedClass.isParameterized().getBaseType())) {
+ JParameterizedType parameterized = transportedClass.isParameterized();
+ if (parameterized == null) {
+ poison("Requests that return collections of List or Set must be parameterized");
+ return false;
+ }
+ if (listInterface.equals(parameterized.getBaseType())) {
methodBuilder.setCollectionType(CollectionType.LIST);
- } else if (setInterface.equals(transportedClass.isParameterized().getBaseType())) {
+ } else if (setInterface.equals(parameterized.getBaseType())) {
methodBuilder.setCollectionType(CollectionType.SET);
} else {
poison("Requests that return collections may be declared with"
diff --git a/user/src/com/google/gwt/requestfactory/server/JsonRequestProcessor.java b/user/src/com/google/gwt/requestfactory/server/JsonRequestProcessor.java
index 81ef9aa..8b63c1b 100644
--- a/user/src/com/google/gwt/requestfactory/server/JsonRequestProcessor.java
+++ b/user/src/com/google/gwt/requestfactory/server/JsonRequestProcessor.java
@@ -62,13 +62,22 @@
public class JsonRequestProcessor implements RequestProcessor<String> {
// TODO should we consume String, InputStream, or JSONObject?
- private static class DvsData {
+ private class DvsData {
private final JSONObject jsonObject;
private final WriteOperation writeOperation;
+ // save version because it is deleted later.
+ private final Integer version;
- DvsData(JSONObject jsonObject, WriteOperation writeOperation) {
+ DvsData(JSONObject jsonObject, WriteOperation writeOperation)
+ throws JSONException, SecurityException, IllegalAccessException,
+ InvocationTargetException, NoSuchMethodException,
+ InstantiationException {
this.jsonObject = jsonObject;
this.writeOperation = writeOperation;
+ this.version = (Integer) (jsonObject.has(Constants.ENCODED_VERSION_PROPERTY)
+ ? decodeParameterValue(Constants.ENTITY_VERSION_PROPERTY.getType(),
+ jsonObject.get(Constants.ENCODED_VERSION_PROPERTY).toString())
+ : null);
}
}
@@ -618,19 +627,15 @@
Class<? extends EntityProxy> entityKeyClass,
RequestProperty propertyContext) throws JSONException,
NoSuchMethodException, IllegalAccessException, InvocationTargetException {
- JSONObject jsonObject = new JSONObject();
if (entityElement == null
|| !EntityProxy.class.isAssignableFrom(entityKeyClass)) {
// JSONObject.NULL isn't a JSONObject
return JSONObject.NULL;
}
+ JSONObject jsonObject = getJsonObjectWithIdAndVersion(
+ isEntityReference(entityElement, entityKeyClass), entityElement,
+ propertyContext);
- jsonObject.put(Constants.ENCODED_ID_PROPERTY, isEntityReference(
- entityElement, entityKeyClass));
- jsonObject.put(Constants.ENCODED_VERSION_PROPERTY,
- encodePropertyValueFromDataStore(entityElement,
- Constants.ENTITY_VERSION_PROPERTY,
- Constants.ENTITY_VERSION_PROPERTY.getName(), propertyContext));
for (Property<?> p : allProperties(entityKeyClass)) {
if (requestedProperty(p, propertyContext)) {
String propertyName = p.getName();
@@ -1146,7 +1151,8 @@
* Decode deltaValueStore to populate involvedKeys and dvsDataMap.
*/
private void decodeDVS(String content) throws SecurityException,
- JSONException {
+ JSONException, IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException, InstantiationException {
JSONObject jsonObject = new JSONObject(content);
for (WriteOperation writeOperation : WriteOperation.values()) {
if (!jsonObject.has(writeOperation.name())) {
@@ -1178,26 +1184,6 @@
}
}
- private WriteOperation detectDeleteOrUpdate(EntityKey entityKey,
- EntityData entityData) throws IllegalArgumentException,
- SecurityException, IllegalAccessException, InvocationTargetException,
- NoSuchMethodException, JSONException, InstantiationException {
- if (entityData == null || entityData.entityInstance == null) {
- return null;
- }
-
- Object entityInstance = getEntityInstance(entityKey);
- if (entityInstance == null) {
- return WriteOperation.DELETE;
- }
- SerializedEntity beforeEntity = beforeDataMap.get(entityKey);
- if (beforeEntity != null && hasChanged(beforeEntity.serializedEntity,
- serializeEntity(entityInstance, entityKey))) {
- return WriteOperation.UPDATE;
- }
- return null;
- }
-
private String encodeId(Object id) {
if (id instanceof String) {
return base64Encode((String) id);
@@ -1235,10 +1221,6 @@
assert originalEntityKey.isFuture;
Object entityInstance = entityData.entityInstance;
assert entityInstance != null;
- JSONObject returnObject = new JSONObject();
- returnObject.put(Constants.ENCODED_FUTUREID_PROPERTY,
- originalEntityKey.encodedId + "");
- // violations have already been taken care of.
Object newId = getRawPropertyValueFromDatastore(entityInstance,
Constants.ENTITY_ID_PROPERTY);
if (newId == null) {
@@ -1248,12 +1230,12 @@
}
newId = encodeId(newId);
- returnObject.put(Constants.ENCODED_ID_PROPERTY, getSchemaAndId(
- originalEntityKey.proxyType, newId));
- returnObject.put(Constants.ENCODED_VERSION_PROPERTY,
- encodePropertyValueFromDataStore(entityInstance,
- Constants.ENTITY_VERSION_PROPERTY,
- Constants.ENTITY_VERSION_PROPERTY.getName(), propertyRefs));
+ JSONObject returnObject = getJsonObjectWithIdAndVersion(
+ getSchemaAndId(originalEntityKey.proxyType, newId), entityInstance,
+ propertyRefs);
+ // violations have already been taken care of.
+ returnObject.put(Constants.ENCODED_FUTUREID_PROPERTY,
+ originalEntityKey.encodedId + "");
return returnObject;
}
@@ -1277,29 +1259,17 @@
return idMethod;
}
- private Object getPropertyValueFromRequestCached(JSONObject recordObject,
- Map<String, Property<?>> propertiesInProxy, String key,
- Property<?> dtoProperty) throws JSONException, IllegalAccessException,
- InvocationTargetException, NoSuchMethodException, InstantiationException {
- Object propertyValue;
- if (!recordObject.isNull(key)
- && EntityProxy.class.isAssignableFrom(dtoProperty.getType())) {
- // if the property type is a Proxy, we expect an encoded Key string
- EntityKey propKey = getEntityKey(recordObject.getString(key));
- // check to see if we've already decoded this object from JSON
- Object cacheValue = cachedEntityLookup.get(propKey);
- // containsKey is used here because an entity lookup can return null
- if (cachedEntityLookup.containsKey(propKey)) {
- propertyValue = cacheValue;
- } else {
- propertyValue = getPropertyValueFromRequest(recordObject, key,
- propertiesInProxy.get(key).getType());
- }
- } else {
- propertyValue = getPropertyValueFromRequest(recordObject, key,
- propertiesInProxy.get(key).getType());
- }
- return propertyValue;
+ private JSONObject getJsonObjectWithIdAndVersion(String encodedId,
+ Object entityElement, RequestProperty propertyContext)
+ throws JSONException, SecurityException, NoSuchMethodException,
+ IllegalAccessException, InvocationTargetException {
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put(Constants.ENCODED_ID_PROPERTY, encodedId);
+ jsonObject.put(Constants.ENCODED_VERSION_PROPERTY,
+ encodePropertyValueFromDataStore(entityElement,
+ Constants.ENTITY_VERSION_PROPERTY,
+ Constants.ENTITY_VERSION_PROPERTY.getName(), propertyContext));
+ return jsonObject;
}
private Object getPropertyValueFromRequestCached(JSONArray recordArray,
@@ -1329,6 +1299,31 @@
return propertyValue;
}
+ private Object getPropertyValueFromRequestCached(JSONObject recordObject,
+ Map<String, Property<?>> propertiesInProxy, String key,
+ Property<?> dtoProperty) throws JSONException, IllegalAccessException,
+ InvocationTargetException, NoSuchMethodException, InstantiationException {
+ Object propertyValue;
+ if (!recordObject.isNull(key)
+ && EntityProxy.class.isAssignableFrom(dtoProperty.getType())) {
+ // if the property type is a Proxy, we expect an encoded Key string
+ EntityKey propKey = getEntityKey(recordObject.getString(key));
+ // check to see if we've already decoded this object from JSON
+ Object cacheValue = cachedEntityLookup.get(propKey);
+ // containsKey is used here because an entity lookup can return null
+ if (cachedEntityLookup.containsKey(propKey)) {
+ propertyValue = cacheValue;
+ } else {
+ propertyValue = getPropertyValueFromRequest(recordObject, key,
+ propertiesInProxy.get(key).getType());
+ }
+ } else {
+ propertyValue = getPropertyValueFromRequest(recordObject, key,
+ propertiesInProxy.get(key).getType());
+ }
+ return propertyValue;
+ }
+
private Object getRawPropertyValueFromDatastore(Object entityElement,
String propertyName) throws SecurityException, NoSuchMethodException,
IllegalAccessException, InvocationTargetException {
@@ -1368,6 +1363,7 @@
if (entityData == null) {
continue;
}
+ // handle CREATE
if (entityKey.isFuture) {
JSONObject createRecord = getCreateReturnRecord(entityKey, entityData);
if (createRecord != null) {
@@ -1375,19 +1371,35 @@
}
continue;
}
- WriteOperation writeOperation = detectDeleteOrUpdate(entityKey,
- entityData);
- if (writeOperation == WriteOperation.DELETE) {
+ // handle DELETE
+ Object entityInstanceAfterOperation = getEntityInstance(entityKey);
+ if (null == entityInstanceAfterOperation) {
JSONObject deleteRecord = new JSONObject();
- deleteRecord.put(Constants.ENCODED_ID_PROPERTY, getSchemaAndId(
- entityKey.proxyType, entityKey.encodedId));
+ deleteRecord.put(Constants.ENCODED_ID_PROPERTY,
+ getSchemaAndId(entityKey.proxyType, entityKey.encodedId));
deleteArray.put(deleteRecord);
+ continue;
}
- if (writeOperation == WriteOperation.UPDATE) {
- JSONObject updateRecord = new JSONObject();
- updateRecord.put(Constants.ENCODED_ID_PROPERTY, getSchemaAndId(
- entityKey.proxyType, entityKey.encodedId));
- updateArray.put(updateRecord);
+ /*
+ * Send an UPDATE if the client is at a version different than that of the
+ * server or if the server version has changed after invoking the domain
+ * method.
+ */
+ boolean clientNeedsUpdating = false;
+ DvsData dvsData = dvsDataMap.get(entityKey);
+ if (dvsData != null && dvsData.version != null) {
+ Integer serverVersion = (Integer) getRawPropertyValueFromDatastore(
+ entityInstanceAfterOperation,
+ Constants.ENTITY_VERSION_PROPERTY.getName());
+ if (!dvsData.version.equals(serverVersion)) {
+ clientNeedsUpdating = true;
+ }
+ }
+ if (clientNeedsUpdating
+ || hasServerVersionChanged(entityKey, entityInstanceAfterOperation)) {
+ updateArray.put(getJsonObjectWithIdAndVersion(
+ getSchemaAndId(entityKey.proxyType, entityKey.encodedId),
+ entityInstanceAfterOperation, propertyRefs));
}
}
if (createArray.length() > 0) {
@@ -1429,6 +1441,18 @@
return violations;
}
+ private boolean hasServerVersionChanged(EntityKey entityKey,
+ Object entityInstanceAfterOperation) throws IllegalArgumentException,
+ SecurityException, IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException, JSONException, InstantiationException {
+ SerializedEntity beforeEntity = beforeDataMap.get(entityKey);
+ if (beforeEntity != null && hasChanged(beforeEntity.serializedEntity,
+ serializeEntity(entityInstanceAfterOperation, entityKey))) {
+ return true;
+ }
+ return false;
+ }
+
private String isEntityReference(Object entity, Class<?> proxyPropertyType)
throws SecurityException, NoSuchMethodException,
IllegalArgumentException, IllegalAccessException,
diff --git a/user/src/com/google/gwt/requestfactory/client/AuthenticationFailureHandler.java b/user/src/com/google/gwt/requestfactory/ui/client/AuthenticationFailureHandler.java
similarity index 97%
rename from user/src/com/google/gwt/requestfactory/client/AuthenticationFailureHandler.java
rename to user/src/com/google/gwt/requestfactory/ui/client/AuthenticationFailureHandler.java
index 6dc5be0..beb0f41 100644
--- a/user/src/com/google/gwt/requestfactory/client/AuthenticationFailureHandler.java
+++ b/user/src/com/google/gwt/requestfactory/ui/client/AuthenticationFailureHandler.java
@@ -14,7 +14,7 @@
* the License.
*/
-package com.google.gwt.requestfactory.client;
+package com.google.gwt.requestfactory.ui.client;
import com.google.gwt.http.client.Response;
import com.google.gwt.requestfactory.shared.RequestEvent;
diff --git a/user/src/com/google/gwt/app/place/EntityProxyKeyProvider.java b/user/src/com/google/gwt/requestfactory/ui/client/EntityProxyKeyProvider.java
similarity index 71%
rename from user/src/com/google/gwt/app/place/EntityProxyKeyProvider.java
rename to user/src/com/google/gwt/requestfactory/ui/client/EntityProxyKeyProvider.java
index ac88236..669cb29 100644
--- a/user/src/com/google/gwt/app/place/EntityProxyKeyProvider.java
+++ b/user/src/com/google/gwt/requestfactory/ui/client/EntityProxyKeyProvider.java
@@ -13,13 +13,19 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.requestfactory.ui.client;
import com.google.gwt.requestfactory.shared.EntityProxy;
import com.google.gwt.view.client.ProvidesKey;
/**
- * A {@link Record}-aware key provider.
+ * An {@link EntityProxy}-aware key provider, handy for use with
+ * {@link com.google.gwt.view.client.SelectionModel} and various
+ * cell widgets.
+ *
+ * @see com.google.gwt.user.cellview.client.CellBrowser
+ * @see com.google.gwt.user.cellview.client.CellList
+ * @see com.google.gwt.user.cellview.client.CellTable
*
* @param <P> the proxy type
*/
diff --git a/user/src/com/google/gwt/requestfactory/client/LoginWidget.java b/user/src/com/google/gwt/requestfactory/ui/client/LoginWidget.java
similarity index 93%
rename from user/src/com/google/gwt/requestfactory/client/LoginWidget.java
rename to user/src/com/google/gwt/requestfactory/ui/client/LoginWidget.java
index 95f418f..f78b5e31 100644
--- a/user/src/com/google/gwt/requestfactory/client/LoginWidget.java
+++ b/user/src/com/google/gwt/requestfactory/ui/client/LoginWidget.java
@@ -14,7 +14,7 @@
* the License.
*/
-package com.google.gwt.requestfactory.client;
+package com.google.gwt.requestfactory.ui.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.SpanElement;
@@ -47,8 +47,7 @@
}
@UiHandler("logoutLink")
- @SuppressWarnings("unused")
- void handleClick(ClickEvent e) {
+ void handleClick(@SuppressWarnings("unused") ClickEvent e) {
if (logoutUrl != "") {
Location.replace(logoutUrl);
}
diff --git a/user/src/com/google/gwt/requestfactory/client/LoginWidget.ui.xml b/user/src/com/google/gwt/requestfactory/ui/client/LoginWidget.ui.xml
similarity index 100%
rename from user/src/com/google/gwt/requestfactory/client/LoginWidget.ui.xml
rename to user/src/com/google/gwt/requestfactory/ui/client/LoginWidget.ui.xml
diff --git a/user/src/com/google/gwt/app/place/ProxyRenderer.java b/user/src/com/google/gwt/requestfactory/ui/client/ProxyRenderer.java
similarity index 95%
rename from user/src/com/google/gwt/app/place/ProxyRenderer.java
rename to user/src/com/google/gwt/requestfactory/ui/client/ProxyRenderer.java
index 3b7ce42..375d839 100644
--- a/user/src/com/google/gwt/app/place/ProxyRenderer.java
+++ b/user/src/com/google/gwt/requestfactory/ui/client/ProxyRenderer.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.requestfactory.ui.client;
import com.google.gwt.text.shared.AbstractRenderer;
diff --git a/user/src/com/google/gwt/rpc/linker/CastableTypeDataImpl.java b/user/src/com/google/gwt/rpc/linker/CastableTypeDataImpl.java
index b9e4c6e..58207fb 100644
--- a/user/src/com/google/gwt/rpc/linker/CastableTypeDataImpl.java
+++ b/user/src/com/google/gwt/rpc/linker/CastableTypeDataImpl.java
@@ -16,7 +16,6 @@
package com.google.gwt.rpc.linker;
-import com.google.gwt.core.ext.linker.CastableTypeMap;
import com.google.gwt.rpc.server.CastableTypeData;
/**
@@ -24,14 +23,14 @@
*/
public class CastableTypeDataImpl implements CastableTypeData {
- private final CastableTypeMap castableTypeMap;
+ private final String castableTypeMapJs;
- public CastableTypeDataImpl(CastableTypeMap castableTypeMap) {
- this.castableTypeMap = castableTypeMap;
+ public CastableTypeDataImpl(String castableTypeMapJs) {
+ this.castableTypeMapJs = castableTypeMapJs;
}
public String toJs() {
- return castableTypeMap.toJs();
+ return castableTypeMapJs;
}
}
diff --git a/user/src/com/google/gwt/rpc/linker/ClientOracleLinker.java b/user/src/com/google/gwt/rpc/linker/ClientOracleLinker.java
index 7f9ff78..eb3c555 100644
--- a/user/src/com/google/gwt/rpc/linker/ClientOracleLinker.java
+++ b/user/src/com/google/gwt/rpc/linker/ClientOracleLinker.java
@@ -69,10 +69,15 @@
}
for (SymbolData symbolData : result.getSymbolMap()) {
+
+ String castableTypeMapString =
+ (symbolData.getCastableTypeMap() == null) ? null :
+ symbolData.getCastableTypeMap().toJs();
+
builder.add(symbolData.getSymbolName(), symbolData.getJsniIdent(),
symbolData.getClassName(), symbolData.getMemberName(),
symbolData.getQueryId(),
- new CastableTypeDataImpl(symbolData.getCastableTypeMap()));
+ new CastableTypeDataImpl(castableTypeMapString));
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
diff --git a/user/src/com/google/gwt/text/Text.gwt.xml b/user/src/com/google/gwt/text/Text.gwt.xml
index b841ec9..babbe40 100644
--- a/user/src/com/google/gwt/text/Text.gwt.xml
+++ b/user/src/com/google/gwt/text/Text.gwt.xml
@@ -16,4 +16,5 @@
<module>
<inherits name="com.google.gwt.core.Core"/>
<source path="shared"/>
+ <source path="client"/>
</module>
diff --git a/user/src/com/google/gwt/i18n/client/DateTimeFormatRenderer.java b/user/src/com/google/gwt/text/client/DateTimeFormatRenderer.java
similarity index 91%
rename from user/src/com/google/gwt/i18n/client/DateTimeFormatRenderer.java
rename to user/src/com/google/gwt/text/client/DateTimeFormatRenderer.java
index b17f818..9a8699b 100644
--- a/user/src/com/google/gwt/i18n/client/DateTimeFormatRenderer.java
+++ b/user/src/com/google/gwt/text/client/DateTimeFormatRenderer.java
@@ -13,8 +13,10 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.i18n.client;
+package com.google.gwt.text.client;
+import com.google.gwt.i18n.client.DateTimeFormat;
+import com.google.gwt.i18n.client.TimeZone;
import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
import com.google.gwt.text.shared.AbstractRenderer;
@@ -28,7 +30,7 @@
private final TimeZone timeZone;
/**
- * Create an instance using {@link PredefinedFormat#DATE_SHORT}
+ * Create an instance using {@link PredefinedFormat#DATE_SHORT}.
*/
public DateTimeFormatRenderer() {
this(DateTimeFormat.getFormat(PredefinedFormat.DATE_SHORT));
@@ -51,7 +53,7 @@
public String render(Date object) {
if (object == null) {
- return toString(object);
+ return "";
}
return timeZone == null ? format.format(object) : format.format(object,
timeZone);
diff --git a/user/src/com/google/gwt/app/client/DoubleParser.java b/user/src/com/google/gwt/text/client/DoubleParser.java
similarity index 77%
rename from user/src/com/google/gwt/app/client/DoubleParser.java
rename to user/src/com/google/gwt/text/client/DoubleParser.java
index b9f3e14..b3d3560 100644
--- a/user/src/com/google/gwt/app/client/DoubleParser.java
+++ b/user/src/com/google/gwt/text/client/DoubleParser.java
@@ -13,18 +13,15 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.client;
+package com.google.gwt.text.client;
+import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.text.shared.Parser;
import java.text.ParseException;
/**
- * <span style="color:red">Experimental API: This class is still under rapid
- * development, and is very likely to be deleted. Use it at your own risk.
- * </span>
- * <p>
- * Simple unlocalized parser of Double that wraps {@link Double#valueOf(String)}.
+ * A localized parser based on {@link NumberFormat#getDecimalFormat}.
*/
public class DoubleParser implements Parser<Double> {
@@ -44,8 +41,12 @@
}
public Double parse(CharSequence object) throws ParseException {
+ if ("".equals(object.toString())) {
+ return null;
+ }
+
try {
- return Double.valueOf(object.toString());
+ return Math.rint(NumberFormat.getDecimalFormat().parse(object.toString()));
} catch (NumberFormatException e) {
throw new ParseException(e.getMessage(), 0);
}
diff --git a/user/src/com/google/gwt/app/client/DoubleRenderer.java b/user/src/com/google/gwt/text/client/DoubleRenderer.java
similarity index 79%
rename from user/src/com/google/gwt/app/client/DoubleRenderer.java
rename to user/src/com/google/gwt/text/client/DoubleRenderer.java
index 17d4c58..4c53c1e 100644
--- a/user/src/com/google/gwt/app/client/DoubleRenderer.java
+++ b/user/src/com/google/gwt/text/client/DoubleRenderer.java
@@ -13,17 +13,14 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.client;
+package com.google.gwt.text.client;
+import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.text.shared.AbstractRenderer;
import com.google.gwt.text.shared.Renderer;
/**
- * <span style="color:red">Experimental API: This class is still under rapid
- * development, and is very likely to be deleted. Use it at your own risk.
- * </span>
- * <p>
- * A simple unlocalized renderer of Long values.
+ * A localized renderer based on {@link NumberFormat#getDecimalFormat}.
*/
public class DoubleRenderer extends AbstractRenderer<Double> {
private static DoubleRenderer INSTANCE;
@@ -42,6 +39,10 @@
}
public String render(Double object) {
- return toString(object);
+ if (object == null) {
+ return "";
+ }
+
+ return NumberFormat.getDecimalFormat().format(object);
}
}
diff --git a/user/src/com/google/gwt/app/client/IntegerParser.java b/user/src/com/google/gwt/text/client/IntegerParser.java
similarity index 74%
rename from user/src/com/google/gwt/app/client/IntegerParser.java
rename to user/src/com/google/gwt/text/client/IntegerParser.java
index 43751da..f959fb0 100644
--- a/user/src/com/google/gwt/app/client/IntegerParser.java
+++ b/user/src/com/google/gwt/text/client/IntegerParser.java
@@ -1,35 +1,32 @@
/*
* Copyright 2010 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.app.client;
+package com.google.gwt.text.client;
+import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.text.shared.Parser;
import java.text.ParseException;
/**
- * <span style="color:red">Experimental API: This class is still under rapid
- * development, and is very likely to be deleted. Use it at your own risk.
- * </span>
- * <p>
- * A simple unlocalized parser based on {@link Integer#valueOf(String)}.
+ * A localized parser based on {@link NumberFormat#getDecimalFormat}.
*/
public class IntegerParser implements Parser<Integer> {
private static IntegerParser INSTANCE;
-
+
/**
* @return the instance of the no-op renderer
*/
@@ -39,14 +36,18 @@
}
return INSTANCE;
}
-
+
protected IntegerParser() {
}
public Integer parse(CharSequence object) throws ParseException {
+ if ("".equals(object.toString())) {
+ return null;
+ }
+
try {
- return Integer.valueOf(object.toString());
- } catch (NumberFormatException e) {
+ return (int) Math.rint(NumberFormat.getDecimalFormat().parse(object.toString()));
+ } catch (NumberFormatException e) {
throw new ParseException(e.getMessage(), 0);
}
}
diff --git a/user/src/com/google/gwt/app/client/IntegerRenderer.java b/user/src/com/google/gwt/text/client/IntegerRenderer.java
similarity index 79%
rename from user/src/com/google/gwt/app/client/IntegerRenderer.java
rename to user/src/com/google/gwt/text/client/IntegerRenderer.java
index 036df4e..d9efe2d 100644
--- a/user/src/com/google/gwt/app/client/IntegerRenderer.java
+++ b/user/src/com/google/gwt/text/client/IntegerRenderer.java
@@ -13,17 +13,15 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.client;
+package com.google.gwt.text.client;
+import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.text.shared.AbstractRenderer;
import com.google.gwt.text.shared.Renderer;
+
/**
- * <span style="color:red">Experimental API: This class is still under rapid
- * development, and is very likely to be deleted. Use it at your own risk.
- * </span>
- * <p>
- * Renderer of Integer values.
+ * A localized renderer based on {@link NumberFormat#getDecimalFormat}.
*/
public class IntegerRenderer extends AbstractRenderer<Integer> {
private static IntegerRenderer INSTANCE;
@@ -42,6 +40,10 @@
}
public String render(Integer object) {
- return toString(object);
+ if (null == object) {
+ return "";
+ }
+
+ return NumberFormat.getDecimalFormat().format(object);
}
}
diff --git a/user/src/com/google/gwt/app/client/LongParser.java b/user/src/com/google/gwt/text/client/LongParser.java
similarity index 79%
rename from user/src/com/google/gwt/app/client/LongParser.java
rename to user/src/com/google/gwt/text/client/LongParser.java
index 49d1a87..f896ca4 100644
--- a/user/src/com/google/gwt/app/client/LongParser.java
+++ b/user/src/com/google/gwt/text/client/LongParser.java
@@ -13,18 +13,16 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.client;
+package com.google.gwt.text.client;
+
+import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.text.shared.Parser;
import java.text.ParseException;
/**
- * <span style="color:red">Experimental API: This class is still under rapid
- * development, and is very likely to be deleted. Use it at your own risk.
- * </span>
- * <p>
- * A no-op renderer.
+ * A localized parser based on {@link NumberFormat#getDecimalFormat}.
*/
public class LongParser implements Parser<Long> {
@@ -44,8 +42,12 @@
}
public Long parse(CharSequence object) throws ParseException {
+ if ("".equals(object.toString())) {
+ return null;
+ }
+
try {
- return Long.valueOf(object.toString());
+ return (long) NumberFormat.getDecimalFormat().parse(object.toString());
} catch (NumberFormatException e) {
throw new ParseException(e.getMessage(), 0);
}
diff --git a/user/src/com/google/gwt/app/client/LongRenderer.java b/user/src/com/google/gwt/text/client/LongRenderer.java
similarity index 79%
rename from user/src/com/google/gwt/app/client/LongRenderer.java
rename to user/src/com/google/gwt/text/client/LongRenderer.java
index 6e16280..0c3a92a 100644
--- a/user/src/com/google/gwt/app/client/LongRenderer.java
+++ b/user/src/com/google/gwt/text/client/LongRenderer.java
@@ -13,17 +13,15 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.client;
+package com.google.gwt.text.client;
+import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.text.shared.AbstractRenderer;
import com.google.gwt.text.shared.Renderer;
+
/**
- * <span style="color:red">Experimental API: This class is still under rapid
- * development, and is very likely to be deleted. Use it at your own risk.
- * </span>
- * <p>
- * Renderer of Long values.
+ * A localized renderer based on {@link NumberFormat#getDecimalFormat}.
*/
public class LongRenderer extends AbstractRenderer<Long> {
private static LongRenderer INSTANCE;
@@ -42,6 +40,10 @@
}
public String render(Long object) {
- return toString(object);
+ if (object == null) {
+ return "";
+ }
+
+ return NumberFormat.getDecimalFormat().format(object);
}
}
diff --git a/user/src/com/google/gwt/text/shared/AbstractRenderer.java b/user/src/com/google/gwt/text/shared/AbstractRenderer.java
index 4e5b520..3c69c9e 100644
--- a/user/src/com/google/gwt/text/shared/AbstractRenderer.java
+++ b/user/src/com/google/gwt/text/shared/AbstractRenderer.java
@@ -31,8 +31,4 @@
public void render(T object, Appendable appendable) throws IOException {
appendable.append(render(object));
}
-
- protected String toString(Object obj) {
- return obj == null ? "" : String.valueOf(obj);
- }
}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/text/shared/PassthroughParser.java b/user/src/com/google/gwt/text/shared/testing/PassthroughParser.java
similarity index 93%
rename from user/src/com/google/gwt/text/shared/PassthroughParser.java
rename to user/src/com/google/gwt/text/shared/testing/PassthroughParser.java
index 5e3ecc9..3cc6555 100644
--- a/user/src/com/google/gwt/text/shared/PassthroughParser.java
+++ b/user/src/com/google/gwt/text/shared/testing/PassthroughParser.java
@@ -13,7 +13,10 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.text.shared;
+package com.google.gwt.text.shared.testing;
+
+import com.google.gwt.text.shared.Parser;
+
/**
* <span style="color:red">Experimental API: This class is still under rapid
diff --git a/user/src/com/google/gwt/text/shared/PassthroughRenderer.java b/user/src/com/google/gwt/text/shared/testing/PassthroughRenderer.java
similarity index 90%
rename from user/src/com/google/gwt/text/shared/PassthroughRenderer.java
rename to user/src/com/google/gwt/text/shared/testing/PassthroughRenderer.java
index 493540b..4967058 100644
--- a/user/src/com/google/gwt/text/shared/PassthroughRenderer.java
+++ b/user/src/com/google/gwt/text/shared/testing/PassthroughRenderer.java
@@ -13,7 +13,11 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.text.shared;
+package com.google.gwt.text.shared.testing;
+
+import com.google.gwt.text.shared.AbstractRenderer;
+import com.google.gwt.text.shared.Renderer;
+
/**
* <span style="color:red">Experimental API: This class is still under rapid
diff --git a/user/src/com/google/gwt/user/cellview/client/CellBrowser.java b/user/src/com/google/gwt/user/cellview/client/CellBrowser.java
index f352f8f..10664ca 100644
--- a/user/src/com/google/gwt/user/cellview/client/CellBrowser.java
+++ b/user/src/com/google/gwt/user/cellview/client/CellBrowser.java
@@ -69,6 +69,15 @@
* the HTML page in which it is run have an explicit <!DOCTYPE>
* declaration.
* </p>
+ *
+ * <p>
+ * <h3>Example</h3>
+ * <dl>
+ * <dt>Trivial example</dt>
+ * <dd>TODO example com.google.gwt.examples.cellview.CellBrowserExample</dd>
+ * <dt>Complex example</dt>
+ * <dd>TODO example com.google.gwt.examples.cellview.CellBrowserExample2</dd>
+ * </dl>
*/
public class CellBrowser extends AbstractCellTree implements ProvidesResize,
RequiresResize, HasAnimation {
@@ -181,7 +190,7 @@
/**
* A custom version of cell list used by the browser. Visible for testing.
- *
+ *
* @param <T> the data type of list items
*/
class BrowserCellList<T> extends CellList<T> {
@@ -356,7 +365,7 @@
/**
* A node in the tree.
- *
+ *
* @param <C> the data type of the children of the node
*/
class TreeNodeImpl<C> implements TreeNode {
@@ -368,7 +377,7 @@
/**
* Construct a new {@link TreeNodeImpl}.
- *
+ *
* @param nodeInfo the nodeInfo for the children nodes
* @param value the value of the node
* @param display the display associated with the node
@@ -482,7 +491,7 @@
/**
* Check the child bounds.
- *
+ *
* @param index the index of the child
* @throws IndexOutOfBoundsException if the child is not in range
*/
@@ -505,7 +514,7 @@
/**
* Get the index of the open item.
- *
+ *
* @return the index of the open item, or -1 if not found
*/
private int getOpenIndex() {
@@ -700,7 +709,7 @@
/**
* Construct a new {@link CellBrowser}.
- *
+ *
* @param <T> the type of data in the root node
* @param viewModel the {@link TreeViewModel} that backs the tree
* @param rootValue the hidden root value of the tree
@@ -711,7 +720,7 @@
/**
* Construct a new {@link CellBrowser} with the specified {@link Resources}.
- *
+ *
* @param <T> the type of data in the root node
* @param viewModel the {@link TreeViewModel} that backs the tree
* @param rootValue the hidden root value of the tree
@@ -762,7 +771,7 @@
/**
* Get the default width of new columns.
- *
+ *
* @return the default width in pixels
*/
public int getDefaultColumnWidth() {
@@ -771,7 +780,7 @@
/**
* Get the minimum width of columns.
- *
+ *
* @return the minimum width in pixels
*/
public int getMinimumColumnWidth() {
@@ -808,7 +817,7 @@
/**
* Set the default width of new columns.
- *
+ *
* @param width the default width in pixels
*/
public void setDefaultColumnWidth(int width) {
@@ -825,7 +834,7 @@
/**
* Set the minimum width of columns.
- *
+ *
* @param minWidth the minimum width in pixels
*/
public void setMinimumColumnWidth(int minWidth) {
@@ -834,7 +843,7 @@
/**
* Create a pager to control the list view.
- *
+ *
* @param <C> the item type in the list view
* @param display the list view to add paging too
* @return the pager
@@ -863,7 +872,7 @@
/**
* Create a new {@link TreeNodeImpl} and append it to the end of the
* LayoutPanel.
- *
+ *
* @param <C> the data type of the children
* @param nodeInfo the info about the node
* @param value the value of the open node
@@ -914,7 +923,7 @@
/**
* Create a {@link HasData} that will display items. The {@link HasData} must
* extend {@link Widget}.
- *
+ *
* @param <C> the item type in the list view
* @param nodeInfo the node info with child data
* @param level the level of the list
@@ -930,7 +939,7 @@
/**
* Get the HTML representation of an image.
- *
+ *
* @param res the {@link ImageResource} to render as HTML
* @return the rendered HTML
*/
@@ -944,7 +953,7 @@
/**
* Get the {@link SplitLayoutPanel} used to lay out the views.
- *
+ *
* @return the {@link SplitLayoutPanel}
*/
private SplitLayoutPanel getSplitLayoutPanel() {
@@ -953,7 +962,7 @@
/**
* Set the open state of a tree node.
- *
+ *
* @param cellList the CellList that changed state.
* @param value the value to open
* @param open true to open, false to close
@@ -1036,7 +1045,7 @@
/**
* Reduce the number of {@link HasData}s down to the specified level.
- *
+ *
* @param level the level to trim to
*/
private void trimToLevel(int level) {
diff --git a/user/src/com/google/gwt/user/cellview/client/CellList.java b/user/src/com/google/gwt/user/cellview/client/CellList.java
index 52df7d8..9412e6e 100644
--- a/user/src/com/google/gwt/user/cellview/client/CellList.java
+++ b/user/src/com/google/gwt/user/cellview/client/CellList.java
@@ -45,6 +45,19 @@
/**
* A single column list of cells.
*
+ * <p>
+ * <h3>Examples</h3>
+ * <p>
+ * TODO example com.google.gwt.examples.cellview.CellListExample
+ * </p>
+ * <p>
+ * TODO example com.google.gwt.examples.cellview.CellListValueUpdaterExample
+ * </p>
+ * <p>
+ * TODO example com.google.gwt.examples.view.KeyProviderExample
+ * </p>
+ * </p>
+ *
* @param <T> the data type of list items
*/
public class CellList<T> extends AbstractHasData<T> {
@@ -259,7 +272,7 @@
/**
* Called when a user action triggers selection.
- *
+ *
* @param event the event that triggered selection
* @param value the value that was selected
* @param indexOnPage the index of the value on the page
@@ -470,7 +483,7 @@
/**
* Called when the user selects a cell with the mouse or tab key.
- *
+ *
* @param event the event
* @param value the value that is selected
* @param indexOnPage the index on the page
diff --git a/user/src/com/google/gwt/user/cellview/client/CellTable.java b/user/src/com/google/gwt/user/cellview/client/CellTable.java
index 3bad38a..8c354a4 100644
--- a/user/src/com/google/gwt/user/cellview/client/CellTable.java
+++ b/user/src/com/google/gwt/user/cellview/client/CellTable.java
@@ -53,6 +53,19 @@
/**
* A list view that supports paging and columns.
*
+ * <p>
+ * <h3>Examples</h3>
+ * <p>
+ * TODO example com.google.gwt.examples.cellview.CellTableExample
+ * </p>
+ * <p>
+ * TODO example com.google.gwt.examples.cellview.CellTableFieldUpdaterExample
+ * </p>
+ * <p>
+ * TODO example com.google.gwt.examples.view.KeyProviderExample
+ * </p>
+ * </p>
+ *
* @param <T> the data type of each row
*/
public class CellTable<T> extends AbstractHasData<T> {
diff --git a/user/src/com/google/gwt/user/cellview/client/CellTree.java b/user/src/com/google/gwt/user/cellview/client/CellTree.java
index 3649cd6..9c549bf 100644
--- a/user/src/com/google/gwt/user/cellview/client/CellTree.java
+++ b/user/src/com/google/gwt/user/cellview/client/CellTree.java
@@ -52,6 +52,15 @@
* the HTML page in which it is run have an explicit <!DOCTYPE>
* declaration.
* </p>
+ *
+ * <p>
+ * <h3>Examples</h3>
+ * <dl>
+ * <dt>Trivial example</dt>
+ * <dd>TODO example com.google.gwt.examples.cellview.CellTreeExample</dd>
+ * <dt>Complex example</dt>
+ * <dd>TODO example com.google.gwt.examples.cellview.CellTreeExample2</dd>
+ * </dl>
*/
public class CellTree extends AbstractCellTree implements HasAnimation,
Focusable {
diff --git a/user/src/com/google/gwt/user/cellview/client/HasDataPresenter.java b/user/src/com/google/gwt/user/cellview/client/HasDataPresenter.java
index b1bb09f0..a3dacbc 100644
--- a/user/src/com/google/gwt/user/cellview/client/HasDataPresenter.java
+++ b/user/src/com/google/gwt/user/cellview/client/HasDataPresenter.java
@@ -269,7 +269,7 @@
*/
private boolean pageStartChangedSinceRender;
- private int rowCount = Integer.MIN_VALUE;
+ private int rowCount = 0;
private boolean rowCountIsExact;
@@ -950,7 +950,7 @@
private void updateLoadingState() {
int cacheSize = rowData.size();
int curPageSize = isRowCountExact() ? getCurrentPageSize() : pageSize;
- if (rowCount == 0) {
+ if (rowCount == 0 && rowCountIsExact) {
view.setLoadingState(LoadingState.EMPTY);
} else if (cacheSize >= curPageSize) {
view.setLoadingState(LoadingState.LOADED);
diff --git a/user/src/com/google/gwt/user/cellview/client/SimplePager.java b/user/src/com/google/gwt/user/cellview/client/SimplePager.java
index 64d51b7..dc16193 100644
--- a/user/src/com/google/gwt/user/cellview/client/SimplePager.java
+++ b/user/src/com/google/gwt/user/cellview/client/SimplePager.java
@@ -34,6 +34,11 @@
/**
* A pager for controlling a {@link HasRows} that only supports simple page
* navigation.
+ *
+ * <p>
+ * <h3>Example</h3>
+ * TODO example com.google.gwt.examples.cellview.SimplePagerExample
+ * </p>
*/
public class SimplePager extends AbstractPager {
diff --git a/user/src/com/google/gwt/app/client/DoubleBox.java b/user/src/com/google/gwt/user/client/ui/DoubleBox.java
similarity index 88%
rename from user/src/com/google/gwt/app/client/DoubleBox.java
rename to user/src/com/google/gwt/user/client/ui/DoubleBox.java
index 43ab5cf..960f0ca 100644
--- a/user/src/com/google/gwt/app/client/DoubleBox.java
+++ b/user/src/com/google/gwt/user/client/ui/DoubleBox.java
@@ -13,10 +13,11 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.client;
+package com.google.gwt.user.client.ui;
import com.google.gwt.dom.client.Document;
-import com.google.gwt.user.client.ui.ValueBox;
+import com.google.gwt.text.client.DoubleParser;
+import com.google.gwt.text.client.DoubleRenderer;
/**
* <span style="color:red">Experimental API: This class is still under rapid
diff --git a/user/src/com/google/gwt/app/client/IntegerBox.java b/user/src/com/google/gwt/user/client/ui/IntegerBox.java
similarity index 88%
rename from user/src/com/google/gwt/app/client/IntegerBox.java
rename to user/src/com/google/gwt/user/client/ui/IntegerBox.java
index 3e762ff..0f6b1f6 100644
--- a/user/src/com/google/gwt/app/client/IntegerBox.java
+++ b/user/src/com/google/gwt/user/client/ui/IntegerBox.java
@@ -13,10 +13,11 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.client;
+package com.google.gwt.user.client.ui;
import com.google.gwt.dom.client.Document;
-import com.google.gwt.user.client.ui.ValueBox;
+import com.google.gwt.text.client.IntegerParser;
+import com.google.gwt.text.client.IntegerRenderer;
/**
* <span style="color:red">Experimental API: This class is still under rapid
diff --git a/user/src/com/google/gwt/user/client/ui/Label.java b/user/src/com/google/gwt/user/client/ui/Label.java
index 22a6daa..7c81449 100644
--- a/user/src/com/google/gwt/user/client/ui/Label.java
+++ b/user/src/com/google/gwt/user/client/ui/Label.java
@@ -19,7 +19,7 @@
import com.google.gwt.dom.client.Element;
import com.google.gwt.editor.client.IsEditor;
import com.google.gwt.editor.client.LeafValueEditor;
-import com.google.gwt.editor.client.adapters.HasTextEditor;
+import com.google.gwt.editor.ui.client.adapters.HasTextEditor;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.DoubleClickEvent;
diff --git a/user/src/com/google/gwt/app/client/LongBox.java b/user/src/com/google/gwt/user/client/ui/LongBox.java
similarity index 88%
rename from user/src/com/google/gwt/app/client/LongBox.java
rename to user/src/com/google/gwt/user/client/ui/LongBox.java
index a4e2d70..0121583 100644
--- a/user/src/com/google/gwt/app/client/LongBox.java
+++ b/user/src/com/google/gwt/user/client/ui/LongBox.java
@@ -13,10 +13,11 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.client;
+package com.google.gwt.user.client.ui;
import com.google.gwt.dom.client.Document;
-import com.google.gwt.user.client.ui.ValueBox;
+import com.google.gwt.text.client.LongParser;
+import com.google.gwt.text.client.LongRenderer;
/**
* <span style="color:red">Experimental API: This class is still under rapid
diff --git a/user/src/com/google/gwt/app/client/NotificationMole.java b/user/src/com/google/gwt/user/client/ui/NotificationMole.java
similarity index 96%
rename from user/src/com/google/gwt/app/client/NotificationMole.java
rename to user/src/com/google/gwt/user/client/ui/NotificationMole.java
index 9ba20f1..47a726f 100644
--- a/user/src/com/google/gwt/app/client/NotificationMole.java
+++ b/user/src/com/google/gwt/user/client/ui/NotificationMole.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.client;
+package com.google.gwt.user.client.ui;
import com.google.gwt.animation.client.Animation;
import com.google.gwt.core.client.GWT;
@@ -25,8 +25,6 @@
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.ui.Composite;
-import com.google.gwt.user.client.ui.HTMLPanel;
/**
* <p>
diff --git a/user/src/com/google/gwt/app/client/NotificationMole.ui.xml b/user/src/com/google/gwt/user/client/ui/NotificationMole.ui.xml
similarity index 100%
rename from user/src/com/google/gwt/app/client/NotificationMole.ui.xml
rename to user/src/com/google/gwt/user/client/ui/NotificationMole.ui.xml
diff --git a/user/src/com/google/gwt/user/client/ui/TextBoxBase.java b/user/src/com/google/gwt/user/client/ui/TextBoxBase.java
index eab38ab..9a710b2 100644
--- a/user/src/com/google/gwt/user/client/ui/TextBoxBase.java
+++ b/user/src/com/google/gwt/user/client/ui/TextBoxBase.java
@@ -16,27 +16,42 @@
package com.google.gwt.user.client.ui;
import com.google.gwt.dom.client.Element;
-import com.google.gwt.text.shared.PassthroughParser;
-import com.google.gwt.text.shared.PassthroughRenderer;
+import com.google.gwt.text.shared.testing.PassthroughParser;
+import com.google.gwt.text.shared.testing.PassthroughRenderer;
/**
- * Legacy abstract base class for all text entry widgets.
+ * Abstract base class for most text entry widgets.
+ *
+ * <p>
+ * The names of the static members of {@link TextBoxBase}, as well as simple
+ * alignment names (<code>left</code>, <code>center</code>, <code>right</code>,
+ * <code>justify</code>), can be used as values for a <code>textAlignment</code>
+ * attribute.
+ * <p>
+ * For example,
+ *
+ * <pre>
+ * <g:TextBox textAlignment='ALIGN_RIGHT'/>
+ * <g:TextBox textAlignment='right'/>
+ * </pre>
*/
-public class TextBoxBase extends ValueBoxBase<String> {
+public class TextBoxBase extends ValueBoxBase<String> implements
+ SourcesChangeEvents {
/**
- * Text alignment constant, used in
- * {@link TextBoxBase#setTextAlignment(TextBoxBase.TextAlignConstant)}.
+ * Legacy wrapper for {@link TextAlignment}, soon to be deprecated.
+ * @deprecated use {@link #setAlignment(TextAlignment)}
*/
+ @Deprecated
public static class TextAlignConstant {
- private String textAlignString;
+ private TextAlignment value;
- private TextAlignConstant(String textAlignString) {
- this.textAlignString = textAlignString;
+ private TextAlignConstant(TextAlignment value) {
+ this.value = value;
}
- String getTextAlignString() {
- return textAlignString;
+ TextAlignment getTextAlignString() {
+ return value;
}
}
@@ -44,25 +59,25 @@
* Center the text.
*/
public static final TextAlignConstant ALIGN_CENTER = new TextAlignConstant(
- "center");
+ TextAlignment.CENTER);
/**
* Justify the text.
*/
public static final TextAlignConstant ALIGN_JUSTIFY = new TextAlignConstant(
- "justify");
+ TextAlignment.JUSTIFY);
/**
* Align the text to the left edge.
*/
public static final TextAlignConstant ALIGN_LEFT = new TextAlignConstant(
- "left");
+ TextAlignment.LEFT);
/**
* Align the text to the right.
*/
public static final TextAlignConstant ALIGN_RIGHT = new TextAlignConstant(
- "right");
+ TextAlignment.RIGHT);
/**
* Creates a text box that wraps the given browser element handle. This is
@@ -75,6 +90,14 @@
}
/**
+ * @deprecated Use {@link #addChangeHandler} instead
+ */
+ @Deprecated
+ public void addChangeListener(ChangeListener listener) {
+ addChangeHandler(new ListenerWrapper.WrappedChangeListener(listener));
+ }
+
+ /**
* Overridden to return "" from an empty text box.
*/
@Override
@@ -82,4 +105,14 @@
String raw = super.getValue();
return raw == null ? "" : raw;
}
+
+ /**
+ * Legacy wrapper for {@link #setAlignment(TextAlignment)}.
+ *
+ * @deprecated use {@link #setAlignment(TextAlignment)}
+ */
+ @Deprecated
+ public void setTextAlignment(TextAlignConstant align) {
+ setAlignment(align.value);
+ }
}
diff --git a/user/src/com/google/gwt/user/client/ui/ValueBoxBase.java b/user/src/com/google/gwt/user/client/ui/ValueBoxBase.java
index ed1dd09..d24f2a3 100644
--- a/user/src/com/google/gwt/user/client/ui/ValueBoxBase.java
+++ b/user/src/com/google/gwt/user/client/ui/ValueBoxBase.java
@@ -18,7 +18,7 @@
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.editor.client.IsEditor;
-import com.google.gwt.editor.client.adapters.ValueBoxEditor;
+import com.google.gwt.editor.ui.client.adapters.ValueBoxEditor;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.HasChangeHandlers;
@@ -34,48 +34,57 @@
import com.google.gwt.text.shared.Renderer;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.ui.TextBoxBase.TextAlignConstant;
import com.google.gwt.user.client.ui.impl.TextBoxImpl;
import java.text.ParseException;
/**
- * <span style="color:red">Experimental API: This class is still under rapid
- * development, and is very likely to be deleted. Use it at your own risk.
- * </span>
- * <p>
* Abstract base class for all text entry widgets.
*
* <h3>Use in UiBinder Templates</h3>
*
- * <p>
- * The names of the static members of {@link TextBoxBase}, as well as simple
- * alignment names (<code>left</code>, <code>center</code>, <code>right</code>,
- * <code>justify</code>), can be used as values for a <code>textAlignment</code>
- * attribute.
- * <p>
- * For example,
- *
- * <pre>
- * <g:TextBox textAlignment='ALIGN_RIGHT'/>
- * <g:TextBox textAlignment='right'/>
- * </pre>
- *
* @param <T> the value type
*/
@SuppressWarnings("deprecation")
public class ValueBoxBase<T> extends FocusWidget implements
- SourcesChangeEvents, HasChangeHandlers, HasName, HasDirectionEstimator,
+ HasChangeHandlers, HasName, HasDirectionEstimator,
HasValue<T>, AutoDirectionHandler.Target, IsEditor<ValueBoxEditor<T>> {
- private static TextBoxImpl impl = GWT.create(TextBoxImpl.class);
+ /**
+ * Alignment values for {@link ValueBoxBase#setAlignment}.
+ */
+ public enum TextAlignment {
+ CENTER {
+ String getTextAlignString() {
+ return "center";
+ }
+ },
+ JUSTIFY {
+ String getTextAlignString() {
+ return "justify";
+ }
+ },
+ LEFT {
+ String getTextAlignString() {
+ return "left";
+ }
+ },
+ RIGHT {
+ String getTextAlignString() {
+ return "right";
+ }
+ };
+ abstract String getTextAlignString();
+ }
+
+ private static TextBoxImpl impl = GWT.create(TextBoxImpl.class);
private final AutoDirectionHandler autoDirHandler;
private final Parser<T> parser;
private final Renderer<T> renderer;
-
private Event currentEvent;
+
private boolean valueChangeHandlerInitialized;
/**
@@ -96,14 +105,6 @@
return addDomHandler(handler, ChangeEvent.getType());
}
- /**
- * @deprecated Use {@link #addChangeHandler} instead
- */
- @Deprecated
- public void addChangeListener(ChangeListener listener) {
- addChangeHandler(new ListenerWrapper.WrappedChangeListener(listener));
- }
-
public HandlerRegistration addValueChangeHandler(ValueChangeHandler<T> handler) {
// Initialization code
if (!valueChangeHandlerInitialized) {
@@ -267,6 +268,10 @@
}
}
+ public void setAlignment(TextAlignment align) {
+ DOM.setStyleAttribute(getElement(), "textAlign", align.getTextAlignString());
+ }
+
/**
* Sets the cursor position.
*
@@ -358,7 +363,7 @@
}
impl.setSelectionRange(getElement(), pos, length);
}
-
+
/**
* Sets this object's text. Note that some browsers will manipulate the text
* before adding it to the widget. For example, most browsers will strip all
@@ -373,18 +378,6 @@
autoDirHandler.refreshDirection();
}
- /**
- * Sets the alignment of the text in the text box.
- *
- * @param align the text alignment (as specified by
- * {@link TextBoxBase#ALIGN_CENTER},
- * {@link TextBoxBase#ALIGN_JUSTIFY}, {@link TextBoxBase#ALIGN_LEFT},
- * and {@link TextBoxBase#ALIGN_RIGHT})
- */
- public void setTextAlignment(TextAlignConstant align) {
- DOM.setStyleAttribute(getElement(), "textAlign", align.getTextAlignString());
- }
-
public void setValue(T value) {
setValue(value, false);
}
diff --git a/user/src/com/google/gwt/view/client/AsyncDataProvider.java b/user/src/com/google/gwt/view/client/AsyncDataProvider.java
index 78fcb9e..73cbf88 100644
--- a/user/src/com/google/gwt/view/client/AsyncDataProvider.java
+++ b/user/src/com/google/gwt/view/client/AsyncDataProvider.java
@@ -22,7 +22,8 @@
* modified.
*
* <p>
- * Note: This class is new and its interface subject to change.
+ * <h3>Example</h3>
+ * TODO example com.google.gwt.examples.view.AsyncDataProviderExample
* </p>
*
* @param <T> the data type of records in the list
diff --git a/user/src/com/google/gwt/view/client/ListDataProvider.java b/user/src/com/google/gwt/view/client/ListDataProvider.java
index 9674447..ca6df3b 100644
--- a/user/src/com/google/gwt/view/client/ListDataProvider.java
+++ b/user/src/com/google/gwt/view/client/ListDataProvider.java
@@ -30,7 +30,8 @@
* in-memory list.
*
* <p>
- * Note: This class is new and its interface subject to change.
+ * <h3>Example</h3>
+ * TODO example com.google.gwt.examples.view.ListDataProviderExample
* </p>
*
* @param <T> the data type of the list
diff --git a/user/test/com/google/gwt/app/AppSuite.java b/user/test/com/google/gwt/activity/ActivitySuite.java
similarity index 66%
rename from user/test/com/google/gwt/app/AppSuite.java
rename to user/test/com/google/gwt/activity/ActivitySuite.java
index af744ed..cf43d25 100644
--- a/user/test/com/google/gwt/app/AppSuite.java
+++ b/user/test/com/google/gwt/activity/ActivitySuite.java
@@ -13,21 +13,20 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app;
+package com.google.gwt.activity;
-import com.google.gwt.app.place.impl.PlaceHistoryMapperGeneratorTest;
-import com.google.gwt.junit.tools.GWTTestSuite;
+import com.google.gwt.activity.shared.ActivityManagerTest;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
- * Suite of app package tests that require GWT.
+ * Tests of the activity package.
*/
-public class AppSuite {
+public class ActivitySuite {
public static Test suite() {
- TestSuite suite = new GWTTestSuite("app package tests that require GWT");
- suite.addTestSuite(PlaceHistoryMapperGeneratorTest.class);
+ TestSuite suite = new TestSuite("Tests of the activity package");
+ suite.addTestSuite(ActivityManagerTest.class);
return suite;
}
}
diff --git a/user/test/com/google/gwt/app/place/ActivityManagerTest.java b/user/test/com/google/gwt/activity/shared/ActivityManagerTest.java
similarity index 98%
rename from user/test/com/google/gwt/app/place/ActivityManagerTest.java
rename to user/test/com/google/gwt/activity/shared/ActivityManagerTest.java
index 0410922..d5d47d0 100644
--- a/user/test/com/google/gwt/app/place/ActivityManagerTest.java
+++ b/user/test/com/google/gwt/activity/shared/ActivityManagerTest.java
@@ -13,13 +13,16 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.activity.shared;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.UmbrellaException;
import com.google.gwt.event.shared.testing.CountingEventBus;
+import com.google.gwt.place.shared.Place;
+import com.google.gwt.place.shared.PlaceChangeEvent;
+import com.google.gwt.place.shared.PlaceChangeRequestEvent;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
diff --git a/user/test/com/google/gwt/place/PlaceSuite.gwt.xml b/user/test/com/google/gwt/place/PlaceSuite.gwt.xml
new file mode 100644
index 0000000..44c1d91
--- /dev/null
+++ b/user/test/com/google/gwt/place/PlaceSuite.gwt.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 0.0.999//EN" "http://google-web-toolkit.googlecode.com/svn/tags/0.0.999/distro-source/core/src/gwt-module.dtd">
+<module>
+ <inherits name='com.google.gwt.place.Place'/>
+
+ <source path="testplaces"/>
+ <source path="testplacemappers"/>
+</module>
diff --git a/user/test/com/google/gwt/app/AppJreSuite.java b/user/test/com/google/gwt/place/PlaceSuite.java
similarity index 61%
rename from user/test/com/google/gwt/app/AppJreSuite.java
rename to user/test/com/google/gwt/place/PlaceSuite.java
index 5708bf5..e9aa7e8 100644
--- a/user/test/com/google/gwt/app/AppJreSuite.java
+++ b/user/test/com/google/gwt/place/PlaceSuite.java
@@ -13,24 +13,25 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app;
+package com.google.gwt.place;
-import com.google.gwt.app.place.ActivityManagerTest;
-import com.google.gwt.app.place.PlaceChangeRequestEventTest;
-import com.google.gwt.app.place.PlaceControllerTest;
-import com.google.gwt.app.place.PlaceHistoryHandlerTest;
-import com.google.gwt.app.rebind.PlaceHistoryGeneratorContextTest;
+import com.google.gwt.junit.tools.GWTTestSuite;
+import com.google.gwt.place.impl.PlaceHistoryMapperGeneratorTest;
+import com.google.gwt.place.rebind.PlaceHistoryGeneratorContextTest;
+import com.google.gwt.place.shared.PlaceChangeRequestEventTest;
+import com.google.gwt.place.shared.PlaceControllerTest;
+import com.google.gwt.place.shared.PlaceHistoryHandlerTest;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
- * Suite of app package tests that require the JRE.
+ * Tests of the place package.
*/
-public class AppJreSuite {
+public class PlaceSuite {
public static Test suite() {
- TestSuite suite = new TestSuite("app package tests that require the JRE");
- suite.addTestSuite(ActivityManagerTest.class);
+ TestSuite suite = new GWTTestSuite("Tests of the place package");
+ suite.addTestSuite(PlaceHistoryMapperGeneratorTest.class);
suite.addTestSuite(PlaceControllerTest.class);
suite.addTestSuite(PlaceChangeRequestEventTest.class);
suite.addTestSuite(PlaceHistoryGeneratorContextTest.class);
diff --git a/user/test/com/google/gwt/app/place/impl/PlaceHistoryMapperGeneratorTest.java b/user/test/com/google/gwt/place/impl/PlaceHistoryMapperGeneratorTest.java
similarity index 81%
rename from user/test/com/google/gwt/app/place/impl/PlaceHistoryMapperGeneratorTest.java
rename to user/test/com/google/gwt/place/impl/PlaceHistoryMapperGeneratorTest.java
index b7a0daa..f3061f1 100644
--- a/user/test/com/google/gwt/app/place/impl/PlaceHistoryMapperGeneratorTest.java
+++ b/user/test/com/google/gwt/place/impl/PlaceHistoryMapperGeneratorTest.java
@@ -13,25 +13,25 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place.impl;
+package com.google.gwt.place.impl;
-import com.google.gwt.app.place.Place;
-import com.google.gwt.app.place.PlaceHistoryMapper;
-import com.google.gwt.app.place.PlaceHistoryMapperWithFactory;
-import com.google.gwt.app.place.WithTokenizers;
-import com.google.gwt.app.place.testplacemappers.NoFactory;
-import com.google.gwt.app.place.testplacemappers.WithFactory;
-import com.google.gwt.app.place.testplaces.Place1;
-import com.google.gwt.app.place.testplaces.Place2;
-import com.google.gwt.app.place.testplaces.Place3;
-import com.google.gwt.app.place.testplaces.Place4;
-import com.google.gwt.app.place.testplaces.Place5;
-import com.google.gwt.app.place.testplaces.Tokenizer2;
-import com.google.gwt.app.place.testplaces.Tokenizer3;
-import com.google.gwt.app.place.testplaces.Tokenizer4;
-import com.google.gwt.app.place.testplaces.TokenizerFactory;
import com.google.gwt.core.client.GWT;
import com.google.gwt.junit.client.GWTTestCase;
+import com.google.gwt.place.shared.Place;
+import com.google.gwt.place.shared.PlaceHistoryMapper;
+import com.google.gwt.place.shared.PlaceHistoryMapperWithFactory;
+import com.google.gwt.place.shared.WithTokenizers;
+import com.google.gwt.place.testplacemappers.NoFactory;
+import com.google.gwt.place.testplacemappers.WithFactory;
+import com.google.gwt.place.testplaces.Place1;
+import com.google.gwt.place.testplaces.Place2;
+import com.google.gwt.place.testplaces.Place3;
+import com.google.gwt.place.testplaces.Place4;
+import com.google.gwt.place.testplaces.Place5;
+import com.google.gwt.place.testplaces.Tokenizer2;
+import com.google.gwt.place.testplaces.Tokenizer3;
+import com.google.gwt.place.testplaces.Tokenizer4;
+import com.google.gwt.place.testplaces.TokenizerFactory;
/**
* Functional test of PlaceHistoryMapperGenerator.
@@ -50,7 +50,7 @@
@Override
public String getModuleName() {
- return "com.google.gwt.app.App";
+ return "com.google.gwt.place.PlaceSuite";
}
Place1 place1 = new Place1("able");
diff --git a/user/test/com/google/gwt/app/rebind/EmptyMockJavaResource.java b/user/test/com/google/gwt/place/rebind/EmptyMockJavaResource.java
similarity index 97%
rename from user/test/com/google/gwt/app/rebind/EmptyMockJavaResource.java
rename to user/test/com/google/gwt/place/rebind/EmptyMockJavaResource.java
index eb3c5d3..588b059 100644
--- a/user/test/com/google/gwt/app/rebind/EmptyMockJavaResource.java
+++ b/user/test/com/google/gwt/place/rebind/EmptyMockJavaResource.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.rebind;
+package com.google.gwt.place.rebind;
import com.google.gwt.dev.javac.impl.MockJavaResource;
diff --git a/user/test/com/google/gwt/app/rebind/MostToLeastDerivedPlaceTypeComparatorTest.java b/user/test/com/google/gwt/place/rebind/MostToLeastDerivedPlaceTypeComparatorTest.java
similarity index 83%
rename from user/test/com/google/gwt/app/rebind/MostToLeastDerivedPlaceTypeComparatorTest.java
rename to user/test/com/google/gwt/place/rebind/MostToLeastDerivedPlaceTypeComparatorTest.java
index 8f5dcbe..ac66a88 100644
--- a/user/test/com/google/gwt/app/rebind/MostToLeastDerivedPlaceTypeComparatorTest.java
+++ b/user/test/com/google/gwt/place/rebind/MostToLeastDerivedPlaceTypeComparatorTest.java
@@ -13,16 +13,8 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.rebind;
+package com.google.gwt.place.rebind;
-import com.google.gwt.app.place.Place;
-import com.google.gwt.app.place.PlaceTokenizer;
-import com.google.gwt.app.place.Prefix;
-import com.google.gwt.app.place.testplaces.Place1;
-import com.google.gwt.app.place.testplaces.Place2;
-import com.google.gwt.app.place.testplaces.Place3;
-import com.google.gwt.app.place.testplaces.Place4;
-import com.google.gwt.app.place.testplaces.Place5;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
@@ -31,6 +23,14 @@
import com.google.gwt.dev.javac.impl.JavaResourceBase;
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
+import com.google.gwt.place.shared.Place;
+import com.google.gwt.place.shared.PlaceTokenizer;
+import com.google.gwt.place.shared.Prefix;
+import com.google.gwt.place.testplaces.Place1;
+import com.google.gwt.place.testplaces.Place2;
+import com.google.gwt.place.testplaces.Place3;
+import com.google.gwt.place.testplaces.Place4;
+import com.google.gwt.place.testplaces.Place5;
import junit.framework.TestCase;
@@ -73,17 +73,17 @@
getJavaResources());
typeOracle = state.getTypeOracle();
- place = typeOracle.getType("com.google.gwt.app.place.Place");
+ place = typeOracle.getType("com.google.gwt.app.place.shared.Place");
assertNotNull(place);
- place1 = typeOracle.getType("com.google.gwt.app.place.testplaces.Place1");
+ place1 = typeOracle.getType("com.google.gwt.app.place.shared.testplaces.Place1");
assertNotNull(place1);
- place2 = typeOracle.getType("com.google.gwt.app.place.testplaces.Place2");
+ place2 = typeOracle.getType("com.google.gwt.app.place.shared.testplaces.Place2");
assertNotNull(place2);
- place3 = typeOracle.getType("com.google.gwt.app.place.testplaces.Place3");
+ place3 = typeOracle.getType("com.google.gwt.app.place.shared.testplaces.Place3");
assertNotNull(place3);
- place4 = typeOracle.getType("com.google.gwt.app.place.testplaces.Place4");
+ place4 = typeOracle.getType("com.google.gwt.app.place.shared.testplaces.Place4");
assertNotNull(place4);
- place5 = typeOracle.getType("com.google.gwt.app.place.testplaces.Place5");
+ place5 = typeOracle.getType("com.google.gwt.app.place.shared.testplaces.Place5");
assertNotNull(place5);
}
diff --git a/user/test/com/google/gwt/app/rebind/PlaceHistoryGeneratorContextTest.java b/user/test/com/google/gwt/place/rebind/PlaceHistoryGeneratorContextTest.java
similarity index 87%
rename from user/test/com/google/gwt/app/rebind/PlaceHistoryGeneratorContextTest.java
rename to user/test/com/google/gwt/place/rebind/PlaceHistoryGeneratorContextTest.java
index c188e13..7855f62 100644
--- a/user/test/com/google/gwt/app/rebind/PlaceHistoryGeneratorContextTest.java
+++ b/user/test/com/google/gwt/place/rebind/PlaceHistoryGeneratorContextTest.java
@@ -13,24 +13,8 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.rebind;
+package com.google.gwt.place.rebind;
-import com.google.gwt.app.place.Place;
-import com.google.gwt.app.place.PlaceHistoryMapper;
-import com.google.gwt.app.place.PlaceHistoryMapperWithFactory;
-import com.google.gwt.app.place.PlaceTokenizer;
-import com.google.gwt.app.place.Prefix;
-import com.google.gwt.app.place.WithTokenizers;
-import com.google.gwt.app.place.testplacemappers.NoFactory;
-import com.google.gwt.app.place.testplacemappers.WithFactory;
-import com.google.gwt.app.place.testplaces.Place1;
-import com.google.gwt.app.place.testplaces.Place2;
-import com.google.gwt.app.place.testplaces.Place3;
-import com.google.gwt.app.place.testplaces.Place4;
-import com.google.gwt.app.place.testplaces.Tokenizer2;
-import com.google.gwt.app.place.testplaces.Tokenizer3;
-import com.google.gwt.app.place.testplaces.Tokenizer4;
-import com.google.gwt.app.place.testplaces.TokenizerFactory;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
@@ -43,6 +27,22 @@
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.util.UnitTestTreeLogger;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
+import com.google.gwt.place.shared.Place;
+import com.google.gwt.place.shared.PlaceHistoryMapper;
+import com.google.gwt.place.shared.PlaceHistoryMapperWithFactory;
+import com.google.gwt.place.shared.PlaceTokenizer;
+import com.google.gwt.place.shared.Prefix;
+import com.google.gwt.place.shared.WithTokenizers;
+import com.google.gwt.place.testplacemappers.NoFactory;
+import com.google.gwt.place.testplacemappers.WithFactory;
+import com.google.gwt.place.testplaces.Place1;
+import com.google.gwt.place.testplaces.Place2;
+import com.google.gwt.place.testplaces.Place3;
+import com.google.gwt.place.testplaces.Place4;
+import com.google.gwt.place.testplaces.Tokenizer2;
+import com.google.gwt.place.testplaces.Tokenizer3;
+import com.google.gwt.place.testplaces.Tokenizer4;
+import com.google.gwt.place.testplaces.TokenizerFactory;
import junit.framework.TestCase;
@@ -197,11 +197,11 @@
protected CharSequence getContent() {
StringBuilder code = new StringBuilder();
code.append("package my;\n");
- code.append("import com.google.gwt.app.place.PlaceHistoryMapperWithFactory;\n");
- code.append("import com.google.gwt.app.place.WithTokenizers;\n");
- code.append("import com.google.gwt.app.place.Prefix;\n");
- code.append("import com.google.gwt.app.place.testplaces.Place1;\n");
- code.append("import com.google.gwt.app.place.testplaces.Tokenizer2;\n");
+ code.append("import com.google.gwt.place.shared.PlaceHistoryMapperWithFactory;\n");
+ code.append("import com.google.gwt.place.shared.WithTokenizers;\n");
+ code.append("import com.google.gwt.place.shared.Prefix;\n");
+ code.append("import com.google.gwt.place.testplaces.Place1;\n");
+ code.append("import com.google.gwt.place.testplaces.Tokenizer2;\n");
code.append("@WithTokenizers(Place1.Tokenizer.class)\n");
code.append("public interface MyPlaceHistoryMapper extends PlaceHistoryMapperWithFactory<MyPlaceHistoryMapper.Factory> {\n");
@@ -242,11 +242,11 @@
protected CharSequence getContent() {
StringBuilder code = new StringBuilder();
code.append("package my;\n");
- code.append("import com.google.gwt.app.place.PlaceHistoryMapperWithFactory;\n");
- code.append("import com.google.gwt.app.place.PlaceTokenizer;\n");
- code.append("import com.google.gwt.app.place.WithTokenizers;\n");
- code.append("import com.google.gwt.app.place.Prefix;\n");
- code.append("import com.google.gwt.app.place.testplaces.Place1;\n");
+ code.append("import com.google.gwt.place.shared.PlaceHistoryMapperWithFactory;\n");
+ code.append("import com.google.gwt.place.shared.PlaceTokenizer;\n");
+ code.append("import com.google.gwt.place.shared.WithTokenizers;\n");
+ code.append("import com.google.gwt.place.shared.Prefix;\n");
+ code.append("import com.google.gwt.place.testplaces.Place1;\n");
code.append("@WithTokenizers(Place1.Tokenizer.class)\n");
code.append("public interface MyPlaceHistoryMapper extends PlaceHistoryMapperWithFactory<MyPlaceHistoryMapper.Factory> {\n");
@@ -288,10 +288,10 @@
protected CharSequence getContent() {
StringBuilder code = new StringBuilder();
code.append("package my;\n");
- code.append("import com.google.gwt.app.place.Place;\n");
- code.append("import com.google.gwt.app.place.PlaceHistoryMapperWithFactory;\n");
- code.append("import com.google.gwt.app.place.PlaceTokenizer;\n");
- code.append("import com.google.gwt.app.place.Prefix;\n");
+ code.append("import com.google.gwt.place.shared.Place;\n");
+ code.append("import com.google.gwt.place.shared.PlaceHistoryMapperWithFactory;\n");
+ code.append("import com.google.gwt.place.shared.PlaceTokenizer;\n");
+ code.append("import com.google.gwt.place.shared.Prefix;\n");
code.append("public interface MyPlaceHistoryMapper extends PlaceHistoryMapperWithFactory<MyPlaceHistoryMapper.Factory> {\n");
code.append(" interface Factory {\n");
diff --git a/user/test/com/google/gwt/app/rebind/RealJavaResource.java b/user/test/com/google/gwt/place/rebind/RealJavaResource.java
similarity index 97%
rename from user/test/com/google/gwt/app/rebind/RealJavaResource.java
rename to user/test/com/google/gwt/place/rebind/RealJavaResource.java
index a18e161..d527758 100644
--- a/user/test/com/google/gwt/app/rebind/RealJavaResource.java
+++ b/user/test/com/google/gwt/place/rebind/RealJavaResource.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.rebind;
+package com.google.gwt.place.rebind;
import com.google.gwt.dev.javac.impl.MockJavaResource;
import com.google.gwt.dev.util.Util;
diff --git a/user/test/com/google/gwt/app/place/MockPlaceControllerDelegate.java b/user/test/com/google/gwt/place/shared/MockPlaceControllerDelegate.java
similarity index 97%
rename from user/test/com/google/gwt/app/place/MockPlaceControllerDelegate.java
rename to user/test/com/google/gwt/place/shared/MockPlaceControllerDelegate.java
index 72964e9..7bb2ff0 100644
--- a/user/test/com/google/gwt/app/place/MockPlaceControllerDelegate.java
+++ b/user/test/com/google/gwt/place/shared/MockPlaceControllerDelegate.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.place.shared;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Window.ClosingEvent;
diff --git a/user/test/com/google/gwt/app/place/PlaceChangeRequestEventTest.java b/user/test/com/google/gwt/place/shared/PlaceChangeRequestEventTest.java
similarity index 96%
rename from user/test/com/google/gwt/app/place/PlaceChangeRequestEventTest.java
rename to user/test/com/google/gwt/place/shared/PlaceChangeRequestEventTest.java
index 0c121c2..46df9d9 100644
--- a/user/test/com/google/gwt/app/place/PlaceChangeRequestEventTest.java
+++ b/user/test/com/google/gwt/place/shared/PlaceChangeRequestEventTest.java
@@ -13,7 +13,8 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.place.shared;
+
import junit.framework.TestCase;
diff --git a/user/test/com/google/gwt/app/place/PlaceControllerTest.java b/user/test/com/google/gwt/place/shared/PlaceControllerTest.java
similarity index 98%
rename from user/test/com/google/gwt/app/place/PlaceControllerTest.java
rename to user/test/com/google/gwt/place/shared/PlaceControllerTest.java
index 6034c77..c3f133d 100644
--- a/user/test/com/google/gwt/app/place/PlaceControllerTest.java
+++ b/user/test/com/google/gwt/place/shared/PlaceControllerTest.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.place.shared;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.SimpleEventBus;
diff --git a/user/test/com/google/gwt/app/place/PlaceHistoryHandlerTest.java b/user/test/com/google/gwt/place/shared/PlaceHistoryHandlerTest.java
similarity index 95%
rename from user/test/com/google/gwt/app/place/PlaceHistoryHandlerTest.java
rename to user/test/com/google/gwt/place/shared/PlaceHistoryHandlerTest.java
index 5306086..05846c7 100644
--- a/user/test/com/google/gwt/app/place/PlaceHistoryHandlerTest.java
+++ b/user/test/com/google/gwt/place/shared/PlaceHistoryHandlerTest.java
@@ -13,15 +13,16 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place;
+package com.google.gwt.place.shared;
-import com.google.gwt.app.place.testplaces.Place1;
-import com.google.gwt.app.place.testplaces.Place2;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.SimpleEventBus;
+import com.google.gwt.place.shared.PlaceHistoryHandler.Historian;
+import com.google.gwt.place.testplaces.Place1;
+import com.google.gwt.place.testplaces.Place2;
import junit.framework.TestCase;
diff --git a/user/test/com/google/gwt/app/place/testplacemappers/NoFactory.java b/user/test/com/google/gwt/place/testplacemappers/NoFactory.java
similarity index 62%
rename from user/test/com/google/gwt/app/place/testplacemappers/NoFactory.java
rename to user/test/com/google/gwt/place/testplacemappers/NoFactory.java
index 6c36148..39ef9e9 100644
--- a/user/test/com/google/gwt/app/place/testplacemappers/NoFactory.java
+++ b/user/test/com/google/gwt/place/testplacemappers/NoFactory.java
@@ -13,17 +13,17 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place.testplacemappers;
+package com.google.gwt.place.testplacemappers;
-import com.google.gwt.app.place.PlaceHistoryMapper;
-import com.google.gwt.app.place.WithTokenizers;
-import com.google.gwt.app.place.testplaces.Place1;
-import com.google.gwt.app.place.testplaces.Tokenizer2;
-import com.google.gwt.app.place.testplaces.Tokenizer3;
-import com.google.gwt.app.place.testplaces.Tokenizer4;
+import com.google.gwt.place.shared.PlaceHistoryMapper;
+import com.google.gwt.place.shared.WithTokenizers;
+import com.google.gwt.place.testplaces.Place1;
+import com.google.gwt.place.testplaces.Tokenizer2;
+import com.google.gwt.place.testplaces.Tokenizer3;
+import com.google.gwt.place.testplaces.Tokenizer4;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
+ * Used by tests of {@link com.google.gwt.place.rebind.PlaceHistoryMapperGenerator}.
*/
@WithTokenizers({
Place1.Tokenizer.class, Tokenizer2.class, Tokenizer3.class,
diff --git a/user/test/com/google/gwt/app/place/testplacemappers/WithFactory.java b/user/test/com/google/gwt/place/testplacemappers/WithFactory.java
similarity index 66%
rename from user/test/com/google/gwt/app/place/testplacemappers/WithFactory.java
rename to user/test/com/google/gwt/place/testplacemappers/WithFactory.java
index bdcb6f1..29976a9 100644
--- a/user/test/com/google/gwt/app/place/testplacemappers/WithFactory.java
+++ b/user/test/com/google/gwt/place/testplacemappers/WithFactory.java
@@ -13,15 +13,15 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place.testplacemappers;
+package com.google.gwt.place.testplacemappers;
-import com.google.gwt.app.place.PlaceHistoryMapperWithFactory;
-import com.google.gwt.app.place.WithTokenizers;
-import com.google.gwt.app.place.testplaces.Tokenizer4;
-import com.google.gwt.app.place.testplaces.TokenizerFactory;
+import com.google.gwt.place.shared.PlaceHistoryMapperWithFactory;
+import com.google.gwt.place.shared.WithTokenizers;
+import com.google.gwt.place.testplaces.Tokenizer4;
+import com.google.gwt.place.testplaces.TokenizerFactory;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
+ * Used by tests of {@link com.google.gwt.place.rebind.PlaceHistoryMapperGenerator}.
*/
@WithTokenizers(Tokenizer4.class)
public interface WithFactory extends
diff --git a/user/test/com/google/gwt/app/place/testplaces/Place1.java b/user/test/com/google/gwt/place/testplaces/Place1.java
similarity index 80%
rename from user/test/com/google/gwt/app/place/testplaces/Place1.java
rename to user/test/com/google/gwt/place/testplaces/Place1.java
index 0e4dd55..587b182 100644
--- a/user/test/com/google/gwt/app/place/testplaces/Place1.java
+++ b/user/test/com/google/gwt/place/testplaces/Place1.java
@@ -13,14 +13,14 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place.testplaces;
+package com.google.gwt.place.testplaces;
-import com.google.gwt.app.place.Place;
-import com.google.gwt.app.place.PlaceTokenizer;
-import com.google.gwt.app.place.Prefix;
+import com.google.gwt.place.shared.Place;
+import com.google.gwt.place.shared.PlaceTokenizer;
+import com.google.gwt.place.shared.Prefix;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
+ * Used by tests of {@link com.google.gwt.place.rebind.PlaceHistoryMapperGenerator}.
*/
public class Place1 extends Place {
public final String content;
diff --git a/user/test/com/google/gwt/app/place/testplaces/Place2.java b/user/test/com/google/gwt/place/testplaces/Place2.java
similarity index 81%
rename from user/test/com/google/gwt/app/place/testplaces/Place2.java
rename to user/test/com/google/gwt/place/testplaces/Place2.java
index 425a5bb..c272aa9 100644
--- a/user/test/com/google/gwt/app/place/testplaces/Place2.java
+++ b/user/test/com/google/gwt/place/testplaces/Place2.java
@@ -13,12 +13,12 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place.testplaces;
+package com.google.gwt.place.testplaces;
-import com.google.gwt.app.place.Place;
+import com.google.gwt.place.shared.Place;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
+ * Used by tests of {@link com.google.gwt.place.rebind.PlaceHistoryMapperGenerator}.
*/
public class Place2 extends Place {
public final String content;
diff --git a/user/test/com/google/gwt/app/place/testplaces/Place3.java b/user/test/com/google/gwt/place/testplaces/Place3.java
similarity index 84%
rename from user/test/com/google/gwt/app/place/testplaces/Place3.java
rename to user/test/com/google/gwt/place/testplaces/Place3.java
index 2ec0c64..5092a2b 100644
--- a/user/test/com/google/gwt/app/place/testplaces/Place3.java
+++ b/user/test/com/google/gwt/place/testplaces/Place3.java
@@ -13,10 +13,10 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place.testplaces;
+package com.google.gwt.place.testplaces;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
+ * Used by tests of {@link com.google.gwt.place.rebind.PlaceHistoryMapperGenerator}.
*/
public class Place3 extends Place1 {
diff --git a/user/test/com/google/gwt/app/place/testplaces/Place4.java b/user/test/com/google/gwt/place/testplaces/Place4.java
similarity index 84%
rename from user/test/com/google/gwt/app/place/testplaces/Place4.java
rename to user/test/com/google/gwt/place/testplaces/Place4.java
index 3c98fee..37a976d 100644
--- a/user/test/com/google/gwt/app/place/testplaces/Place4.java
+++ b/user/test/com/google/gwt/place/testplaces/Place4.java
@@ -13,10 +13,10 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place.testplaces;
+package com.google.gwt.place.testplaces;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
+ * Used by tests of {@link com.google.gwt.place.rebind.PlaceHistoryMapperGenerator}.
*/
public class Place4 extends Place1 {
diff --git a/user/test/com/google/gwt/app/place/testplaces/Place5.java b/user/test/com/google/gwt/place/testplaces/Place5.java
similarity index 84%
rename from user/test/com/google/gwt/app/place/testplaces/Place5.java
rename to user/test/com/google/gwt/place/testplaces/Place5.java
index 47bfb1a..8df3e12 100644
--- a/user/test/com/google/gwt/app/place/testplaces/Place5.java
+++ b/user/test/com/google/gwt/place/testplaces/Place5.java
@@ -13,10 +13,10 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place.testplaces;
+package com.google.gwt.place.testplaces;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
+ * Used by tests of {@link com.google.gwt.place.rebind.PlaceHistoryMapperGenerator}.
*/
public class Place5 extends Place3 {
diff --git a/user/test/com/google/gwt/app/place/testplaces/Tokenizer2.java b/user/test/com/google/gwt/place/testplaces/Tokenizer2.java
similarity index 81%
rename from user/test/com/google/gwt/app/place/testplaces/Tokenizer2.java
rename to user/test/com/google/gwt/place/testplaces/Tokenizer2.java
index dc3d772..520efd7 100644
--- a/user/test/com/google/gwt/app/place/testplaces/Tokenizer2.java
+++ b/user/test/com/google/gwt/place/testplaces/Tokenizer2.java
@@ -13,12 +13,12 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place.testplaces;
+package com.google.gwt.place.testplaces;
-import com.google.gwt.app.place.PlaceTokenizer;
+import com.google.gwt.place.shared.PlaceTokenizer;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
+ * Used by tests of {@link com.google.gwt.place.rebind.PlaceHistoryMapperGenerator}.
*/
public class Tokenizer2 implements PlaceTokenizer<Place2> {
public Place2 getPlace(String token) {
diff --git a/user/test/com/google/gwt/app/place/testplaces/Tokenizer3.java b/user/test/com/google/gwt/place/testplaces/Tokenizer3.java
similarity index 81%
rename from user/test/com/google/gwt/app/place/testplaces/Tokenizer3.java
rename to user/test/com/google/gwt/place/testplaces/Tokenizer3.java
index f8a129a..854e488 100644
--- a/user/test/com/google/gwt/app/place/testplaces/Tokenizer3.java
+++ b/user/test/com/google/gwt/place/testplaces/Tokenizer3.java
@@ -13,12 +13,12 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place.testplaces;
+package com.google.gwt.place.testplaces;
-import com.google.gwt.app.place.PlaceTokenizer;
+import com.google.gwt.place.shared.PlaceTokenizer;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
+ * Used by tests of {@link com.google.gwt.place.rebind.PlaceHistoryMapperGenerator}.
*/
public class Tokenizer3 implements PlaceTokenizer<Place3> {
diff --git a/user/test/com/google/gwt/app/place/testplaces/Tokenizer4.java b/user/test/com/google/gwt/place/testplaces/Tokenizer4.java
similarity index 81%
rename from user/test/com/google/gwt/app/place/testplaces/Tokenizer4.java
rename to user/test/com/google/gwt/place/testplaces/Tokenizer4.java
index 089ca8c..7f41635 100644
--- a/user/test/com/google/gwt/app/place/testplaces/Tokenizer4.java
+++ b/user/test/com/google/gwt/place/testplaces/Tokenizer4.java
@@ -13,12 +13,12 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place.testplaces;
+package com.google.gwt.place.testplaces;
-import com.google.gwt.app.place.PlaceTokenizer;
+import com.google.gwt.place.shared.PlaceTokenizer;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
+ * Used by tests of {@link com.google.gwt.place.rebind.PlaceHistoryMapperGenerator}.
*/
public class Tokenizer4 implements PlaceTokenizer<Place4> {
public Place4 getPlace(String token) {
diff --git a/user/test/com/google/gwt/app/place/testplaces/TokenizerFactory.java b/user/test/com/google/gwt/place/testplaces/TokenizerFactory.java
similarity index 83%
rename from user/test/com/google/gwt/app/place/testplaces/TokenizerFactory.java
rename to user/test/com/google/gwt/place/testplaces/TokenizerFactory.java
index 60046b4..24210b5 100644
--- a/user/test/com/google/gwt/app/place/testplaces/TokenizerFactory.java
+++ b/user/test/com/google/gwt/place/testplaces/TokenizerFactory.java
@@ -13,13 +13,13 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place.testplaces;
+package com.google.gwt.place.testplaces;
-import com.google.gwt.app.place.PlaceTokenizer;
-import com.google.gwt.app.place.Prefix;
+import com.google.gwt.place.shared.PlaceTokenizer;
+import com.google.gwt.place.shared.Prefix;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
+ * Used by tests of {@link com.google.gwt.place.rebind.PlaceHistoryMapperGenerator}.
*/
public class TokenizerFactory {
public static final String PLACE2_PREFIX = "p2";
diff --git a/user/test/com/google/gwt/requestfactory/RequestFactoryJreSuite.java b/user/test/com/google/gwt/requestfactory/RequestFactoryJreSuite.java
index 1f71e90..a6ad74a 100644
--- a/user/test/com/google/gwt/requestfactory/RequestFactoryJreSuite.java
+++ b/user/test/com/google/gwt/requestfactory/RequestFactoryJreSuite.java
@@ -16,6 +16,7 @@
package com.google.gwt.requestfactory;
import com.google.gwt.requestfactory.client.impl.SimpleEntityProxyIdTest;
+import com.google.gwt.requestfactory.rebind.model.RequestFactoryModelTest;
import com.google.gwt.requestfactory.server.JsonRequestProcessorTest;
import com.google.gwt.requestfactory.server.ReflectionBasedOperationRegistryTest;
import com.google.gwt.requestfactory.server.RequestPropertyTest;
@@ -33,6 +34,7 @@
suite.addTestSuite(SimpleEntityProxyIdTest.class);
suite.addTestSuite(JsonRequestProcessorTest.class);
suite.addTestSuite(ReflectionBasedOperationRegistryTest.class);
+ suite.addTestSuite(RequestFactoryModelTest.class);
suite.addTestSuite(RequestPropertyTest.class);
return suite;
}
diff --git a/user/test/com/google/gwt/requestfactory/RequestFactorySuite.java b/user/test/com/google/gwt/requestfactory/RequestFactorySuite.java
index b99fc29..44de728 100644
--- a/user/test/com/google/gwt/requestfactory/RequestFactorySuite.java
+++ b/user/test/com/google/gwt/requestfactory/RequestFactorySuite.java
@@ -16,11 +16,11 @@
package com.google.gwt.requestfactory;
import com.google.gwt.junit.tools.GWTTestSuite;
-import com.google.gwt.requestfactory.client.EditorTest;
import com.google.gwt.requestfactory.client.FindServiceTest;
import com.google.gwt.requestfactory.client.RequestFactoryExceptionHandlerTest;
import com.google.gwt.requestfactory.client.RequestFactoryStringTest;
import com.google.gwt.requestfactory.client.RequestFactoryTest;
+import com.google.gwt.requestfactory.client.ui.EditorTest;
import junit.framework.Test;
diff --git a/user/test/com/google/gwt/requestfactory/client/RequestFactoryStringTest.java b/user/test/com/google/gwt/requestfactory/client/RequestFactoryStringTest.java
index 8917683..fa7c212 100644
--- a/user/test/com/google/gwt/requestfactory/client/RequestFactoryStringTest.java
+++ b/user/test/com/google/gwt/requestfactory/client/RequestFactoryStringTest.java
@@ -164,6 +164,50 @@
});
}
+ public void testFindFindEdit() {
+ delayTestFinish(5000);
+
+ final SimpleFooEventHandler<SimpleFooStringProxy> handler = new SimpleFooEventHandler<SimpleFooStringProxy>();
+ EntityProxyChange.registerForProxyType(req.getEventBus(),
+ SimpleFooStringProxy.class, handler);
+
+ req.simpleFooStringRequest().findSimpleFooStringById("999x").fire(
+ new Receiver<SimpleFooStringProxy>() {
+
+ @Override
+ public void onSuccess(SimpleFooStringProxy newFoo) {
+ assertEquals(1, handler.updateEventCount);
+ assertEquals(1, handler.totalEventCount);
+
+ req.simpleFooStringRequest().findSimpleFooStringById("999x").fire(
+ new Receiver<SimpleFooStringProxy>() {
+
+ @Override
+ public void onSuccess(SimpleFooStringProxy newFoo) {
+ // no events are fired second time.
+ assertEquals(1, handler.updateEventCount);
+ assertEquals(1, handler.totalEventCount);
+ SimpleFooStringRequest context = req.simpleFooStringRequest();
+ final Request<Void> mutateRequest = context.persist().using(
+ newFoo);
+ newFoo = context.edit(newFoo);
+ newFoo.setUserName("Ray");
+ mutateRequest.fire(new Receiver<Void>() {
+ @Override
+ public void onSuccess(Void response) {
+ // events fired on updates.
+ assertEquals(2, handler.updateEventCount);
+ assertEquals(2, handler.totalEventCount);
+
+ finishTestAndReset();
+ }
+ });
+ }
+ });
+ }
+ });
+ }
+
public void testFetchEntity() {
delayTestFinish(5000);
req.simpleFooStringRequest().findSimpleFooStringById("999x").fire(
@@ -275,8 +319,8 @@
@Override
public void onSuccess(SimpleFooStringProxy finalFoo) {
assertEquals("Ray", finalFoo.getUserName());
- assertEquals(3, handler.updateEventCount);
- assertEquals(3, handler.totalEventCount);
+ assertEquals(2, handler.updateEventCount);
+ assertEquals(2, handler.totalEventCount);
finishTestAndReset();
}
});
diff --git a/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java b/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java
index d83dafa..d454685 100644
--- a/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java
+++ b/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java
@@ -42,7 +42,6 @@
* Tests for {@link com.google.gwt.requestfactory.shared.RequestFactory}.
*/
public class RequestFactoryTest extends RequestFactoryTestBase {
- private static final int DELAY_TEST_FINISH = 5000;
/*
* DO NOT USE finishTest(). Instead, call finishTestAndReset();
@@ -168,14 +167,17 @@
}
}
+ private static final int DELAY_TEST_FINISH = 5000;
+
public <T extends EntityProxy> void assertContains(Collection<T> col, T value) {
for (T x : col) {
if (x.stableId().equals(value.stableId())) {
return;
}
}
- assertTrue(("Value " + value + " not found in collection ")
- + col.toString(), false);
+ assertTrue(
+ ("Value " + value + " not found in collection ") + col.toString(),
+ false);
}
public <T extends EntityProxy> void assertNotContains(Collection<T> col,
@@ -185,12 +187,132 @@
}
}
+ public void disabled_testEchoComplexFutures() {
+ // relate futures on the server. Check if the relationship is still present
+ // on the client.
+ delayTestFinish(DELAY_TEST_FINISH);
+ final SimpleFooEventHandler<SimpleFooProxy> handler = new SimpleFooEventHandler<SimpleFooProxy>();
+ EntityProxyChange.registerForProxyType(req.getEventBus(),
+ SimpleFooProxy.class, handler);
+ SimpleFooRequest context = req.simpleFooRequest();
+ final SimpleFooProxy simpleFoo = context.create(SimpleFooProxy.class);
+ final SimpleBarProxy simpleBar = context.create(SimpleBarProxy.class);
+ context.echoComplex(simpleFoo, simpleBar).fire(
+ new Receiver<SimpleFooProxy>() {
+ @Override
+ public void onSuccess(SimpleFooProxy response) {
+ assertEquals(0, handler.totalEventCount);
+ checkStableIdEquals(simpleFoo, response);
+ SimpleBarProxy responseBar = response.getBarField();
+ assertNotNull(responseBar);
+ checkStableIdEquals(simpleBar, responseBar);
+ finishTestAndReset();
+ }
+ });
+ }
+
+ public void disabled_testEchoSimpleFutures() {
+ // tests if futureIds can be echoed back.
+ delayTestFinish(DELAY_TEST_FINISH);
+ final SimpleFooEventHandler<SimpleFooProxy> handler = new SimpleFooEventHandler<SimpleFooProxy>();
+ EntityProxyChange.registerForProxyType(req.getEventBus(),
+ SimpleFooProxy.class, handler);
+ SimpleFooRequest context = req.simpleFooRequest();
+ final SimpleFooProxy simpleFoo = context.create(SimpleFooProxy.class);
+ context.echo(simpleFoo).fire(new Receiver<SimpleFooProxy>() {
+ @Override
+ public void onSuccess(SimpleFooProxy response) {
+ assertEquals(0, handler.totalEventCount);
+ checkStableIdEquals(simpleFoo, response);
+ finishTestAndReset();
+ }
+ });
+ }
+
+ /**
+ * Test that removing a parent entity and implicitly removing the child sends
+ * an event to the client that the child was removed.
+ *
+ * TODO(rjrjr): Should cascading deletes be detected?
+ */
+ public void disableTestMethodWithSideEffectDeleteChild() {
+ delayTestFinish(DELAY_TEST_FINISH);
+
+ // Persist bar.
+ SimpleBarRequest context = req.simpleBarRequest();
+ final SimpleBarProxy bar = context.create(SimpleBarProxy.class);
+ context.persistAndReturnSelf().using(bar).fire(
+ new Receiver<SimpleBarProxy>() {
+ @Override
+ public void onSuccess(SimpleBarProxy persistentBar) {
+ // Persist foo with bar as a child.
+ SimpleFooRequest context = req.simpleFooRequest();
+ SimpleFooProxy foo = context.create(SimpleFooProxy.class);
+ final Request<SimpleFooProxy> persistRequest = context.persistAndReturnSelf().using(
+ foo);
+ foo = context.edit(foo);
+ foo.setUserName("John");
+ foo.setBarField(bar);
+ persistRequest.fire(new Receiver<SimpleFooProxy>() {
+ @Override
+ public void onSuccess(SimpleFooProxy persistentFoo) {
+ // Handle changes to SimpleFooProxy.
+ final SimpleFooEventHandler<SimpleFooProxy> fooHandler = new SimpleFooEventHandler<SimpleFooProxy>();
+ EntityProxyChange.registerForProxyType(req.getEventBus(),
+ SimpleFooProxy.class, fooHandler);
+
+ // Handle changes to SimpleBarProxy.
+ final SimpleFooEventHandler<SimpleBarProxy> barHandler = new SimpleFooEventHandler<SimpleBarProxy>();
+ EntityProxyChange.registerForProxyType(req.getEventBus(),
+ SimpleBarProxy.class, barHandler);
+
+ // Delete bar.
+ SimpleFooRequest context = req.simpleFooRequest();
+ final Request<Void> deleteRequest = context.deleteBar().using(
+ persistentFoo);
+ SimpleFooProxy editable = context.edit(persistentFoo);
+ editable.setBarField(bar);
+ deleteRequest.fire(new Receiver<Void>() {
+ @Override
+ public void onSuccess(Void response) {
+ assertEquals(1, fooHandler.updateEventCount); // set bar to
+ // null
+ assertEquals(1, fooHandler.totalEventCount);
+
+ assertEquals(1, barHandler.deleteEventCount); // deleted bar
+ assertEquals(1, barHandler.totalEventCount);
+ finishTestAndReset();
+ }
+ });
+ }
+ });
+ }
+ });
+ }
+
@Override
public String getModuleName() {
return "com.google.gwt.requestfactory.RequestFactorySuite";
}
/**
+ * Test that the same object, referenced twice, points to the same instance.
+ */
+ public void testAntiAliasing() {
+ delayTestFinish(DELAY_TEST_FINISH);
+ simpleFooRequest().fetchDoubleReference().with("fooField",
+ "selfOneToManyField").fire(new Receiver<SimpleFooProxy>() {
+ @Override
+ public void onSuccess(SimpleFooProxy response) {
+ assertNotNull(response.getFooField());
+ assertSame(response.getFooField(),
+ response.getSelfOneToManyField().get(0));
+ finishTestAndReset();
+ }
+ });
+ }
+
+ /**
* Test that we can commit child objects.
*/
public void testCascadingCommit() {
@@ -222,11 +344,6 @@
});
}
- public void testChangedNothing() {
- SimpleFooRequest context = simpleFooRequest();
- assertFalse(context.isChanged());
- }
-
public void testChangedCreate() {
SimpleFooRequest context = simpleFooRequest();
@@ -277,6 +394,11 @@
});
}
+ public void testChangedNothing() {
+ SimpleFooRequest context = simpleFooRequest();
+ assertFalse(context.isChanged());
+ }
+
public void testClassToken() {
String token = req.getHistoryToken(SimpleFooProxy.class);
assertEquals(SimpleFooProxy.class, req.getProxyClass(token));
@@ -285,6 +407,21 @@
assertEquals(SimpleFooProxy.class, foo.stableId().getProxyClass());
}
+ public void testCollectionSubProperties() {
+ delayTestFinish(DELAY_TEST_FINISH);
+ simpleFooRequest().getSimpleFooWithSubPropertyCollection().with(
+ "selfOneToManyField", "selfOneToManyField.fooField").fire(
+ new Receiver<SimpleFooProxy>() {
+ @Override
+ public void onSuccess(SimpleFooProxy response) {
+ assertEquals(
+ "I'm here",
+ response.getSelfOneToManyField().get(0).getFooField().getUserName());
+ finishTestAndReset();
+ }
+ });
+ }
+
public void testDummyCreate() {
delayTestFinish(DELAY_TEST_FINISH);
@@ -361,48 +498,6 @@
});
}
- public void disabled_testEchoSimpleFutures() {
- // tests if futureIds can be echoed back.
- delayTestFinish(DELAY_TEST_FINISH);
- final SimpleFooEventHandler<SimpleFooProxy> handler = new SimpleFooEventHandler<SimpleFooProxy>();
- EntityProxyChange.registerForProxyType(req.getEventBus(),
- SimpleFooProxy.class, handler);
- SimpleFooRequest context = req.simpleFooRequest();
- final SimpleFooProxy simpleFoo = context.create(SimpleFooProxy.class);
- context.echo(simpleFoo).fire(new Receiver<SimpleFooProxy>() {
- @Override
- public void onSuccess(SimpleFooProxy response) {
- assertEquals(0, handler.totalEventCount);
- checkStableIdEquals(simpleFoo, response);
- finishTestAndReset();
- }
- });
- }
-
- public void disabled_testEchoComplexFutures() {
- // relate futures on the server. Check if the relationship is still present
- // on the client.
- delayTestFinish(DELAY_TEST_FINISH);
- final SimpleFooEventHandler<SimpleFooProxy> handler = new SimpleFooEventHandler<SimpleFooProxy>();
- EntityProxyChange.registerForProxyType(req.getEventBus(),
- SimpleFooProxy.class, handler);
- SimpleFooRequest context = req.simpleFooRequest();
- final SimpleFooProxy simpleFoo = context.create(SimpleFooProxy.class);
- final SimpleBarProxy simpleBar = context.create(SimpleBarProxy.class);
- context.echoComplex(simpleFoo, simpleBar).fire(
- new Receiver<SimpleFooProxy>() {
- @Override
- public void onSuccess(SimpleFooProxy response) {
- assertEquals(0, handler.totalEventCount);
- checkStableIdEquals(simpleFoo, response);
- SimpleBarProxy responseBar = response.getBarField();
- assertNotNull(responseBar);
- checkStableIdEquals(simpleBar, responseBar);
- finishTestAndReset();
- }
- });
- }
-
/**
* Tests behaviors relating to editing an object with one context and then
* using with another.
@@ -503,6 +598,67 @@
});
}
+ public void testFindFindEdit() {
+ delayTestFinish(5000);
+
+ final SimpleFooEventHandler<SimpleFooProxy> handler = new SimpleFooEventHandler<SimpleFooProxy>();
+ EntityProxyChange.registerForProxyType(req.getEventBus(),
+ SimpleFooProxy.class, handler);
+
+ req.simpleFooRequest().findSimpleFooById(999L).fire(
+ new Receiver<SimpleFooProxy>() {
+
+ @Override
+ public void onSuccess(SimpleFooProxy newFoo) {
+ assertEquals(1, handler.updateEventCount);
+ assertEquals(1, handler.totalEventCount);
+
+ req.simpleFooRequest().findSimpleFooById(999L).fire(
+ new Receiver<SimpleFooProxy>() {
+
+ @Override
+ public void onSuccess(SimpleFooProxy newFoo) {
+ // no events are fired second time.
+ assertEquals(1, handler.updateEventCount);
+ assertEquals(1, handler.totalEventCount);
+ SimpleFooRequest context = req.simpleFooRequest();
+ final Request<Void> mutateRequest = context.persist().using(
+ newFoo);
+ newFoo = context.edit(newFoo);
+ newFoo.setUserName("Ray");
+ mutateRequest.fire(new Receiver<Void>() {
+ @Override
+ public void onSuccess(Void response) {
+ // events fired on updates.
+ assertEquals(2, handler.updateEventCount);
+ assertEquals(2, handler.totalEventCount);
+
+ finishTestAndReset();
+ }
+ });
+ }
+ });
+ }
+ });
+ }
+
+ public void testForwardReferenceDecode() {
+ delayTestFinish(DELAY_TEST_FINISH);
+ simpleFooRequest().getTripletReference().with(
+ "selfOneToManyField.selfOneToManyField.fooField").fire(
+ new Receiver<SimpleFooProxy>() {
+ public void onSuccess(SimpleFooProxy response) {
+ assertNotNull(response.getSelfOneToManyField().get(0));
+ assertNotNull(response.getSelfOneToManyField().get(0).getSelfOneToManyField());
+ assertNotNull(response.getSelfOneToManyField().get(0).getSelfOneToManyField().get(
+ 0));
+ assertNotNull(response.getSelfOneToManyField().get(0).getSelfOneToManyField().get(
+ 0).getFooField());
+ finishTestAndReset();
+ }
+ });
+ }
+
public void testGetEventBus() {
assertEquals(eventBus, req.getEventBus());
}
@@ -582,6 +738,87 @@
});
}
+ /*
+ * tests that (a) any method can have a side effect that is handled correctly.
+ * (b) instance methods are handled correctly and (c) a request cannot be
+ * reused after a successful response is received. (Yet?)
+ */
+ public void testMethodWithSideEffects() {
+ delayTestFinish(DELAY_TEST_FINISH);
+
+ final SimpleFooEventHandler<SimpleFooProxy> handler = new SimpleFooEventHandler<SimpleFooProxy>();
+ EntityProxyChange.registerForProxyType(req.getEventBus(),
+ SimpleFooProxy.class, handler);
+
+ simpleFooRequest().findSimpleFooById(999L).fire(
+ new Receiver<SimpleFooProxy>() {
+
+ @Override
+ public void onSuccess(SimpleFooProxy newFoo) {
+ assertEquals(1, handler.updateEventCount);
+ assertEquals(1, handler.totalEventCount);
+ SimpleFooRequest context = simpleFooRequest();
+ final Request<Long> mutateRequest = context.countSimpleFooWithUserNameSideEffect().using(
+ newFoo);
+ newFoo = context.edit(newFoo);
+ newFoo.setUserName("Ray");
+ mutateRequest.fire(new Receiver<Long>() {
+ @Override
+ public void onSuccess(Long response) {
+ assertCannotFire(mutateRequest);
+ assertEquals(new Long(2L), response);
+ assertEquals(2, handler.updateEventCount);
+ assertEquals(2, handler.totalEventCount);
+
+ // confirm that the instance method did have the desired
+ // sideEffect.
+ simpleFooRequest().findSimpleFooById(999L).fire(
+ new Receiver<SimpleFooProxy>() {
+ @Override
+ public void onSuccess(SimpleFooProxy finalFoo) {
+ assertEquals("Ray", finalFoo.getUserName());
+ assertEquals(2, handler.updateEventCount);
+ assertEquals(2, handler.totalEventCount);
+ finishTestAndReset();
+ }
+ });
+ }
+
+ });
+
+ try {
+ newFoo.setUserName("Barney");
+ fail();
+ } catch (IllegalStateException e) {
+ /* pass, cannot change a request that is in flight */
+ }
+ }
+ });
+ }
+
+ public void testMultipleEdits() {
+ RequestContext c1 = req.simpleFooRequest();
+ SimpleFooProxy proxy = c1.create(SimpleFooProxy.class);
+ // Re-editing is idempotent
+ assertSame(proxy, c1.edit(c1.edit(proxy)));
+
+ // Should not allow "crossing the steams"
+ RequestContext c2 = req.simpleFooRequest();
+ try {
+ c2.edit(proxy);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ /**
+ * Ensures that a service method can respond with a null value.
+ */
+ public void testNullEntityProxyResult() {
+ delayTestFinish(DELAY_TEST_FINISH);
+ simpleFooRequest().returnNullSimpleFoo().fire(new NullReceiver());
+ }
+
/**
* Test that a null value can be sent in a request.
*/
@@ -597,6 +834,14 @@
}
/**
+ * Ensures that a service method can respond with a null value.
+ */
+ public void testNullListResult() {
+ delayTestFinish(DELAY_TEST_FINISH);
+ simpleFooRequest().returnNullList().fire(new NullReceiver());
+ }
+
+ /**
* Test that a null value can be sent in a request.
*/
public void testNullSimpleFooRequest() {
@@ -649,6 +894,14 @@
}
/**
+ * Ensures that a service method can respond with a null value.
+ */
+ public void testNullStringResult() {
+ delayTestFinish(DELAY_TEST_FINISH);
+ simpleFooRequest().returnNullString().fire(new NullReceiver());
+ }
+
+ /**
* Test that a null value can be sent within a list of entities.
*/
public void testNullValueInEntityListRequest() {
@@ -679,7 +932,7 @@
*/
public void testNullValueInIntegerListRequest() {
delayTestFinish(DELAY_TEST_FINISH);
- List<Integer> list = Arrays.asList(new Integer[] {1, 2, null});
+ List<Integer> list = Arrays.asList(new Integer[]{1, 2, null});
final Request<Void> fooReq = req.simpleFooRequest().receiveNullValueInIntegerList(
list);
fooReq.fire(new Receiver<Void>() {
@@ -695,7 +948,7 @@
*/
public void testNullValueInStringListRequest() {
delayTestFinish(DELAY_TEST_FINISH);
- List<String> list = Arrays.asList(new String[] {"nonnull", "null", null});
+ List<String> list = Arrays.asList(new String[]{"nonnull", "null", null});
final Request<Void> fooReq = req.simpleFooRequest().receiveNullValueInStringList(
list);
fooReq.fire(new Receiver<Void>() {
@@ -706,164 +959,6 @@
});
}
- /**
- * Ensures that a service method can respond with a null value.
- */
- public void testNullListResult() {
- delayTestFinish(DELAY_TEST_FINISH);
- simpleFooRequest().returnNullList().fire(new NullReceiver());
- }
-
- public void testMultipleEdits() {
- RequestContext c1 = req.simpleFooRequest();
- SimpleFooProxy proxy = c1.create(SimpleFooProxy.class);
- // Re-editing is idempotent
- assertSame(proxy, c1.edit(c1.edit(proxy)));
-
- // Should not allow "crossing the steams"
- RequestContext c2 = req.simpleFooRequest();
- try {
- c2.edit(proxy);
- fail();
- } catch (IllegalArgumentException expected) {
- }
- }
-
- /**
- * Ensures that a service method can respond with a null value.
- */
- public void testNullEntityProxyResult() {
- delayTestFinish(DELAY_TEST_FINISH);
- simpleFooRequest().returnNullSimpleFoo().fire(new NullReceiver());
- }
-
- /**
- * Ensures that a service method can respond with a null value.
- */
- public void testNullStringResult() {
- delayTestFinish(DELAY_TEST_FINISH);
- simpleFooRequest().returnNullString().fire(new NullReceiver());
- }
-
- /*
- * tests that (a) any method can have a side effect that is handled correctly.
- * (b) instance methods are handled correctly and (c) a request cannot be
- * reused after a successful response is received. (Yet?)
- */
- public void testMethodWithSideEffects() {
- delayTestFinish(DELAY_TEST_FINISH);
-
- final SimpleFooEventHandler<SimpleFooProxy> handler = new SimpleFooEventHandler<SimpleFooProxy>();
- EntityProxyChange.registerForProxyType(req.getEventBus(),
- SimpleFooProxy.class, handler);
-
- simpleFooRequest().findSimpleFooById(999L).fire(
- new Receiver<SimpleFooProxy>() {
-
- @Override
- public void onSuccess(SimpleFooProxy newFoo) {
- assertEquals(1, handler.updateEventCount);
- assertEquals(1, handler.totalEventCount);
- SimpleFooRequest context = simpleFooRequest();
- final Request<Long> mutateRequest = context.countSimpleFooWithUserNameSideEffect().using(
- newFoo);
- newFoo = context.edit(newFoo);
- newFoo.setUserName("Ray");
- mutateRequest.fire(new Receiver<Long>() {
- @Override
- public void onSuccess(Long response) {
- assertCannotFire(mutateRequest);
- assertEquals(new Long(2L), response);
- assertEquals(2, handler.updateEventCount);
- assertEquals(2, handler.totalEventCount);
-
- // confirm that the instance method did have the desired
- // sideEffect.
- simpleFooRequest().findSimpleFooById(999L).fire(
- new Receiver<SimpleFooProxy>() {
- @Override
- public void onSuccess(SimpleFooProxy finalFoo) {
- assertEquals("Ray", finalFoo.getUserName());
- assertEquals(3, handler.updateEventCount);
- assertEquals(3, handler.totalEventCount);
- finishTestAndReset();
- }
- });
- }
-
- });
-
- try {
- newFoo.setUserName("Barney");
- fail();
- } catch (IllegalStateException e) {
- /* pass, cannot change a request that is in flight */
- }
- }
- });
- }
-
- /**
- * Test that removing a parent entity and implicitly removing the child sends
- * an event to the client that the child was removed.
- *
- * TODO(rjrjr): Should cascading deletes be detected?
- */
- public void disableTestMethodWithSideEffectDeleteChild() {
- delayTestFinish(DELAY_TEST_FINISH);
-
- // Persist bar.
- SimpleBarRequest context = req.simpleBarRequest();
- final SimpleBarProxy bar = context.create(SimpleBarProxy.class);
- context.persistAndReturnSelf().using(bar).fire(
- new Receiver<SimpleBarProxy>() {
- @Override
- public void onSuccess(SimpleBarProxy persistentBar) {
- // Persist foo with bar as a child.
- SimpleFooRequest context = req.simpleFooRequest();
- SimpleFooProxy foo = context.create(SimpleFooProxy.class);
- final Request<SimpleFooProxy> persistRequest = context.persistAndReturnSelf().using(
- foo);
- foo = context.edit(foo);
- foo.setUserName("John");
- foo.setBarField(bar);
- persistRequest.fire(new Receiver<SimpleFooProxy>() {
- @Override
- public void onSuccess(SimpleFooProxy persistentFoo) {
- // Handle changes to SimpleFooProxy.
- final SimpleFooEventHandler<SimpleFooProxy> fooHandler = new SimpleFooEventHandler<SimpleFooProxy>();
- EntityProxyChange.registerForProxyType(req.getEventBus(),
- SimpleFooProxy.class, fooHandler);
-
- // Handle changes to SimpleBarProxy.
- final SimpleFooEventHandler<SimpleBarProxy> barHandler = new SimpleFooEventHandler<SimpleBarProxy>();
- EntityProxyChange.registerForProxyType(req.getEventBus(),
- SimpleBarProxy.class, barHandler);
-
- // Delete bar.
- SimpleFooRequest context = req.simpleFooRequest();
- final Request<Void> deleteRequest = context.deleteBar().using(
- persistentFoo);
- SimpleFooProxy editable = context.edit(persistentFoo);
- editable.setBarField(bar);
- deleteRequest.fire(new Receiver<Void>() {
- @Override
- public void onSuccess(Void response) {
- assertEquals(1, fooHandler.updateEventCount); // set bar to
- // null
- assertEquals(1, fooHandler.totalEventCount);
-
- assertEquals(1, barHandler.deleteEventCount); // deleted bar
- assertEquals(1, barHandler.totalEventCount);
- finishTestAndReset();
- }
- });
- }
- });
- }
- });
- }
-
public void testPersistAllValueTypes() {
delayTestFinish(DELAY_TEST_FINISH);
@@ -871,8 +966,8 @@
SimpleFooProxy f = r.create(SimpleFooProxy.class);
f.setUserName("user name");
- f.setByteField((byte)100);
- f.setShortField((short)12345);
+ f.setByteField((byte) 100);
+ f.setShortField((short) 12345);
f.setFloatField(1234.56f);
f.setDoubleField(1.2345);
f.setLongField(1234L);
@@ -884,8 +979,8 @@
@Override
public void onSuccess(SimpleFooProxy f) {
assertEquals("user name", f.getUserName());
- assertEquals(Byte.valueOf((byte)100), f.getByteField());
- assertEquals(Short.valueOf((short)12345), f.getShortField());
+ assertEquals(Byte.valueOf((byte) 100), f.getByteField());
+ assertEquals(Short.valueOf((short) 12345), f.getShortField());
assertEquals(Float.valueOf(1234.56f), f.getFloatField());
assertEquals(Double.valueOf(1.2345), f.getDoubleField());
assertEquals(Long.valueOf(1234L), f.getLongField());
@@ -922,35 +1017,35 @@
fooProxy.setBarField(barProxy);
fooProxy.setUserName("Hello");
fooProxy.setByteField((byte) 55);
- context.persistAndReturnSelf().using(fooProxy).fire(
- new Receiver<SimpleFooProxy>() {
- @Override
- public void onSuccess(SimpleFooProxy received) {
- // Check that Foo points to Bar
- assertNotNull(received.getBarField());
- assertEquals(barProxy.stableId(),
- received.getBarField().stableId());
- assertEquals("Hello", received.getUserName());
- assertTrue(55 == received.getByteField());
+ context.persistAndReturnSelf().using(fooProxy).with(
+ "barField").fire(new Receiver<SimpleFooProxy>() {
+ @Override
+ public void onSuccess(SimpleFooProxy received) {
+ // Check that Foo points to Bar
+ assertNotNull(received.getBarField());
+ assertEquals(barProxy.stableId(),
+ received.getBarField().stableId());
+ assertEquals("Hello", received.getUserName());
+ assertTrue(55 == received.getByteField());
- // Unset the association
- SimpleFooRequest context = simpleFooRequest();
- received = context.edit(received);
- received.setBarField(null);
- received.setUserName(null);
- received.setByteField(null);
- context.persistAndReturnSelf().using(received).fire(
- new Receiver<SimpleFooProxy>() {
- @Override
- public void onSuccess(SimpleFooProxy response) {
- assertNull(response.getBarField());
- assertNull(response.getUserName());
- assertNull(response.getByteField());
- finishTestAndReset();
- }
- });
- }
- });
+ // Unset the association
+ SimpleFooRequest context = simpleFooRequest();
+ received = context.edit(received);
+ received.setBarField(null);
+ received.setUserName(null);
+ received.setByteField(null);
+ context.persistAndReturnSelf().using(received).fire(
+ new Receiver<SimpleFooProxy>() {
+ @Override
+ public void onSuccess(SimpleFooProxy response) {
+ assertNull(response.getBarField());
+ assertNull(response.getUserName());
+ assertNull(response.getByteField());
+ finishTestAndReset();
+ }
+ });
+ }
+ });
}
});
}
@@ -1010,6 +1105,30 @@
});
}
+ /**
+ * Ensure that a relationship can be set up between two newly-created objects.
+ */
+ public void testPersistFutureToFuture() {
+ delayTestFinish(DELAY_TEST_FINISH);
+ SimpleFooRequest context = simpleFooRequest();
+ SimpleFooProxy newFoo = context.create(SimpleFooProxy.class);
+ final SimpleBarProxy newBar = context.create(SimpleBarProxy.class);
+
+ Request<SimpleFooProxy> fooReq = context.persistAndReturnSelf().using(
+ newFoo).with("barField");
+ newFoo = context.edit(newFoo);
+ newFoo.setBarField(newBar);
+
+ fooReq.fire(new Receiver<SimpleFooProxy>() {
+ @Override
+ public void onSuccess(SimpleFooProxy response) {
+ assertNotNull(response.getBarField());
+ assertEquals(newBar.stableId(), response.getBarField().stableId());
+ finishTestAndReset();
+ }
+ });
+ }
+
/*
* Find Entity2 Create Entity, Persist Entity Relate Entity2 to Entity Persist
* Entity
@@ -1048,30 +1167,6 @@
});
}
- /**
- * Ensure that a relationship can be set up between two newly-created objects.
- */
- public void testPersistFutureToFuture() {
- delayTestFinish(DELAY_TEST_FINISH);
- SimpleFooRequest context = simpleFooRequest();
- SimpleFooProxy newFoo = context.create(SimpleFooProxy.class);
- final SimpleBarProxy newBar = context.create(SimpleBarProxy.class);
-
- Request<SimpleFooProxy> fooReq = context.persistAndReturnSelf().using(
- newFoo).with("barField");
- newFoo = context.edit(newFoo);
- newFoo.setBarField(newBar);
-
- fooReq.fire(new Receiver<SimpleFooProxy>() {
- @Override
- public void onSuccess(SimpleFooProxy response) {
- assertNotNull(response.getBarField());
- assertEquals(newBar.stableId(), response.getBarField().stableId());
- finishTestAndReset();
- }
- });
- }
-
/*
* Create Entity, Persist Entity Create Entity2, Perist Entity2 relate Entity2
* to Entity Persist
@@ -1933,14 +2028,14 @@
});
}
- protected SimpleFooRequest simpleFooRequest() {
- return req.simpleFooRequest();
- }
-
protected SimpleBarRequest simpleBarRequest() {
return req.simpleBarRequest();
}
+ protected SimpleFooRequest simpleFooRequest() {
+ return req.simpleFooRequest();
+ }
+
private void assertCannotFire(final Request<Long> mutateRequest) {
try {
mutateRequest.fire(new Receiver<Long>() {
diff --git a/user/test/com/google/gwt/requestfactory/client/EditorTest.java b/user/test/com/google/gwt/requestfactory/client/ui/EditorTest.java
similarity index 97%
rename from user/test/com/google/gwt/requestfactory/client/EditorTest.java
rename to user/test/com/google/gwt/requestfactory/client/ui/EditorTest.java
index 2db02d6..6b1cc48 100644
--- a/user/test/com/google/gwt/requestfactory/client/EditorTest.java
+++ b/user/test/com/google/gwt/requestfactory/client/ui/EditorTest.java
@@ -13,7 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.requestfactory.client;
+package com.google.gwt.requestfactory.client.ui;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
@@ -24,6 +24,8 @@
import com.google.gwt.editor.client.HasEditorDelegate;
import com.google.gwt.editor.client.HasEditorErrors;
import com.google.gwt.editor.client.adapters.SimpleEditor;
+import com.google.gwt.requestfactory.client.RequestFactoryEditorDriver;
+import com.google.gwt.requestfactory.client.RequestFactoryTestBase;
import com.google.gwt.requestfactory.shared.Receiver;
import com.google.gwt.requestfactory.shared.Request;
import com.google.gwt.requestfactory.shared.SimpleBarProxy;
diff --git a/user/test/com/google/gwt/requestfactory/rebind/model/RequestFactoryModelTest.java b/user/test/com/google/gwt/requestfactory/rebind/model/RequestFactoryModelTest.java
new file mode 100644
index 0000000..42a821b
--- /dev/null
+++ b/user/test/com/google/gwt/requestfactory/rebind/model/RequestFactoryModelTest.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright 2010 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.requestfactory.rebind.model;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.dev.javac.CompilationState;
+import com.google.gwt.dev.javac.CompilationStateBuilder;
+import com.google.gwt.dev.javac.impl.JavaResourceBase;
+import com.google.gwt.dev.javac.impl.MockJavaResource;
+import com.google.gwt.dev.resource.Resource;
+import com.google.gwt.dev.util.UnitTestTreeLogger;
+import com.google.gwt.dev.util.Util;
+import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
+import com.google.gwt.requestfactory.server.TestContextImpl;
+import com.google.gwt.requestfactory.server.TestContextNoIdImpl;
+import com.google.gwt.requestfactory.server.TestContextNoVersionImpl;
+import com.google.gwt.requestfactory.shared.EntityProxy;
+import com.google.gwt.requestfactory.shared.InstanceRequest;
+import com.google.gwt.requestfactory.shared.ProxyFor;
+import com.google.gwt.requestfactory.shared.Receiver;
+import com.google.gwt.requestfactory.shared.Request;
+import com.google.gwt.requestfactory.shared.RequestContext;
+import com.google.gwt.requestfactory.shared.RequestFactory;
+import com.google.gwt.requestfactory.shared.Service;
+import com.google.gwt.requestfactory.shared.impl.Property;
+
+import junit.framework.TestCase;
+
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+
+/**
+ * Test case for {@link com.google.gwt.requestfactory.rebind.model.RequestFactoryModel}
+ * that uses mock CompilationStates.
+ */
+public class RequestFactoryModelTest extends TestCase {
+
+ /**
+ * Constructs an empty interface representation of a type.
+ */
+ private static class EmptyMockJavaResource extends MockJavaResource {
+
+ private final StringBuilder code = new StringBuilder();
+
+ public EmptyMockJavaResource(Class<?> clazz) {
+ super(clazz.getName());
+
+ code.append("package ").append(clazz.getPackage().getName())
+ .append(";\n");
+ code.append("public interface ").append(clazz.getSimpleName());
+
+ int numParams = clazz.getTypeParameters().length;
+ if (numParams != 0) {
+ code.append("<");
+ for (int i = 0; i < numParams; i++) {
+ if (i != 0) {
+ code.append(",");
+ }
+ code.append("T").append(i);
+ }
+ code.append(">");
+ }
+
+ code.append("{}\n");
+ }
+
+ @Override
+ protected CharSequence getContent() {
+ return code;
+ }
+ }
+
+ /**
+ * Loads the actual source of a type. This should be used only for types
+ * directly tested by this test. Note that use of this class requires your
+ * source files to be on your classpath.
+ */
+ private static class RealJavaResource extends MockJavaResource {
+
+ public RealJavaResource(Class<?> clazz) {
+ super(clazz.getName());
+ }
+
+ @Override
+ protected CharSequence getContent() {
+ String resourceName = getTypeName().replace('.', '/') + ".java";
+ InputStream stream = Thread.currentThread().getContextClassLoader()
+ .getResourceAsStream(resourceName);
+ return Util.readStreamAsString(stream);
+ }
+ }
+
+ private static TreeLogger createCompileLogger() {
+ PrintWriterTreeLogger logger = new PrintWriterTreeLogger(
+ new PrintWriter(System.err, true));
+ logger.setMaxDetail(TreeLogger.ERROR);
+ return logger;
+ }
+
+ private TreeLogger logger;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ logger = createCompileLogger();
+ }
+
+ public void testBadCollectionType() {
+ testModelWithMethodDecl("Request<SortedSet<Integer>> badReturnType();",
+ "Requests that return collections may be declared with java.util.List or java.util.Set only");
+ }
+
+ public void testBadCollectionTypeNotParameterized() {
+ testModelWithMethodDecl("Request<SortedSet> badReturnType();",
+ "Requests that return collections of List or Set must be parameterized");
+ }
+
+ public void testBadReturnType() {
+ testModelWithMethodDecl("Request<Iterable> badReturnType();",
+ "Invalid Request parameterization java.lang.Iterable");
+ }
+
+ public void testMismatchedArityInstance() {
+ testModelWithMethodDecl(
+ "InstanceRequest<TestProxy, String> mismatchedArityInstance(TestProxy p, int x);",
+ "Parameter 0 of method TestContext.mismatchedArityInstance does not match method com.google.gwt.requestfactory.server.TestContextImpl.mismatchedArityInstance");
+ }
+
+ public void testMismatchedArityStatic() {
+ testModelWithMethodDecl("Request<String> mismatchedArityStatic(int x);",
+ "Method TestContext.mismatchedArityStatic parameters do not match same method on com.google.gwt.requestfactory.server.TestContextImpl");
+ }
+
+ public void testMismatchedModifierNonStatic() {
+ testModelWithMethodDecl(
+ "InstanceRequest<TestProxy, String> mismatchedNonStatic();",
+ "Method TestContext.mismatchedNonStatic is an instance method, while the corresponding method on com.google.gwt.requestfactory.server.TestContextImpl is static");
+ }
+
+ public void testMismatchedModifierStatic() {
+ testModelWithMethodDecl("Request<String> mismatchedStatic();",
+ "Method TestContext.mismatchedStatic is a static method, while the corresponding method on com.google.gwt.requestfactory.server.TestContextImpl is not");
+ }
+
+ public void testMismatchedParamType() {
+ testModelWithMethodDecl("Request<String> mismatchedParamType(Integer x);",
+ "Parameter 0 of method TestContext.mismatchedParamType does not match method com.google.gwt.requestfactory.server.TestContextImpl.mismatchedParamType");
+ }
+
+ public void testMismatchedReturnType() {
+ testModelWithMethodDecl("Request<String> mismatchedReturnType();",
+ "Return type of method TestContext.mismatchedReturnType does not match method com.google.gwt.requestfactory.server.TestContextImpl.mismatchedReturnType");
+ }
+
+ public void testMissingId() {
+ testModelWithMethodDeclArgs("Request<TestProxy> okMethodProxy();",
+ TestContextNoIdImpl.class.getName(),
+ TestContextNoIdImpl.class.getName(),
+ "The class com.google.gwt.requestfactory.server.TestContextNoIdImpl is missing method getId()");
+ }
+
+ public void testMissingMethod() {
+ testModelWithMethodDecl("Request<String> missingMethod();",
+ "Method t.TestContext.missingMethod has no corresponding public method on"
+ + " com.google.gwt.requestfactory.server.TestContextImpl");
+ }
+
+ public void testMissingProxyFor() {
+ testModelWithMethodDeclArgs("Request<TestProxy> okMethodProxy();",
+ TestContextImpl.class.getName(), null,
+ "The t.TestProxy type does not have a @ProxyFor annotation");
+ }
+
+ public void testMissingService() {
+ testModelWithMethodDeclArgs("Request<String> okMethod();", null,
+ TestContextImpl.class.getName(),
+ "RequestContext subtype t.TestContext is missing a @Service annotation");
+ }
+
+ public void testMissingVersion() {
+ testModelWithMethodDeclArgs("Request<TestProxy> okMethodProxy();",
+ TestContextNoVersionImpl.class.getName(),
+ TestContextNoVersionImpl.class.getName(),
+ "The class com.google.gwt.requestfactory.server.TestContextNoVersionImpl is missing method getVersion()");
+ }
+
+ public void testModelWithMethodDecl(final String clientMethodDecls,
+ String... expected) {
+ testModelWithMethodDeclArgs(clientMethodDecls,
+ TestContextImpl.class.getName(), TestContextImpl.class.getName(),
+ expected);
+ }
+
+ public void testModelWithMethodDeclArgs(final String clientMethodDecls,
+ final String serviceClass, String proxyClass, String... expected) {
+ Set<Resource> javaResources = getJavaResources(proxyClass);
+ javaResources.add(new MockJavaResource("t.TestRequestFactory") {
+ @Override
+ protected CharSequence getContent() {
+ StringBuilder code = new StringBuilder();
+ code.append("package t;\n");
+ code.append("import " + RequestFactory.class.getName() + ";\n");
+ code.append("interface TestRequestFactory extends RequestFactory {\n");
+ code.append("TestContext testContext();");
+ code.append("}");
+ return code;
+ }
+ });
+ javaResources.add(new MockJavaResource("t.TestContext") {
+ @Override
+ protected CharSequence getContent() {
+ StringBuilder code = new StringBuilder();
+ code.append("package t;\n");
+ code.append("import " + Request.class.getName() + ";\n");
+ code.append("import " + InstanceRequest.class.getName() + ";\n");
+
+ code.append("import " + RequestContext.class.getName() + ";\n");
+ code.append("import " + SortedSet.class.getName() + ";\n");
+ code.append("import " + List.class.getName() + ";\n");
+ code.append("import " + Set.class.getName() + ";\n");
+ code.append("import " + Service.class.getName() + ";\n");
+ code.append("import " + TestContextImpl.class.getName() + ";\n");
+
+ if (serviceClass != null) {
+ code.append("@Service(" + serviceClass + ".class)");
+ }
+ code.append("interface TestContext extends RequestContext {\n");
+ code.append(clientMethodDecls);
+ code.append("}");
+ return code;
+ }
+ });
+
+ CompilationState state = CompilationStateBuilder
+ .buildFrom(logger, javaResources);
+
+ UnitTestTreeLogger.Builder builder = new UnitTestTreeLogger.Builder();
+ builder.setLowestLogLevel(TreeLogger.ERROR);
+ for (String expectedMsg : expected) {
+ builder.expectError(expectedMsg, null);
+ }
+ builder.expectError(RequestFactoryModel.poisonedMessage(), null);
+ UnitTestTreeLogger testLogger = builder.createLogger();
+ try {
+ new RequestFactoryModel(testLogger,
+ state.getTypeOracle().findType("t.TestRequestFactory"));
+ fail("Should have complained");
+ } catch (UnableToCompleteException e) {
+ }
+ testLogger.assertCorrectLogEntries();
+ }
+
+ public void testOverloadedMethod() {
+ testModelWithMethodDecl("Request<String> overloadedMethod();",
+ "Method t.TestContext.overloadedMethod is overloaded on com.google.gwt.requestfactory.server.TestContextImpl");
+ }
+
+ private Set<Resource> getJavaResources(final String proxyClass) {
+ MockJavaResource[] javaFiles = {new MockJavaResource("t.AddressProxy") {
+ @Override
+ protected CharSequence getContent() {
+ StringBuilder code = new StringBuilder();
+ code.append("package t;\n");
+ code.append("import " + ProxyFor.class.getName() + ";\n");
+ code.append("import " + EntityProxy.class.getName() + ";\n");
+ if (proxyClass != null) {
+ code.append("@ProxyFor(" + proxyClass + ".class)");
+ }
+ code.append("interface TestProxy extends EntityProxy {\n");
+ code.append("}");
+ return code;
+ }
+ }, new MockJavaResource("java.util.List") {
+ // Tests a Driver interface that extends more than RFED
+ @Override
+ protected CharSequence getContent() {
+ StringBuilder code = new StringBuilder();
+ code.append("package java.util;\n");
+ code.append("public interface List<T> extends Collection<T> {\n");
+ code.append("}");
+ return code;
+ }
+ }, new MockJavaResource("java.util.Set") {
+ // Tests a Driver interface that extends more than RFED
+ @Override
+ protected CharSequence getContent() {
+ StringBuilder code = new StringBuilder();
+ code.append("package java.util;\n");
+ code.append("public interface Set<T> extends Collection<T> {\n");
+ code.append("}");
+ return code;
+ }
+ }, new MockJavaResource("java.util.SortedSet") {
+ // Tests a Driver interface that extends more than RFED
+ @Override
+ protected CharSequence getContent() {
+ StringBuilder code = new StringBuilder();
+ code.append("package java.util;\n");
+ code.append("public interface SortedSet<T> extends Set<T> {\n");
+ code.append("}");
+ return code;
+ }
+ }};
+
+ Set<Resource> toReturn = new HashSet<Resource>(Arrays.asList(javaFiles));
+
+ toReturn.addAll(Arrays.asList(
+ new Resource[]{new EmptyMockJavaResource(Iterable.class),
+ new EmptyMockJavaResource(Property.class),
+ new EmptyMockJavaResource(EntityProxy.class),
+ new EmptyMockJavaResource(InstanceRequest.class),
+ new EmptyMockJavaResource(RequestFactory.class),
+ new EmptyMockJavaResource(Receiver.class),
+
+ new RealJavaResource(Request.class),
+ new RealJavaResource(Service.class),
+ new RealJavaResource(ProxyFor.class),
+ new EmptyMockJavaResource(RequestContext.class),}));
+ toReturn.addAll(Arrays.asList(JavaResourceBase.getStandardResources()));
+ return toReturn;
+ }
+}
diff --git a/user/test/com/google/gwt/requestfactory/server/JsonRequestProcessorTest.java b/user/test/com/google/gwt/requestfactory/server/JsonRequestProcessorTest.java
index 23a0f94..919f897 100644
--- a/user/test/com/google/gwt/requestfactory/server/JsonRequestProcessorTest.java
+++ b/user/test/com/google/gwt/requestfactory/server/JsonRequestProcessorTest.java
@@ -111,6 +111,7 @@
// nulls becomes JSON Null. Needed because JSONObject stringify treats 'null'
// as a reason to not emit the key in the stringified object
assertEquals(JSONObject.NULL, requestProcessor.encodePropertyValue(null));
+ assertEquals(new Double(1.0), requestProcessor.encodePropertyValue(new Integer(1)));
}
public void testEndToEnd() throws Exception {
@@ -134,8 +135,9 @@
JSONArray updateArray = result.getJSONObject("sideEffects").getJSONArray(
"UPDATE");
assertEquals(1, updateArray.length());
- assertEquals(1, updateArray.getJSONObject(0).length());
+ assertEquals(2, updateArray.getJSONObject(0).length());
assertTrue(updateArray.getJSONObject(0).has(Constants.ENCODED_ID_PROPERTY));
+ assertTrue(updateArray.getJSONObject(0).has(Constants.ENCODED_VERSION_PROPERTY));
assertFalse(updateArray.getJSONObject(0).has("violations"));
assertEquals(45, (int) fooResult.getIntId());
assertEquals("JSC", fooResult.getUserName());
@@ -146,26 +148,102 @@
assertEquals(false, (boolean) fooResult.getBoolField());
}
+ private String createNoChangeRequestAndGetServerVersion(JSONObject foo) throws Exception {
+ // change the value on the server behind the back
+ SimpleFoo fooResult = SimpleFoo.findSimpleFooById(999L);
+ fooResult.setUserName("JSC");
+ fooResult.setIntId(45);
+ String savedVersion = requestProcessor.encodePropertyValue(fooResult.getVersion() + 1).toString();
+ fooResult.setVersion(fooResult.getVersion() + 1);
+ fooResult.isChanged = false;
+
+ // modify fields and sync -- there should be no change on the server.
+ foo.put("intId", 45);
+ foo.put("userName", "JSC");
+ return savedVersion;
+ }
+
public void testEndToEndSmartDiff_NoChange() throws Exception {
com.google.gwt.requestfactory.server.SimpleFoo.reset();
// fetch object
JSONObject foo = fetchVerifyAndGetInitialObject();
- // change the value on the server behind the back
- SimpleFoo fooResult = SimpleFoo.findSimpleFooById(999L);
- fooResult.setUserName("JSC");
- fooResult.setIntId(45);
+ String savedVersion = createNoChangeRequestAndGetServerVersion(foo);
+ JSONObject result = getResultFromServer(foo);
- // modify fields and sync -- there should be no change on the server.
- foo.put("intId", 45);
- foo.put("userName", "JSC");
+ // check modified fields and no violations
+ assertTrue(result.getJSONObject("sideEffects").has("UPDATE"));
+ JSONArray updateArray = result.getJSONObject("sideEffects").getJSONArray(
+ "UPDATE");
+ // verify that the version number is unchanged.
+ assertEquals(1, updateArray.length());
+ assertEquals(2, updateArray.getJSONObject(0).length());
+ assertTrue(updateArray.getJSONObject(0).has(Constants.ENCODED_ID_PROPERTY));
+ assertTrue(updateArray.getJSONObject(0).has(
+ Constants.ENCODED_VERSION_PROPERTY));
+ assertEquals(savedVersion,
+ updateArray.getJSONObject(0).getString(
+ Constants.ENCODED_VERSION_PROPERTY));
+ // verify that the server values are unchanged.
+ SimpleFoo fooResult = SimpleFoo.findSimpleFooById(999L);
+ assertEquals(45, (int) fooResult.getIntId());
+ assertEquals("JSC", fooResult.getUserName());
+ assertEquals(savedVersion,
+ requestProcessor.encodePropertyValue(fooResult.getVersion()).toString());
+ }
+
+ /*
+ * This test differs from testEndToEndSmartDiff_NoChange in that the version
+ * numbers are not sent. As a result, the server does not send an UPDATE
+ * sideEffect in its response.
+ */
+ public void testEndToEndSmartDiff_NoChange_NoVersion() throws Exception {
+ com.google.gwt.requestfactory.server.SimpleFoo.reset();
+ // fetch object
+ JSONObject foo = fetchVerifyAndGetInitialObject();
+
+ String savedVersion = createNoChangeRequestAndGetServerVersion(foo);
+ // remove version number from the request.
+ foo.remove(Constants.ENCODED_VERSION_PROPERTY);
JSONObject result = getResultFromServer(foo);
// check modified fields and no violations
assertFalse(result.getJSONObject("sideEffects").has("UPDATE"));
- fooResult = SimpleFoo.findSimpleFooById(999L);
+
+ // verify that the server values are unchanged.
+ SimpleFoo fooResult = SimpleFoo.findSimpleFooById(999L);
assertEquals(45, (int) fooResult.getIntId());
assertEquals("JSC", fooResult.getUserName());
+ assertEquals(savedVersion,
+ requestProcessor.encodePropertyValue(fooResult.getVersion()).toString());
+ }
+
+ /*
+ * This test differs from testEndToEndSmartDiff_NoChange in that the property
+ * that is changed here does not cause a version increment. As a result, no
+ * UPDATE is sent back.
+ */
+ public void testEndToEndSmartDiff_NoVersionChange() throws Exception {
+ com.google.gwt.requestfactory.server.SimpleFoo.reset();
+ // fetch object
+ JSONObject foo = fetchVerifyAndGetInitialObject();
+ // change the value on the server behind the back
+ SimpleFoo fooResult = SimpleFoo.findSimpleFooById(999L);
+ fooResult.setLongField(45L);
+ String savedVersion = requestProcessor.encodePropertyValue(fooResult.getVersion()).toString();
+
+ // modify fields and sync -- there should be no change on the server.
+ foo.put("longField", 45L);
+ JSONObject result = getResultFromServer(foo);
+
+ // check modified fields and no violations
+ assertFalse(result.getJSONObject("sideEffects").has("UPDATE"));
+
+ // verify that the server values are unchanged.
+ fooResult = SimpleFoo.findSimpleFooById(999L);
+ assertEquals(45L, (long) fooResult.getLongField());
+ assertEquals(savedVersion,
+ requestProcessor.encodePropertyValue(fooResult.getVersion()).toString());
}
public void testEndToEndSmartDiff_SomeChangeWithNull() throws Exception {
diff --git a/user/test/com/google/gwt/requestfactory/server/SimpleBar.java b/user/test/com/google/gwt/requestfactory/server/SimpleBar.java
index fd47a98..80495e9 100644
--- a/user/test/com/google/gwt/requestfactory/server/SimpleBar.java
+++ b/user/test/com/google/gwt/requestfactory/server/SimpleBar.java
@@ -80,7 +80,7 @@
Map<String, SimpleBar> value = (Map<String, SimpleBar>) req.getSession().getAttribute(
SimpleBar.class.getCanonicalName());
if (value == null) {
- value = reset();
+ value = resetImpl();
}
return value;
}
@@ -95,7 +95,11 @@
return toReturn;
}
- public static synchronized Map<String, SimpleBar> reset() {
+ public static void reset() {
+ resetImpl();
+ }
+
+ public static synchronized Map<String, SimpleBar> resetImpl() {
Map<String, SimpleBar> instance = new HashMap<String, SimpleBar>();
// fixtures
SimpleBar s1 = new SimpleBar();
@@ -157,6 +161,7 @@
isNew = false;
get().put(getId(), this);
}
+ version++;
}
public SimpleBar persistAndReturnSelf() {
diff --git a/user/test/com/google/gwt/requestfactory/server/SimpleFoo.java b/user/test/com/google/gwt/requestfactory/server/SimpleFoo.java
index 6e2b989..bef8b4a 100644
--- a/user/test/com/google/gwt/requestfactory/server/SimpleFoo.java
+++ b/user/test/com/google/gwt/requestfactory/server/SimpleFoo.java
@@ -21,6 +21,7 @@
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@@ -59,6 +60,16 @@
return simpleFoo;
}
+ public static SimpleFoo fetchDoubleReference() {
+ SimpleFoo foo = new SimpleFoo();
+ SimpleFoo foo2 = new SimpleFoo();
+ foo.setFooField(foo2);
+ foo.setSelfOneToManyField(Arrays.asList(foo2));
+ foo.persist();
+ foo2.persist();
+ return foo;
+ }
+
public static List<SimpleFoo> findAll() {
return new ArrayList<SimpleFoo>(get().values());
}
@@ -86,7 +97,7 @@
Map<Long, SimpleFoo> value = (Map<Long, SimpleFoo>) req.getSession().getAttribute(
SimpleFoo.class.getCanonicalName());
if (value == null) {
- value = reset();
+ value = resetImpl();
}
return value;
}
@@ -108,6 +119,36 @@
return list;
}
+ public static SimpleFoo getSimpleFooWithSubPropertyCollection() {
+ SimpleFoo foo = new SimpleFoo();
+ SimpleFoo subFoo = new SimpleFoo();
+ SimpleFoo subSubFoo = new SimpleFoo();
+ subFoo.setFooField(subSubFoo);
+ subSubFoo.setUserName("I'm here");
+ subSubFoo.persist();
+ subFoo.persist();
+ foo.persist();
+ foo.setSelfOneToManyField(Arrays.asList(subFoo));
+ return foo;
+ }
+
+ public static SimpleFoo getTripletReference() {
+ SimpleFoo foo1 = new SimpleFoo();
+ SimpleFoo foo2 = new SimpleFoo();
+ SimpleFoo foo3 = new SimpleFoo();
+ ArrayList<SimpleFoo> foos = new ArrayList<SimpleFoo>();
+ foos.add(foo2);
+ ArrayList<SimpleFoo> subFoos = new ArrayList<SimpleFoo>();
+ subFoos.add(foo3);
+ foo1.setSelfOneToManyField(foos);
+ foo2.setSelfOneToManyField(subFoos);
+ foo3.setFooField(foo2);
+ foo1.persist();
+ foo2.persist();
+ foo3.persist();
+ return foo1;
+ }
+
public static Boolean processBooleanList(List<Boolean> values) {
return values.get(0);
}
@@ -191,7 +232,11 @@
}
}
- public static synchronized Map<Long, SimpleFoo> reset() {
+ public static void reset() {
+ resetImpl();
+ }
+
+ public static synchronized Map<Long, SimpleFoo> resetImpl() {
Map<Long, SimpleFoo> instance = new HashMap<Long, SimpleFoo>();
// fixtures
SimpleFoo s1 = new SimpleFoo();
@@ -275,6 +320,13 @@
private List<Integer> numberListField;
+ /*
+ * isChanged is just a quick-and-dirty way to get version-ing for now.
+ * Currently, only set by setUserName and setIntId. TODO for later: Use a
+ * cleaner solution to figure out when to increment version numbers.
+ */
+ boolean isChanged;
+
public SimpleFoo() {
intId = 42;
version = 1;
@@ -297,10 +349,12 @@
nullField = null;
barNullField = null;
pleaseCrash = 0;
+ isChanged = false;
}
public Long countSimpleFooWithUserNameSideEffect() {
findSimpleFoo(1L).setUserName(userName);
+ version++;
return countSimpleFoo();
}
@@ -449,6 +503,10 @@
isNew = false;
get().put(getId(), this);
}
+ if (isChanged) {
+ version++;
+ isChanged = false;
+ }
}
public SimpleFoo persistAndReturnSelf() {
@@ -547,7 +605,10 @@
}
public void setIntId(Integer id) {
- this.intId = id;
+ if (!this.intId.equals(id)) {
+ this.intId = id;
+ isChanged = true;
+ }
}
public void setLongField(Long longField) {
@@ -604,7 +665,10 @@
}
public void setUserName(String userName) {
- this.userName = userName;
+ if (!this.userName.equals(userName)) {
+ this.userName = userName;
+ isChanged = true;
+ }
}
public void setVersion(Integer version) {
diff --git a/user/test/com/google/gwt/requestfactory/server/SimpleFooString.java b/user/test/com/google/gwt/requestfactory/server/SimpleFooString.java
index 354b2b9..d4d3eb6 100644
--- a/user/test/com/google/gwt/requestfactory/server/SimpleFooString.java
+++ b/user/test/com/google/gwt/requestfactory/server/SimpleFooString.java
@@ -73,7 +73,7 @@
SimpleFooString value = (SimpleFooString) req.getSession().getAttribute(
SimpleFooString.class.getCanonicalName());
if (value == null) {
- value = reset();
+ value = resetImpl();
}
return value;
}
@@ -99,7 +99,11 @@
return get();
}
- public static synchronized SimpleFooString reset() {
+ public static void reset() {
+ resetImpl();
+ }
+
+ public static synchronized SimpleFooString resetImpl() {
SimpleFooString instance = new SimpleFooString();
HttpServletRequest req = RequestFactoryServlet.getThreadLocalRequest();
if (req == null) {
@@ -185,6 +189,7 @@
public Long countSimpleFooWithUserNameSideEffect() {
get().setUserName(userName);
+ version++;
return 1L;
}
@@ -322,6 +327,7 @@
public void persist() {
setId(nextId++ + "x");
+ version++;
}
public SimpleFooString persistAndReturnSelf() {
diff --git a/user/test/com/google/gwt/requestfactory/server/TestContextImpl.java b/user/test/com/google/gwt/requestfactory/server/TestContextImpl.java
new file mode 100644
index 0000000..f64dcee
--- /dev/null
+++ b/user/test/com/google/gwt/requestfactory/server/TestContextImpl.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2010 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.requestfactory.server;
+
+/**
+ * Bad service method declarations.
+ */
+public class TestContextImpl {
+
+ public static Class badReturnType() {
+ return null;
+ }
+
+ public static String mismatchedArityStatic(int x, int y, int z) {
+ return null;
+ }
+
+ public static String mismatchedParamType(String param) {
+ return null;
+ }
+
+ public static Integer mismatchedReturnType() {
+ return null;
+ }
+
+ public static String overloadedMethod() {
+ return null;
+ }
+
+ public static String overloadedMethod(String foo) {
+ return null;
+ }
+ public String getId() {
+ return null;
+ }
+
+ public String getVersion() {
+ return null;
+ }
+
+ public String mismatchedArityInstance(int x, int y) {
+ return null;
+ }
+
+ public String mismatchedStatic(String param) {
+ return null;
+ }
+
+ public static String okMethod() {
+ return null;
+ }
+
+ public static TestContextImpl okMethodProxy() {
+ return null;
+ }
+
+ public static String mismatchedNonStatic(String param) {
+ return null;
+ }
+}
+
diff --git a/user/test/com/google/gwt/app/place/testplaces/Place3.java b/user/test/com/google/gwt/requestfactory/server/TestContextNoIdImpl.java
similarity index 72%
copy from user/test/com/google/gwt/app/place/testplaces/Place3.java
copy to user/test/com/google/gwt/requestfactory/server/TestContextNoIdImpl.java
index 2ec0c64..8e64d37 100644
--- a/user/test/com/google/gwt/app/place/testplaces/Place3.java
+++ b/user/test/com/google/gwt/requestfactory/server/TestContextNoIdImpl.java
@@ -13,14 +13,19 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place.testplaces;
+package com.google.gwt.requestfactory.server;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
+ * Bad proxy, no id.
*/
-public class Place3 extends Place1 {
+public class TestContextNoIdImpl {
- public Place3(String token) {
- super(token);
+ public static TestContextNoIdImpl okMethodProxy() {
+ return null;
}
-}
\ No newline at end of file
+
+ public String getVersion() {
+ return null;
+ }
+}
+
diff --git a/user/test/com/google/gwt/app/place/testplaces/Place3.java b/user/test/com/google/gwt/requestfactory/server/TestContextNoVersionImpl.java
similarity index 71%
copy from user/test/com/google/gwt/app/place/testplaces/Place3.java
copy to user/test/com/google/gwt/requestfactory/server/TestContextNoVersionImpl.java
index 2ec0c64..0bccfa6 100644
--- a/user/test/com/google/gwt/app/place/testplaces/Place3.java
+++ b/user/test/com/google/gwt/requestfactory/server/TestContextNoVersionImpl.java
@@ -13,14 +13,19 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.app.place.testplaces;
+package com.google.gwt.requestfactory.server;
/**
- * Used by tests of {@link com.google.gwt.app.rebind.PlaceHistoryMapperGenerator}.
+ * Bad proxy, no version.
*/
-public class Place3 extends Place1 {
+public class TestContextNoVersionImpl {
- public Place3(String token) {
- super(token);
+ public static TestContextNoVersionImpl okMethodProxy() {
+ return null;
}
-}
\ No newline at end of file
+
+ public String getId() {
+ return null;
+ }
+}
+
diff --git a/user/test/com/google/gwt/requestfactory/shared/SimpleFooRequest.java b/user/test/com/google/gwt/requestfactory/shared/SimpleFooRequest.java
index 8549959..9ae1831 100644
--- a/user/test/com/google/gwt/requestfactory/shared/SimpleFooRequest.java
+++ b/user/test/com/google/gwt/requestfactory/shared/SimpleFooRequest.java
@@ -37,6 +37,8 @@
Request<SimpleFooProxy> echoComplex(SimpleFooProxy fooProxy,
SimpleBarProxy barProxy);
+ Request<SimpleFooProxy> fetchDoubleReference();
+
Request<List<SimpleFooProxy>> findAll();
Request<SimpleFooProxy> findSimpleFooById(Long id);
@@ -45,6 +47,10 @@
Request<Set<Integer>> getNumberSet();
+ Request<SimpleFooProxy> getSimpleFooWithSubPropertyCollection();
+
+ Request<SimpleFooProxy> getTripletReference();
+
InstanceRequest<SimpleFooProxy, String> hello(SimpleBarProxy proxy);
InstanceRequest<SimpleFooProxy, Void> persist();
@@ -59,11 +65,11 @@
Request<SimpleEnum> processEnumList(List<SimpleEnum> values);
- Request<String> processString(String value);
-
InstanceRequest<SimpleFooProxy, String> processList(
List<SimpleFooProxy> values);
+ Request<String> processString(String value);
+
InstanceRequest<SimpleFooProxy, Void> receiveNull(String value);
Request<Void> receiveNullList(List<SimpleFooProxy> value);
diff --git a/user/test/com/google/gwt/text/TextSuite.gwt.xml b/user/test/com/google/gwt/text/TextSuite.gwt.xml
new file mode 100644
index 0000000..de4eae9
--- /dev/null
+++ b/user/test/com/google/gwt/text/TextSuite.gwt.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
+<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">
+<module>
+ <inherits name="com.google.gwt.text.Text" />
+ <source path="client"/>
+</module>
\ No newline at end of file
diff --git a/user/test/com/google/gwt/text/TextSuite.java b/user/test/com/google/gwt/text/TextSuite.java
new file mode 100644
index 0000000..cfe30d3
--- /dev/null
+++ b/user/test/com/google/gwt/text/TextSuite.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2010 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.text;
+
+import com.google.gwt.junit.tools.GWTTestSuite;
+import com.google.gwt.text.client.DateTimeFormatRendererTest;
+import com.google.gwt.text.client.DoubleParserTest;
+import com.google.gwt.text.client.IntegerParserTest;
+import com.google.gwt.text.client.LongParserTest;
+
+import junit.framework.Test;
+
+/**
+ * Tests of com.google.gwt.text.
+ */
+public class TextSuite {
+ public static Test suite() {
+ GWTTestSuite suite = new GWTTestSuite(
+ "Tests of com.google.gwt.text");
+ suite.addTestSuite(DateTimeFormatRendererTest.class);
+ suite.addTestSuite(DoubleParserTest.class);
+ suite.addTestSuite(IntegerParserTest.class);
+ suite.addTestSuite(LongParserTest.class);
+ return suite;
+ }
+}
diff --git a/user/test/com/google/gwt/text/client/DateTimeFormatRendererTest.java b/user/test/com/google/gwt/text/client/DateTimeFormatRendererTest.java
new file mode 100644
index 0000000..d9844fe
--- /dev/null
+++ b/user/test/com/google/gwt/text/client/DateTimeFormatRendererTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2010 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.text.client;
+
+import com.google.gwt.i18n.client.DateTimeFormat;
+import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
+import com.google.gwt.i18n.client.TimeZone;
+import com.google.gwt.junit.client.GWTTestCase;
+
+import java.util.Date;
+
+/**
+ * Eponymous unit test.
+ */
+public class DateTimeFormatRendererTest extends GWTTestCase {
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.text.TextSuite";
+ }
+
+ public void testDefault() {
+ Date d = new Date(39874748234L);
+
+ assertEquals(
+ DateTimeFormat.getFormat(PredefinedFormat.DATE_SHORT).format(d),
+ new DateTimeFormatRenderer().render(d));
+ }
+
+ public void testFull() {
+ Date d = new Date(3983374748234L);
+ DateTimeFormat f = DateTimeFormat.getFormat(PredefinedFormat.DATE_FULL);
+ TimeZone t = TimeZone.createTimeZone(180);
+
+ assertEquals(f.format(d, t), new DateTimeFormatRenderer(f, t).render(d));
+ }
+
+ public void testNoTz() {
+ Date d = new Date(3983374748234L);
+ DateTimeFormat f = DateTimeFormat.getFormat(PredefinedFormat.DATE_FULL);
+
+ assertEquals(f.format(d), new DateTimeFormatRenderer(f).render(d));
+ }
+
+ public void testNull() {
+ assertEquals("", new DateTimeFormatRenderer().render(null));
+ }
+}
diff --git a/user/test/com/google/gwt/text/client/DoubleParserTest.java b/user/test/com/google/gwt/text/client/DoubleParserTest.java
new file mode 100644
index 0000000..d14414d
--- /dev/null
+++ b/user/test/com/google/gwt/text/client/DoubleParserTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2010 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.text.client;
+
+import com.google.gwt.junit.client.GWTTestCase;
+
+import java.text.ParseException;
+
+/**
+ * Eponymous unit test.
+ */
+public class DoubleParserTest extends GWTTestCase {
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.text.TextSuite";
+ }
+
+ public void testOuroborus() throws ParseException {
+ assertEquals("123", DoubleRenderer.instance().render(DoubleParser.instance().parse("123")));
+ }
+
+ public void testNull() throws ParseException {
+ assertEquals("", DoubleRenderer.instance().render(DoubleParser.instance().parse("")));
+ }
+}
diff --git a/user/test/com/google/gwt/text/client/IntegerParserTest.java b/user/test/com/google/gwt/text/client/IntegerParserTest.java
new file mode 100644
index 0000000..85f922d
--- /dev/null
+++ b/user/test/com/google/gwt/text/client/IntegerParserTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2010 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.text.client;
+
+import com.google.gwt.junit.client.GWTTestCase;
+
+import java.text.ParseException;
+
+/**
+ * Eponymous unit test.
+ */
+public class IntegerParserTest extends GWTTestCase {
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.text.TextSuite";
+ }
+
+ public void testOuroborus() throws ParseException {
+ assertEquals("123", IntegerRenderer.instance().render(IntegerParser.instance().parse("123")));
+ }
+
+ public void testNull() throws ParseException {
+ assertEquals("", IntegerRenderer.instance().render(IntegerParser.instance().parse("")));
+ }
+}
diff --git a/user/test/com/google/gwt/text/client/LongParserTest.java b/user/test/com/google/gwt/text/client/LongParserTest.java
new file mode 100644
index 0000000..25e72c0
--- /dev/null
+++ b/user/test/com/google/gwt/text/client/LongParserTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2010 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.text.client;
+
+import com.google.gwt.junit.client.GWTTestCase;
+
+import java.text.ParseException;
+
+/**
+ * Eponymous unit test.
+ */
+public class LongParserTest extends GWTTestCase {
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.text.TextSuite";
+ }
+
+ public void testOuroborus() throws ParseException {
+ assertEquals("123", LongRenderer.instance().render(LongParser.instance().parse("123")));
+ }
+
+ public void testNull() throws ParseException {
+ assertEquals("", LongRenderer.instance().render(LongParser.instance().parse("")));
+ }
+}
diff --git a/user/test/com/google/gwt/user/cellview/client/HasDataPresenterTest.java b/user/test/com/google/gwt/user/cellview/client/HasDataPresenterTest.java
index 5a1c40f..2b825f1 100644
--- a/user/test/com/google/gwt/user/cellview/client/HasDataPresenterTest.java
+++ b/user/test/com/google/gwt/user/cellview/client/HasDataPresenterTest.java
@@ -351,6 +351,18 @@
view.assertSelectedRows();
}
+ public void testDefaults() {
+ HasData<String> listView = new MockHasData<String>();
+ MockView<String> view = new MockView<String>();
+ HasDataPresenter<String> presenter = new HasDataPresenter<String>(listView,
+ view, 10, null);
+
+ assertEquals(0, presenter.getRowCount());
+ assertFalse(presenter.isRowCountExact());
+ assertEquals(0, presenter.getCurrentPageSize());
+ assertEquals(new Range(0, 10), presenter.getVisibleRange());
+ }
+
public void testGetCurrentPageSize() {
HasData<String> listView = new MockHasData<String>();
MockView<String> view = new MockView<String>();
@@ -884,10 +896,17 @@
assertTrue(presenter.isRowCountExact());
view.assertLoadingState(LoadingState.LOADING);
- // Set size to 0.
+ // Set size to 0, but not exact. The state is loading until we know there is
+ // no data.
presenter.setRowCount(0, false);
assertEquals(0, presenter.getRowCount());
assertFalse(presenter.isRowCountExact());
+ view.assertLoadingState(LoadingState.LOADING);
+
+ // Set size to 0 and exact. Now we know the list is empty.
+ presenter.setRowCount(0, true);
+ assertEquals(0, presenter.getRowCount());
+ assertTrue(presenter.isRowCountExact());
view.assertLoadingState(LoadingState.EMPTY);
}
diff --git a/user/test/com/google/gwt/user/client/ui/ValueBoxBaseTest.java b/user/test/com/google/gwt/user/client/ui/ValueBoxBaseTest.java
index da8d0ff..65a2ae1 100644
--- a/user/test/com/google/gwt/user/client/ui/ValueBoxBaseTest.java
+++ b/user/test/com/google/gwt/user/client/ui/ValueBoxBaseTest.java
@@ -18,8 +18,8 @@
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.junit.client.GWTTestCase;
-import com.google.gwt.text.shared.PassthroughRenderer;
import com.google.gwt.text.shared.Renderer;
+import com.google.gwt.text.shared.testing.PassthroughRenderer;
import java.text.ParseException;
@@ -35,7 +35,8 @@
MockParser parser = new MockParser();
ValueBoxBase<String> valueBoxBase =
- new ValueBoxBase<String>(elm, renderer, parser);
+ new ValueBoxBase<String>(elm, renderer, parser) {
+ };
parser.throwException = true;
valueBoxBase.setText("");
@@ -57,7 +58,8 @@
MockParser parser = new MockParser();
ValueBoxBase<String> valueBoxBase =
- new ValueBoxBase<String>(elm, renderer, parser);
+ new ValueBoxBase<String>(elm, renderer, parser) {
+ };
parser.throwException = true;
valueBoxBase.setText("simple string");
@@ -79,7 +81,8 @@
MockParser parser = new MockParser();
ValueBoxBase<String> valueBoxBase =
- new ValueBoxBase<String>(elm, renderer, parser);
+ new ValueBoxBase<String>(elm, renderer, parser) {
+ };
String text = " two space padding test ";
valueBoxBase.setText(text);