Resolves ROO-1508 by requiring CompositeEditors to return a canonical component Editor instance for path traversal.
Patch by: bobv
Review by: rjrjr
Review at http://gwt-code-reviews.appspot.com/965801
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8965 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/editor/client/CompositeEditor.java b/user/src/com/google/gwt/editor/client/CompositeEditor.java
index 11569de..95d48a6 100644
--- a/user/src/com/google/gwt/editor/client/CompositeEditor.java
+++ b/user/src/com/google/gwt/editor/client/CompositeEditor.java
@@ -82,6 +82,12 @@
}
/**
+ * Returns an canonical sub-editor instance that will be used by the driver
+ * for computing all edited paths.
+ */
+ E createEditorForTraversal();
+
+ /**
* Used to implement {@link EditorDelegate#getPath()}.
*/
String getPathElement(E subEditor);
diff --git a/user/src/com/google/gwt/editor/client/adapters/ListEditor.java b/user/src/com/google/gwt/editor/client/adapters/ListEditor.java
index 314be63..988aaa2 100644
--- a/user/src/com/google/gwt/editor/client/adapters/ListEditor.java
+++ b/user/src/com/google/gwt/editor/client/adapters/ListEditor.java
@@ -52,6 +52,12 @@
this.editorSource = source;
}
+ public E createEditorForTraversal() {
+ E toReturn = editorSource.create(0);
+ editorSource.dispose(toReturn);
+ return toReturn;
+ }
+
public void flush() {
list.flush();
}
diff --git a/user/src/com/google/gwt/editor/client/adapters/OptionalFieldEditor.java b/user/src/com/google/gwt/editor/client/adapters/OptionalFieldEditor.java
index cac0a07..0373e16 100644
--- a/user/src/com/google/gwt/editor/client/adapters/OptionalFieldEditor.java
+++ b/user/src/com/google/gwt/editor/client/adapters/OptionalFieldEditor.java
@@ -63,6 +63,10 @@
this.subEditor = subEditor;
}
+ public E createEditorForTraversal() {
+ return subEditor;
+ }
+
public void flush() {
currentValue = chain.getValue(subEditor);
}
diff --git a/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java b/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java
index 18f9f62..a33e03b 100644
--- a/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java
+++ b/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java
@@ -194,8 +194,8 @@
for (EditorData d : data) {
String mutableObjectExpression;
if (d.getBeanOwnerExpression().length() > 0) {
- mutableObjectExpression = mutableObjectExpression(d, String.format(
- "(getObject()%s)", d.getBeanOwnerExpression()));
+ mutableObjectExpression = mutableObjectExpression(d,
+ String.format("(getObject()%s)", d.getBeanOwnerExpression()));
} else {
mutableObjectExpression = "getObject()";
}
@@ -294,7 +294,8 @@
editor.getQualifiedSourceName(), List.class.getName());
sw.indent();
for (EditorData d : data) {
- if (d.isDelegateRequired() || d.isDeclaredPathNested()) {
+ if (d.isDelegateRequired() || d.isDeclaredPathNested()
+ || d.isCompositeEditor()) {
// if (editor.subEditor != null) {
sw.println("if (editor.%s != null) {", d.getSimpleExpression());
sw.indent();
@@ -308,6 +309,15 @@
sw.println("%s.traverseEditor(editor.%s, localPath, paths);",
getEditorDelegate(d), d.getSimpleExpression());
}
+ if (d.isCompositeEditor()) {
+ /*
+ * composedDelegate.traverseEditor(editor.subEditor.
+ * createEditorForTraversal(), localPath, paths);
+ */
+ sw.println(
+ "%s.traverseEditor(editor.%s.createEditorForTraversal(), localPath, paths);",
+ getEditorDelegate(d.getComposedData()), d.getSimpleExpression());
+ }
sw.outdent();
sw.println("}");
}
@@ -330,7 +340,7 @@
* @param context
* @param model
* @param sw
- *
+ *
* @throws UnableToCompleteException
*/
protected void writeAdditionalContent(TreeLogger logger,
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 3dab1b4..8577228 100644
--- a/user/src/com/google/gwt/editor/rebind/model/EditorModel.java
+++ b/user/src/com/google/gwt/editor/rebind/model/EditorModel.java
@@ -60,7 +60,7 @@
if (compositeEditorIntf.equals(parameterized.getBaseType())) {
JClassType[] typeArgs = parameterized.getTypeArgs();
assert typeArgs.length == 3;
- return new JClassType[] {typeArgs[1], typeArgs[2]};
+ return new JClassType[]{typeArgs[1], typeArgs[2]};
}
}
}
@@ -83,8 +83,8 @@
if (parameterization != null) {
return parameterization[0];
}
- logger.log(TreeLogger.ERROR, noEditorParameterizationMessage(editorIntf,
- editorType));
+ logger.log(TreeLogger.ERROR,
+ noEditorParameterizationMessage(editorIntf, editorType));
throw new UnableToCompleteException();
}
@@ -102,8 +102,8 @@
if (parameterization != null) {
return parameterization[0];
}
- logger.log(TreeLogger.ERROR, noEditorParameterizationMessage(editorIntf,
- editorType));
+ logger.log(TreeLogger.ERROR,
+ noEditorParameterizationMessage(editorIntf, editorType));
throw new UnableToCompleteException();
}
@@ -326,6 +326,10 @@
&& isEditorIntf.isAssignableFrom(editorType)) {
// Ignore IsEditor.asEditor()
continue;
+ } else if (access.getPath().equals("createEditorForTraversal")
+ && compositeEditorIntf.isAssignableFrom(editorType)) {
+ // Ignore CompositeEditor.createEditorForTraversal();
+ continue;
}
List<EditorData> data = createEditorData(access);
accumulateEditorData(data, flatData, toReturn);
@@ -376,8 +380,8 @@
// Are we looking at a view that implements IsEditor?
if (access.isEditor()) {
- EditorAccess subAccess = EditorAccess.via(access, calculateIsEditedType(
- subLogger, access.getEditorType()));
+ EditorAccess subAccess = EditorAccess.via(access,
+ calculateIsEditedType(subLogger, access.getEditorType()));
toReturn = createEditorData(subAccess);
// If an object only implements IsEditor, return now
diff --git a/user/test/com/google/gwt/requestfactory/client/ui/EditorTest.java b/user/test/com/google/gwt/requestfactory/client/ui/EditorTest.java
index 6b1cc48..d9b71ae 100644
--- a/user/test/com/google/gwt/requestfactory/client/ui/EditorTest.java
+++ b/user/test/com/google/gwt/requestfactory/client/ui/EditorTest.java
@@ -23,6 +23,8 @@
import com.google.gwt.editor.client.EditorError;
import com.google.gwt.editor.client.HasEditorDelegate;
import com.google.gwt.editor.client.HasEditorErrors;
+import com.google.gwt.editor.client.adapters.EditorSource;
+import com.google.gwt.editor.client.adapters.ListEditor;
import com.google.gwt.editor.client.adapters.SimpleEditor;
import com.google.gwt.requestfactory.client.RequestFactoryEditorDriver;
import com.google.gwt.requestfactory.client.RequestFactoryTestBase;
@@ -55,6 +57,10 @@
RequestFactoryEditorDriver<SimpleFooProxy, SimpleFooEditor> {
}
+ static class SimpleFooBarOnlyEditor implements Editor<SimpleFooProxy> {
+ SimpleBarEditor barField = new SimpleBarEditor();
+ }
+
static class SimpleFooEditor implements HasEditorErrors<SimpleFooProxy> {
/**
* Test field-based access.
@@ -67,6 +73,13 @@
@Path("barField.userName")
final SimpleEditor<String> barName = SimpleEditor.of();
+ final ListEditor<SimpleFooProxy, SimpleFooBarOnlyEditor> selfOneToManyField = ListEditor.of(new EditorSource<SimpleFooBarOnlyEditor>() {
+ @Override
+ public SimpleFooBarOnlyEditor create(int index) {
+ return new SimpleFooBarOnlyEditor();
+ }
+ });
+
private final SimpleBarEditor barEditor = new SimpleBarEditor();
List<EditorError> errors;
@@ -108,32 +121,32 @@
driver.initialize(req, editor);
req.simpleFooRequest().findSimpleFooById(1L).with(driver.getPaths()).fire(
- new Receiver<SimpleFooProxy>() {
- @Override
- public void onSuccess(SimpleFooProxy response) {
-
- SimpleFooRequest context = req.simpleFooRequest();
- driver.edit(response, context);
- context.persistAndReturnSelf().using(response).with(
- driver.getPaths()).to(new Receiver<SimpleFooProxy>() {
+ new Receiver<SimpleFooProxy>() {
@Override
public void onSuccess(SimpleFooProxy response) {
- assertEquals("EditorFooTest", response.getUserName());
- assertEquals("EditorBarTest",
- response.getBarField().getUserName());
- finishTestAndReset();
+
+ SimpleFooRequest context = req.simpleFooRequest();
+ driver.edit(response, context);
+ context.persistAndReturnSelf().using(response).with(
+ driver.getPaths()).to(new Receiver<SimpleFooProxy>() {
+ @Override
+ public void onSuccess(SimpleFooProxy response) {
+ assertEquals("EditorFooTest", response.getUserName());
+ assertEquals("EditorBarTest",
+ response.getBarField().getUserName());
+ finishTestAndReset();
+ }
+ });
+ assertEquals("GWT", editor.userName.getValue());
+ assertEquals("FOO", editor.barEditor().userName.getValue());
+ assertEquals("FOO", editor.barName.getValue());
+ editor.userName.setValue("EditorFooTest");
+ // When there are duplicate paths, last declared editor wins
+ editor.barEditor().userName.setValue("EditorBarTest");
+ editor.barName.setValue("ignored");
+ driver.flush().fire();
}
});
- assertEquals("GWT", editor.userName.getValue());
- assertEquals("FOO", editor.barEditor().userName.getValue());
- assertEquals("FOO", editor.barName.getValue());
- editor.userName.setValue("EditorFooTest");
- // When there are duplicate paths, last declared editor wins
- editor.barEditor().userName.setValue("EditorBarTest");
- editor.barName.setValue("ignored");
- driver.flush().fire();
- }
- });
}
public void testNoSubscription() {
@@ -141,10 +154,10 @@
final SimpleFooDriver driver = GWT.create(SimpleFooDriver.class);
driver.initialize(req, editor);
-
+
/*
* Confirm that it's always safe to call subscribe. The editor's delegate
- * isn't set until edit is called, so edit nothing.
+ * isn't set until edit is called, so edit nothing.
*/
driver.edit(null, null);
assertNull(editor.delegate.subscribe());
@@ -157,10 +170,11 @@
final SimpleFooDriver driver = GWT.create(SimpleFooDriver.class);
driver.initialize(req, editor);
- assertEquals(Arrays.asList("barField.userName", "barField"),
- Arrays.asList(driver.getPaths()));
+ String[] paths = driver.getPaths();
+ assertEquals(Arrays.asList("barField.userName", "selfOneToManyField",
+ "selfOneToManyField.barField", "barField"), Arrays.asList(paths));
- req.simpleFooRequest().findSimpleFooById(1L).with(driver.getPaths()).fire(
+ req.simpleFooRequest().findSimpleFooById(1L).with(paths).fire(
new Receiver<SimpleFooProxy>() {
@Override
public void onSuccess(SimpleFooProxy response) {
@@ -202,7 +216,7 @@
}
});
}
-
+
public void testViolations() {
delayTestFinish(TEST_TIMEOUT);
final SimpleFooEditor editor = new SimpleFooEditor();