Fix a NullPointerException in Editor framework when a null sub-Editor is encountered during traversal. Patch by: bobv Review by: rjrjr Review at http://gwt-code-reviews.appspot.com/1354802 git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9705 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/editor/client/impl/AbstractEditorContext.java b/user/src/com/google/gwt/editor/client/impl/AbstractEditorContext.java index 64b04e4..8f33519 100644 --- a/user/src/com/google/gwt/editor/client/impl/AbstractEditorContext.java +++ b/user/src/com/google/gwt/editor/client/impl/AbstractEditorContext.java
@@ -41,11 +41,6 @@ private final LeafValueEditor<T> leafValueEditor; private final ValueAwareEditor<T> valueAwareEditor; - public AbstractEditorContext(AbstractEditorDelegate<T, ?> delegate) { - this(delegate.getEditor(), delegate.getPath()); - this.delegate = delegate; - } - public AbstractEditorContext(Editor<T> editor, String path) { this.editor = editor; this.path = path; @@ -123,6 +118,10 @@ return isHalted; } + public void setEditorDelegate(AbstractEditorDelegate<T, ?> delegate) { + this.delegate = delegate; + } + public abstract void setInModel(T data); public void traverse(EditorVisitor visitor, AbstractEditorDelegate<?, ?> next) {
diff --git a/user/src/com/google/gwt/editor/client/impl/RootEditorContext.java b/user/src/com/google/gwt/editor/client/impl/RootEditorContext.java index 5f82cda..3723c13 100644 --- a/user/src/com/google/gwt/editor/client/impl/RootEditorContext.java +++ b/user/src/com/google/gwt/editor/client/impl/RootEditorContext.java
@@ -28,7 +28,8 @@ public RootEditorContext(AbstractEditorDelegate<T, ?> editorDelegate, Class<T> editedType, T value) { - super(editorDelegate); + super(editorDelegate.getEditor(), editorDelegate.getPath()); + setEditorDelegate(editorDelegate); this.editedType = editedType; this.value = value; }
diff --git a/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java b/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java index a080e37..fdb0427 100644 --- a/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java +++ b/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java
@@ -27,7 +27,6 @@ import com.google.gwt.editor.client.Editor; import com.google.gwt.editor.client.EditorVisitor; import com.google.gwt.editor.client.impl.AbstractEditorContext; -import com.google.gwt.editor.client.impl.AbstractEditorDelegate; import com.google.gwt.editor.client.impl.RootEditorContext; import com.google.gwt.editor.rebind.model.EditorData; import com.google.gwt.editor.rebind.model.EditorModel; @@ -192,17 +191,18 @@ sw.println("getEditorChain().accept(visitor);"); } for (EditorData d : data) { + if (d.isDelegateRequired()) { + sw.println("if (%s != null) ", delegateFields.get(d)); + } sw.println("{"); sw.indent(); String editorContextName = getEditorContext(delegateData, d); + sw.println( + "%s ctx = new %s(getObject(), editor.%s, appendPath(\"%s\"));", + editorContextName, editorContextName, d.getSimpleExpression(), + d.getDeclaredPath()); if (d.isDelegateRequired()) { - sw.println("%s ctx = new %s(getObject(), %s);", editorContextName, - editorContextName, delegateFields.get(d)); - } else { - sw.println( - "%s ctx = new %s(getObject(), editor.%s, appendPath(\"%s\"));", - editorContextName, editorContextName, d.getSimpleExpression(), - d.getDeclaredPath()); + sw.println("ctx.setEditorDelegate(%s);", delegateFields.get(d)); } sw.println("ctx.traverse(visitor, %s);", d.isDelegateRequired() ? delegateFields.get(d) : "null"); @@ -250,19 +250,13 @@ if (pw != null) { ClassSourceFileComposerFactory f = new ClassSourceFileComposerFactory( pkg, simpleName); - String editedSourceName = data.getEditedType().getQualifiedSourceName(); + String editedSourceName = data.getEditedType().getParameterizedQualifiedSourceName(); f.setSuperclass(AbstractEditorContext.class.getCanonicalName() + "<" + editedSourceName + ">"); SourceWriter sw = f.createSourceWriter(context, pw); String parentSourceName = parent.getEditedType().getQualifiedSourceName(); sw.println("private final %s parent;", parentSourceName); - sw.println("public %s(%s parent, %s<%s, ?> delegate) {", simpleName, - parentSourceName, AbstractEditorDelegate.class.getCanonicalName(), - editedSourceName); - sw.indentln("super(delegate);"); - sw.indentln("this.parent = parent;"); - sw.println("}"); sw.println("public %s(%s parent, %s<%s> editor, String path) {", simpleName, parentSourceName, Editor.class.getCanonicalName(), @@ -283,8 +277,8 @@ sw.println("}"); sw.println( - "@Override public Class<%1$s> getEditedType() { return %1$s.class; }", - editedSourceName); + "@Override public Class getEditedType() { return %s.class; }", + data.getEditedType().getQualifiedSourceName()); sw.println("@Override public %s getFromModel() {", editedSourceName); sw.indentln("return (parent != null && %s) ? parent%s%s : null;",
diff --git a/user/test/com/google/gwt/editor/client/SimpleBeanEditorTest.java b/user/test/com/google/gwt/editor/client/SimpleBeanEditorTest.java index 2f5b990..66d7c9f 100644 --- a/user/test/com/google/gwt/editor/client/SimpleBeanEditorTest.java +++ b/user/test/com/google/gwt/editor/client/SimpleBeanEditorTest.java
@@ -321,6 +321,37 @@ assertEquals("Should see this", person.getName()); } + public void testEditorWithNullSubEditor() { + PersonEditor editor = new PersonEditor(); + editor.addressEditor = null; + PersonEditorDriver driver = GWT.create(PersonEditorDriver.class); + driver.initialize(editor); + driver.edit(person); + + assertEquals("Alice", editor.name.getValue()); + editor.name.setValue("New name"); + driver.flush(); + assertEquals("New name", person.getName()); + + /* + * Verify that changing the editor structure without re-initializing is a + * no-op. + */ + editor.name.setValue("Should see this"); + editor.addressEditor = new AddressEditor(); + editor.addressEditor.city.setValue("Should not see this"); + driver.flush(); + assertEquals("Should see this", person.getName()); + assertEquals("City", person.getAddress().getCity()); + + // Re-initialize and check that flushing works again + driver.initialize(editor); + driver.edit(person); + editor.addressEditor.city.setValue("Should see this"); + driver.flush(); + assertEquals("Should see this", person.getAddress().getCity()); + } + /** * Test the use of the IsEditor interface that allows a view object to * encapsulate its Editor.