Allow @Editor.Path("") as a valid annotation to indicate that a sub-editor should be aliased to the object being edited by its parent object.
Patch by: bobv
Review by: rjrjr
Review at http://gwt-code-reviews.appspot.com/1205801
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9401 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/editor/client/impl/AbstractEditorDelegate.java b/user/src/com/google/gwt/editor/client/impl/AbstractEditorDelegate.java
index 911d743..ee85f62 100644
--- a/user/src/com/google/gwt/editor/client/impl/AbstractEditorDelegate.java
+++ b/user/src/com/google/gwt/editor/client/impl/AbstractEditorDelegate.java
@@ -187,6 +187,9 @@
public abstract HandlerRegistration subscribe();
protected String appendPath(String path) {
+ if (path.length() == 0) {
+ return this.path;
+ }
return appendPath(this.path, path);
}
diff --git a/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java b/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java
index a33e03b..56579a6 100644
--- a/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java
+++ b/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java
@@ -174,9 +174,9 @@
delegateFields.get(d));
} else if (d.isLeafValueEditor()) {
// if (can().access().without().npe()) { editor.subEditor.setValue() }
- sw.println("if (%4$s) editor.%1$s.setValue(getObject()%2$s.%3$s());",
+ sw.println("if (%4$s) editor.%1$s.setValue(getObject()%2$s%3$s);",
d.getSimpleExpression(), d.getBeanOwnerExpression(),
- d.getGetterName(), d.getBeanOwnerGuard("getObject()"));
+ d.getGetterExpression(), d.getBeanOwnerGuard("getObject()"));
// simpleEditor.put("some.path", editor.simpleEditor());
sw.println("simpleEditors.put(\"%s\", editor.%s);",
d.getDeclaredPath(), d.getSimpleExpression());
@@ -259,8 +259,8 @@
// if (can().access().without().npe()) {
sw.println("if (%s) {", d.getBeanOwnerGuard("getObject()"));
// subDelegate.refresh(getObject().getFoo().getBar());
- sw.indentln("%s.refresh(getObject()%s.%s());", delegateFields.get(d),
- d.getBeanOwnerExpression(), d.getGetterName());
+ sw.indentln("%s.refresh(getObject()%s%s);", delegateFields.get(d),
+ d.getBeanOwnerExpression(), d.getGetterExpression());
// } else { subDelegate.refresh(null); }
sw.println("} else { %s.refresh(null); }", delegateFields.get(d));
sw.outdent();
@@ -270,9 +270,9 @@
sw.println("if (editor.%s != null) {", d.getSimpleExpression());
sw.indent();
// if (can().access().without().npe()) { editor.subEditor.setValue() }
- sw.println("if (%4$s) editor.%1$s.setValue(getObject()%2$s.%3$s());",
+ sw.println("if (%4$s) editor.%1$s.setValue(getObject()%2$s%3$s);",
d.getSimpleExpression(), d.getBeanOwnerExpression(),
- d.getGetterName(), d.getBeanOwnerGuard("getObject()"));
+ d.getGetterExpression(), d.getBeanOwnerGuard("getObject()"));
// else { editor.subEditor.setValue(null); }
sw.println("else { editor.%s.setValue(null); }",
d.getSimpleExpression());
diff --git a/user/src/com/google/gwt/editor/rebind/SimpleBeanEditorDriverGenerator.java b/user/src/com/google/gwt/editor/rebind/SimpleBeanEditorDriverGenerator.java
index 1a2200b..33465d9 100644
--- a/user/src/com/google/gwt/editor/rebind/SimpleBeanEditorDriverGenerator.java
+++ b/user/src/com/google/gwt/editor/rebind/SimpleBeanEditorDriverGenerator.java
@@ -55,9 +55,9 @@
Map<EditorData, String> delegateFields) {
// fooDelegate.initialize(appendPath("foo"), getObject().getFoo(),
// editor.fooEditor);
- sw.println("%s.initialize(appendPath(\"%s\"), getObject()%s.%s(),"
+ sw.println("%s.initialize(appendPath(\"%s\"), getObject()%s%s,"
+ " editor.%s, delegateMap);", delegateFields.get(d),
- d.getPropertyName(), d.getBeanOwnerExpression(), d.getGetterName(),
+ d.getPropertyName(), d.getBeanOwnerExpression(), d.getGetterExpression(),
d.getSimpleExpression());
}
}
diff --git a/user/src/com/google/gwt/editor/rebind/model/EditorAccess.java b/user/src/com/google/gwt/editor/rebind/model/EditorAccess.java
index 91aca95..9260db2 100644
--- a/user/src/com/google/gwt/editor/rebind/model/EditorAccess.java
+++ b/user/src/com/google/gwt/editor/rebind/model/EditorAccess.java
@@ -102,8 +102,8 @@
}
/**
- * Returns <code> true if the editor accessed by this EditorAccess
- * implements the IsEditor interface.
+ * Returns {@code true} if the editor accessed by this EditorAccess implements
+ * the IsEditor interface.
*/
public boolean isEditor() {
return isEditor;
diff --git a/user/src/com/google/gwt/editor/rebind/model/EditorData.java b/user/src/com/google/gwt/editor/rebind/model/EditorData.java
index 29dcb44..0bda120 100644
--- a/user/src/com/google/gwt/editor/rebind/model/EditorData.java
+++ b/user/src/com/google/gwt/editor/rebind/model/EditorData.java
@@ -85,8 +85,7 @@
}
try {
data.editorExpression = (parent == null ? ""
- : (parent.getExpression() + "."))
- + access.getExpresson();
+ : (parent.getExpression() + ".")) + access.getExpresson();
data.path = (parent == null ? "" : (parent.getPath() + "."))
+ access.getPath();
@@ -103,8 +102,8 @@
}
}
- public Builder getterName(String value) {
- data.getterName = value;
+ public Builder getterExpression(String value) {
+ data.getterExpression = value;
return this;
}
@@ -131,7 +130,7 @@
private JClassType editedType;
private JClassType editorType;
private String editorExpression;
- private String getterName;
+ private String getterExpression;
private boolean isLeaf;
private boolean isCompositeEditor;
private boolean isDelegateRequired;
@@ -179,8 +178,12 @@
return editorExpression;
}
- public String getGetterName() {
- return getterName;
+ /**
+ * Returns an expression, relative to an instance of the parent object being
+ * edited, to retrieve the value to pass into the editor.
+ */
+ public String getGetterExpression() {
+ return getterExpression;
}
/**
diff --git a/user/src/com/google/gwt/editor/rebind/model/EditorModel.java b/user/src/com/google/gwt/editor/rebind/model/EditorModel.java
index 8577228..e11df64 100644
--- a/user/src/com/google/gwt/editor/rebind/model/EditorModel.java
+++ b/user/src/com/google/gwt/editor/rebind/model/EditorModel.java
@@ -455,6 +455,9 @@
JClassType lookingAt = proxyType;
part : for (int i = 0, j = parts.length; i < j; i++) {
+ if (parts[i].length() == 0) {
+ continue;
+ }
String getterName = camelCase("get", parts[i]);
for (JClassType search : lookingAt.getFlattenedSupertypeHierarchy()) {
@@ -494,7 +497,7 @@
}
int idx = interstitialGetters.lastIndexOf(".");
- builder.beanOwnerExpression(idx == 0 ? "" : interstitialGetters.substring(
+ builder.beanOwnerExpression(idx <= 0 ? "" : interstitialGetters.substring(
0, idx));
if (parts.length > 1) {
// Strip after last && since null is a valid value
@@ -502,8 +505,13 @@
interstitialGuard.length());
builder.beanOwnerGuard(interstitialGuard.substring(8));
}
- builder.getterName(interstitialGetters.substring(idx + 1,
- interstitialGetters.length() - 2));
+ if (interstitialGetters.length() > 0) {
+ builder.getterExpression("."
+ + interstitialGetters.substring(idx + 1,
+ interstitialGetters.length() - 2) + "()");
+ } else {
+ builder.getterExpression("");
+ }
builder.setterName(setterName);
}
diff --git a/user/src/com/google/gwt/requestfactory/rebind/RequestFactoryEditorDriverGenerator.java b/user/src/com/google/gwt/requestfactory/rebind/RequestFactoryEditorDriverGenerator.java
index e36214f..84e5f78 100644
--- a/user/src/com/google/gwt/requestfactory/rebind/RequestFactoryEditorDriverGenerator.java
+++ b/user/src/com/google/gwt/requestfactory/rebind/RequestFactoryEditorDriverGenerator.java
@@ -89,9 +89,9 @@
protected void writeDelegateInitialization(SourceWriter sw, EditorData d,
Map<EditorData, String> delegateFields) {
sw.println("%s.initialize(eventBus, factory, "
- + "appendPath(\"%s\"), getObject()%s.%s()," + " editor.%s,"
+ + "appendPath(\"%s\"), getObject()%s%s," + " editor.%s,"
+ " delegateMap, request);", delegateFields.get(d),
- d.getPropertyName(), d.getBeanOwnerExpression(), d.getGetterName(),
- d.getSimpleExpression());
+ d.getPropertyName(), d.getBeanOwnerExpression(),
+ d.getGetterExpression(), d.getSimpleExpression());
}
}
diff --git a/user/test/com/google/gwt/editor/EditorSuite.java b/user/test/com/google/gwt/editor/EditorSuite.java
index e69456e..a4d615c 100644
--- a/user/test/com/google/gwt/editor/EditorSuite.java
+++ b/user/test/com/google/gwt/editor/EditorSuite.java
@@ -15,8 +15,6 @@
*/
package com.google.gwt.editor;
-import com.google.gwt.autobean.client.AutoBeanTest;
-import com.google.gwt.autobean.server.AutoBeanJreTest;
import com.google.gwt.editor.client.EditorErrorTest;
import com.google.gwt.editor.client.SimpleBeanEditorTest;
import com.google.gwt.editor.client.adapters.ListEditorWrapperTest;
@@ -34,8 +32,6 @@
public static Test suite() {
GWTTestSuite suite = new GWTTestSuite(
"Test suite for core Editor functions");
- suite.addTestSuite(AutoBeanJreTest.class);
- suite.addTestSuite(AutoBeanTest.class);
suite.addTestSuite(DelegateMapTest.class);
suite.addTestSuite(EditorModelTest.class);
suite.addTestSuite(EditorErrorTest.class);
diff --git a/user/test/com/google/gwt/editor/client/SimpleBeanEditorTest.java b/user/test/com/google/gwt/editor/client/SimpleBeanEditorTest.java
index 1f15edb..b2e55bd 100644
--- a/user/test/com/google/gwt/editor/client/SimpleBeanEditorTest.java
+++ b/user/test/com/google/gwt/editor/client/SimpleBeanEditorTest.java
@@ -93,6 +93,22 @@
SimpleBeanEditorDriver<Person, PersonEditorWithAddressEditorView> {
}
+ /**
+ * A test for assigning the object associated with an editor to an immediate
+ * child editors.
+ */
+ class PersonEditorWithAliasedSubEditors implements Editor<Person> {
+ @Path("")
+ PersonEditor e1 = new PersonEditor();
+
+ @Path("")
+ PersonEditor e2 = new PersonEditor();
+ }
+
+ interface PersonEditorWithAliasedSubEditorsDriver extends
+ SimpleBeanEditorDriver<Person, PersonEditorWithAliasedSubEditors> {
+ }
+
class PersonEditorWithCoAddressEditorView implements Editor<Person> {
AddressCoEditorView addressEditor = new AddressCoEditorView();
SimpleEditor<String> name = SimpleEditor.of(UNINITIALIZED);
@@ -265,6 +281,29 @@
assertEquals("David", person.manager.name);
}
+ public void testAliasedEditors() {
+ PersonEditorWithAliasedSubEditors editor = new PersonEditorWithAliasedSubEditors();
+ PersonEditorWithAliasedSubEditorsDriver driver = GWT.create(PersonEditorWithAliasedSubEditorsDriver.class);
+ driver.initialize(editor);
+ driver.edit(person);
+
+ assertEquals("Alice", editor.e1.name.getValue());
+ assertEquals("Alice", editor.e2.name.getValue());
+
+ /*
+ * Expecting that aliased editors will be editing disjoint sets of
+ * properties, but we want to at least have a predictable behavior if two
+ * editors are assigned to the same property.
+ */
+ editor.e1.name.setValue("Should not see this");
+ driver.flush();
+ assertEquals("Alice", person.getName());
+
+ editor.e2.name.setValue("Should see this");
+ driver.flush();
+ assertEquals("Should see this", person.getName());
+ }
+
/**
* Test the use of the IsEditor interface that allows a view object to
* encapsulate its Editor.
diff --git a/user/test/com/google/gwt/editor/rebind/model/EditorModelTest.java b/user/test/com/google/gwt/editor/rebind/model/EditorModelTest.java
index d7164d4..564b02f 100644
--- a/user/test/com/google/gwt/editor/rebind/model/EditorModelTest.java
+++ b/user/test/com/google/gwt/editor/rebind/model/EditorModelTest.java
@@ -198,12 +198,12 @@
assertFalse(fields[0].isDeclaredPathNested());
assertEquals("", fields[0].getBeanOwnerExpression());
assertEquals("true", fields[0].getBeanOwnerGuard("object"));
- assertEquals("getName", fields[0].getGetterName());
+ assertEquals(".getName()", fields[0].getGetterExpression());
assertEquals("address.street", fields[1].getPath());
assertEquals(".getAddress()", fields[1].getBeanOwnerExpression());
assertEquals("object.getAddress() != null",
fields[1].getBeanOwnerGuard("object"));
- assertEquals("getStreet", fields[1].getGetterName());
+ assertEquals(".getStreet()", fields[1].getGetterExpression());
assertEquals("setStreet", fields[1].getSetterName());
assertEquals("street", fields[1].getPropertyName());
assertTrue(fields[1].isDeclaredPathNested());
@@ -404,6 +404,16 @@
testLogger.assertCorrectLogEntries();
}
+ /**
+ * Verify that {@code @Path("")} is valid.
+ */
+ public void testZeroLengthPath() throws UnableToCompleteException {
+ EditorModel m = new EditorModel(logger,
+ types.findType("t.PersonEditorWithAliasedSubEditorsDriver"), rfedType);
+ EditorData[] fields = m.getEditorData();
+ assertEquals(6, fields.length);
+ }
+
private void checkPersonName(EditorData editorField) {
assertNotNull(editorField);
assertEquals(types.findType(SimpleEditor.class.getName()),
@@ -411,7 +421,7 @@
assertTrue(editorField.isLeafValueEditor());
assertFalse(editorField.isDelegateRequired());
assertFalse(editorField.isValueAwareEditor());
- assertEquals("getName", editorField.getGetterName());
+ assertEquals(".getName()", editorField.getGetterExpression());
assertEquals("setName", editorField.getSetterName());
}
@@ -425,7 +435,7 @@
assertTrue(editorField.isLeafValueEditor());
assertFalse(editorField.isDelegateRequired());
assertFalse(editorField.isValueAwareEditor());
- assertEquals("getReadonly", editorField.getGetterName());
+ assertEquals(".getReadonly()", editorField.getGetterExpression());
assertNull(editorField.getSetterName());
}
@@ -614,6 +624,31 @@
code.append("}");
return code;
}
+ }, new MockJavaResource("t.PersonEditorWithAliasedSubEditors") {
+ @Override
+ protected CharSequence getContent() {
+ StringBuilder code = new StringBuilder();
+ code.append("package t;\n");
+ code.append("import " + Editor.class.getName() + ";\n");
+ code.append("import " + SimpleEditor.class.getName() + ";\n");
+ code.append("class PersonEditorWithAliasedSubEditors implements Editor<PersonProxy> {\n");
+ code.append("@Path(\"\") PersonEditor e1;\n");
+ code.append("@Path(\"\") PersonEditor e2;\n");
+ code.append("}");
+ return code;
+ }
+ }, new MockJavaResource("t.PersonEditorWithAliasedSubEditorsDriver") {
+ @Override
+ protected CharSequence getContent() {
+ StringBuilder code = new StringBuilder();
+ code.append("package t;\n");
+ code.append("import " + RequestFactoryEditorDriver.class.getName()
+ + ";\n");
+ code.append("interface PersonEditorWithAliasedSubEditorsDriver extends"
+ + " RequestFactoryEditorDriver<PersonProxy, t.PersonEditorWithAliasedSubEditors> {\n");
+ code.append("}");
+ return code;
+ }
}, new MockJavaResource("t.PersonEditorUsingMethods") {
@Override
protected CharSequence getContent() {
@@ -774,7 +809,7 @@
}};
Set<Resource> toReturn = new HashSet<Resource>(Arrays.asList(javaFiles));
- toReturn.addAll(Arrays.asList(new Resource[] {
+ toReturn.addAll(Arrays.asList(new Resource[]{
new RealJavaResource(CompositeEditor.class),
new RealJavaResource(Editor.class),
new RealJavaResource(EditorError.class),