Cherry-pick r10472 into GWT 2.4 branch. git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/2.4@10474 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 ed1e52b..583711e 100644 --- a/user/src/com/google/gwt/editor/client/impl/AbstractEditorDelegate.java +++ b/user/src/com/google/gwt/editor/client/impl/AbstractEditorDelegate.java
@@ -80,7 +80,7 @@ subDelegate.path = subPath; } subDelegate.setObject(ensureMutable(object)); - traverse(new Initializer(), subDelegate); + traverse(createInitializerVisitor(), subDelegate); } public void detach(S subEditor) { @@ -177,6 +177,10 @@ throw new IllegalStateException(); } + protected EditorVisitor createInitializerVisitor() { + return new Initializer(); + } + protected <Q> Q ensureMutable(Q object) { return object; }
diff --git a/user/src/com/google/gwt/editor/client/impl/BaseEditorDriver.java b/user/src/com/google/gwt/editor/client/impl/BaseEditorDriver.java index dddb011..7c4dc5f 100644 --- a/user/src/com/google/gwt/editor/client/impl/BaseEditorDriver.java +++ b/user/src/com/google/gwt/editor/client/impl/BaseEditorDriver.java
@@ -63,8 +63,7 @@ return c.isDirty() || !leafValueMap.equals(c.getLeafValues()); } - public boolean setConstraintViolations( - final Iterable<ConstraintViolation<?>> violations) { + public boolean setConstraintViolations(final Iterable<ConstraintViolation<?>> violations) { return doSetViolations(SimpleViolation.iterableFromConstrantViolations(violations)); } @@ -73,8 +72,7 @@ if (GWT.isProdMode()) { return super.toString(); } else { - return editor == null ? "Uninitialized" - : EditorHierarchyPrinter.toString(asEditorDriver()); + return editor == null ? "Uninitialized" : EditorHierarchyPrinter.toString(asEditorDriver()); } } @@ -84,12 +82,16 @@ protected abstract AbstractEditorDelegate<T, E> createDelegate(); + protected EditorVisitor createInitializerVisitor() { + return new Initializer(); + } + protected void doEdit(T object) { checkEditor(); object = delegate.ensureMutable(object); this.object = object; delegate.setObject(object); - accept(new Initializer()); + accept(createInitializerVisitor()); DirtCollector c = new DirtCollector(); accept(c); leafValueMap = c.getLeafValues(); @@ -110,8 +112,7 @@ protected boolean doSetViolations(Iterable<SimpleViolation> violations) { checkObject(); - SimpleViolation.pushViolations(violations, asEditorDriver(), - getViolationKeyMethod()); + SimpleViolation.pushViolations(violations, asEditorDriver(), getViolationKeyMethod()); // Collect the errors, which will take care of co-editor chains. errors = new ArrayList<EditorError>();
diff --git a/user/src/com/google/gwt/editor/client/impl/Initializer.java b/user/src/com/google/gwt/editor/client/impl/Initializer.java index 84168a5..3e9eb4c 100644 --- a/user/src/com/google/gwt/editor/client/impl/Initializer.java +++ b/user/src/com/google/gwt/editor/client/impl/Initializer.java
@@ -24,7 +24,7 @@ * Extends the logic in Refresher to provide the editor instance with references * to framework plumbing fixes. */ -class Initializer extends Refresher { +public class Initializer extends Refresher { @Override public <Q> boolean visit(EditorContext<Q> ctx) {
diff --git a/user/src/com/google/web/bindery/requestfactory/gwt/client/impl/AbstractRequestFactoryEditorDriver.java b/user/src/com/google/web/bindery/requestfactory/gwt/client/impl/AbstractRequestFactoryEditorDriver.java index 79a767f..fa7aa35 100644 --- a/user/src/com/google/web/bindery/requestfactory/gwt/client/impl/AbstractRequestFactoryEditorDriver.java +++ b/user/src/com/google/web/bindery/requestfactory/gwt/client/impl/AbstractRequestFactoryEditorDriver.java
@@ -16,7 +16,6 @@ package com.google.web.bindery.requestfactory.gwt.client.impl; import com.google.gwt.editor.client.Editor; -import com.google.gwt.editor.client.EditorContext; import com.google.gwt.editor.client.EditorVisitor; import com.google.gwt.editor.client.impl.AbstractEditorDelegate; import com.google.gwt.editor.client.impl.BaseEditorDriver; @@ -26,7 +25,6 @@ import com.google.web.bindery.autobean.shared.AutoBean; import com.google.web.bindery.autobean.shared.AutoBeanUtils; import com.google.web.bindery.event.shared.EventBus; -import com.google.web.bindery.requestfactory.gwt.client.HasRequestContext; import com.google.web.bindery.requestfactory.gwt.client.RequestFactoryEditorDriver; import com.google.web.bindery.requestfactory.shared.EntityProxy; import com.google.web.bindery.requestfactory.shared.RequestContext; @@ -43,8 +41,8 @@ * @param <R> the type being edited * @param <E> the type of Editor */ -public abstract class AbstractRequestFactoryEditorDriver<R, E extends Editor<R>> - extends BaseEditorDriver<R, E> implements RequestFactoryEditorDriver<R, E> { +public abstract class AbstractRequestFactoryEditorDriver<R, E extends Editor<R>> extends + BaseEditorDriver<R, E> implements RequestFactoryEditorDriver<R, E> { /** * Adapts a RequestFactory Violation object to the SimpleViolation interface. @@ -89,12 +87,14 @@ private final Iterable<com.google.web.bindery.requestfactory.shared.Violation> violations; - public ViolationIterable(Iterable<com.google.web.bindery.requestfactory.shared.Violation> violations) { + public ViolationIterable( + Iterable<com.google.web.bindery.requestfactory.shared.Violation> violations) { this.violations = violations; } public Iterator<SimpleViolation> iterator() { - final Iterator<com.google.web.bindery.requestfactory.shared.Violation> source = violations.iterator(); + final Iterator<com.google.web.bindery.requestfactory.shared.Violation> source = + violations.iterator(); return new Iterator<SimpleViolation>() { public boolean hasNext() { return source.hasNext(); @@ -159,22 +159,13 @@ edit(object, null); } - public void edit(R object, final RequestContext saveRequest) { + public void edit(R object, RequestContext saveRequest) { this.saveRequest = saveRequest; - // Provide the delegate and maybe the editor with the RequestContext - accept(new EditorVisitor() { - @Override - public <T> void endVisit(EditorContext<T> ctx) { - RequestFactoryEditorDelegate<?, ?> delegate = (RequestFactoryEditorDelegate<?, ?>) ctx.getEditorDelegate(); - if (delegate != null) { - delegate.setRequestContext(saveRequest); - } - Editor<T> editor = ctx.getEditor(); - if (editor instanceof HasRequestContext<?>) { - ((HasRequestContext<T>) editor).setRequestContext(saveRequest); - } - } - }); + /* + * Provide the delegate with the RequestContext so ensureMutable works as + * expected Editor will be provided the delegate by the Initializer visitor. + */ + ((RequestFactoryEditorDelegate<R, E>) getDelegate()).setRequestContext(saveRequest); doEdit(object); } @@ -192,8 +183,7 @@ doInitialize(null, null, editor); } - public void initialize(EventBus eventBus, RequestFactory requestFactory, - E editor) { + public void initialize(EventBus eventBus, RequestFactory requestFactory, E editor) { assert eventBus != null : "eventBus must not be null"; assert requestFactory != null : "requestFactory must not be null"; doInitialize(eventBus, requestFactory, editor); @@ -204,7 +194,8 @@ } @SuppressWarnings("deprecation") - public boolean setViolations(Iterable<com.google.web.bindery.requestfactory.shared.Violation> violations) { + public boolean setViolations( + Iterable<com.google.web.bindery.requestfactory.shared.Violation> violations) { return doSetViolations(new ViolationIterable(violations)); } @@ -216,12 +207,16 @@ @Override protected void configureDelegate(AbstractEditorDelegate<R, E> rootDelegate) { - ((RequestFactoryEditorDelegate<R, E>) rootDelegate).initialize(eventBus, - factory, "", getEditor()); + ((RequestFactoryEditorDelegate<R, E>) rootDelegate).initialize(eventBus, factory, "", + getEditor()); } - protected void doInitialize(EventBus eventBus, RequestFactory requestFactory, - E editor) { + @Override + protected EditorVisitor createInitializerVisitor() { + return new Initializer(saveRequest); + } + + protected void doInitialize(EventBus eventBus, RequestFactory requestFactory, E editor) { this.eventBus = eventBus; this.factory = requestFactory; super.doInitialize(editor);
diff --git a/user/src/com/google/web/bindery/requestfactory/gwt/client/impl/Initializer.java b/user/src/com/google/web/bindery/requestfactory/gwt/client/impl/Initializer.java new file mode 100644 index 0000000..8e43e36 --- /dev/null +++ b/user/src/com/google/web/bindery/requestfactory/gwt/client/impl/Initializer.java
@@ -0,0 +1,49 @@ +/* + * Copyright 2011 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.web.bindery.requestfactory.gwt.client.impl; + +import com.google.gwt.editor.client.Editor; +import com.google.gwt.editor.client.EditorContext; +import com.google.web.bindery.requestfactory.gwt.client.HasRequestContext; +import com.google.web.bindery.requestfactory.shared.RequestContext; + +/** + * Extension of standard Editor Initializer that provides the current + * RequestContext. + */ +class Initializer extends com.google.gwt.editor.client.impl.Initializer { + + private final RequestContext request; + + public Initializer(RequestContext request) { + this.request = request; + } + + @Override + public <T> boolean visit(EditorContext<T> ctx) { + RequestFactoryEditorDelegate<?, ?> delegate = + (RequestFactoryEditorDelegate<?, ?>) ctx.getEditorDelegate(); + if (delegate != null) { + delegate.setRequestContext(request); + } + Editor<T> editor = ctx.getEditor(); + if (editor instanceof HasRequestContext) { + ((HasRequestContext<T>) editor).setRequestContext(request); + } + + return super.visit(ctx); + } +}
diff --git a/user/src/com/google/web/bindery/requestfactory/gwt/client/impl/RequestFactoryEditorDelegate.java b/user/src/com/google/web/bindery/requestfactory/gwt/client/impl/RequestFactoryEditorDelegate.java index 0cf247a..4cbcf92 100644 --- a/user/src/com/google/web/bindery/requestfactory/gwt/client/impl/RequestFactoryEditorDelegate.java +++ b/user/src/com/google/web/bindery/requestfactory/gwt/client/impl/RequestFactoryEditorDelegate.java
@@ -16,9 +16,9 @@ package com.google.web.bindery.requestfactory.gwt.client.impl; import com.google.gwt.editor.client.Editor; +import com.google.gwt.editor.client.EditorVisitor; import com.google.gwt.editor.client.impl.AbstractEditorDelegate; import com.google.gwt.editor.client.impl.Refresher; -// This import is not an accident, details in subscribe() implementation import com.google.gwt.event.shared.HandlerRegistration; import com.google.web.bindery.event.shared.EventBus; import com.google.web.bindery.requestfactory.shared.BaseProxy; @@ -127,6 +127,11 @@ } @Override + protected EditorVisitor createInitializerVisitor() { + return new Initializer(request); + } + + @Override protected <T> T ensureMutable(T object) { if (request == null) { // Read-only mode
diff --git a/user/test/com/google/web/bindery/requestfactory/gwt/client/ui/EditorTest.java b/user/test/com/google/web/bindery/requestfactory/gwt/client/ui/EditorTest.java index 963b694..ec6987f 100644 --- a/user/test/com/google/web/bindery/requestfactory/gwt/client/ui/EditorTest.java +++ b/user/test/com/google/web/bindery/requestfactory/gwt/client/ui/EditorTest.java
@@ -61,12 +61,18 @@ } } - static class SimpleFooBarNameOnlyEditor implements Editor<SimpleFooProxy> { + static class SimpleFooBarNameOnlyEditor implements HasRequestContext<SimpleFooProxy> { + RequestContext ctx; + /** * Test nested path access. */ @Path("barField.userName") final SimpleEditor<String> barName = SimpleEditor.of(); + + public void setRequestContext(RequestContext ctx) { + this.ctx = ctx; + } } interface SimpleFooDriver extends RequestFactoryEditorDriver<SimpleFooProxy, SimpleFooEditor> { @@ -84,14 +90,6 @@ @Path("barField.userName") final SimpleEditor<String> barName = SimpleEditor.of(); - final ListEditor<SimpleFooProxy, SimpleFooBarNameOnlyEditor> selfOneToManyField = ListEditor - .of(new EditorSource<SimpleFooBarNameOnlyEditor>() { - @Override - public SimpleFooBarNameOnlyEditor create(int index) { - return new SimpleFooBarNameOnlyEditor(); - } - }); - private final SimpleBarEditor barEditor = new SimpleBarEditor(); List<EditorError> errors; @@ -118,6 +116,23 @@ } } + static class SimpleFooEditorWithList implements Editor<SimpleFooProxy> { + + final SimpleEditor<String> userName = SimpleEditor.of(); + + final ListEditor<SimpleFooProxy, SimpleFooBarNameOnlyEditor> selfOneToManyField = ListEditor + .of(new EditorSource<SimpleFooBarNameOnlyEditor>() { + @Override + public SimpleFooBarNameOnlyEditor create(int index) { + return new SimpleFooBarNameOnlyEditor(); + } + }); + } + + interface SimpleFooEditorWithListDriver extends + RequestFactoryEditorDriver<SimpleFooProxy, SimpleFooEditorWithList> { + } + private static final int TEST_TIMEOUT = 5000; @Override @@ -132,8 +147,7 @@ final SimpleFooDriver driver = GWT.create(SimpleFooDriver.class); driver.initialize(req, editor); final String[] paths = driver.getPaths(); - assertEquals(Arrays.asList("barField", "selfOneToManyField", "selfOneToManyField.barField"), - Arrays.asList(paths)); + assertEquals(Arrays.asList("barField"), Arrays.asList(paths)); req.simpleFooRequest().findSimpleFooById(1L).with(paths).fire(new Receiver<SimpleFooProxy>() { @Override @@ -157,8 +171,7 @@ editor.userName.setValue("EditorFooTest"); // When there are duplicate paths, last declared editor wins editor.barEditor().userName.setValue("EditorBarTest"); - editor.barName.setValue("ignored 1"); - editor.selfOneToManyField.getEditors().get(0).barName.setValue("ignored 2"); + editor.barName.setValue("ignored"); driver.flush().fire(); } }); @@ -211,6 +224,53 @@ }); } + /** + * Tests issues with {@code CompositeEditor}s when subeditors are dynamically + * created, such as with a {@link ListEditor}. + * + * @see http://code.google.com/p/google-web-toolkit/issues/detail?id=6081 + */ + public void testList() { + delayTestFinish(TEST_TIMEOUT); + final SimpleFooEditorWithList editor = new SimpleFooEditorWithList(); + + final SimpleFooEditorWithListDriver driver = GWT.create(SimpleFooEditorWithListDriver.class); + driver.initialize(req, editor); + + final String[] paths = driver.getPaths(); + assertEquals(Arrays.asList("selfOneToManyField", "selfOneToManyField.barField"), Arrays + .asList(paths)); + + req.simpleFooRequest().getSimpleFooWithSubPropertyCollection().with(paths).fire( + new Receiver<SimpleFooProxy>() { + @Override + public void onSuccess(SimpleFooProxy response) { + + SimpleFooRequest context = req.simpleFooRequest(); + driver.edit(response, context); + + SimpleFooBarNameOnlyEditor subeditor = editor.selfOneToManyField.getEditors().get(0); + // test context is correctly set in CompositeEditor subeditors + assertSame(context, subeditor.ctx); + + context.persistAndReturnSelf().using(response).with(paths).to( + new Receiver<SimpleFooProxy>() { + @Override + public void onSuccess(SimpleFooProxy response) { + assertEquals("EditorBarTest", response.getSelfOneToManyField().get(0) + .getBarField().getUserName()); + finishTestAndReset(); + } + }); + assertEquals("FOO", subeditor.barName.getValue()); + + subeditor.barName.setValue("EditorBarTest"); + + driver.flush().fire(); + } + }); + } + public void testNoSubscription() { final SimpleFooEditorWithDelegate editor = new SimpleFooEditorWithDelegate(); @@ -233,9 +293,9 @@ */ public void testReuse() { delayTestFinish(TEST_TIMEOUT); - final SimpleFooEditor editor = new SimpleFooEditor(); + final SimpleFooEditorWithList editor = new SimpleFooEditorWithList(); - final SimpleFooDriver driver = GWT.create(SimpleFooDriver.class); + final SimpleFooEditorWithListDriver driver = GWT.create(SimpleFooEditorWithListDriver.class); driver.initialize(req, editor); req.simpleFooRequest().findSimpleFooById(1L).with(driver.getPaths()).fire( @@ -272,8 +332,7 @@ driver.initialize(req, editor); String[] paths = driver.getPaths(); - assertEquals(Arrays.asList("barField", "selfOneToManyField", "selfOneToManyField.barField"), - Arrays.asList(paths)); + assertEquals(Arrays.asList("barField"), Arrays.asList(paths)); req.simpleFooRequest().findSimpleFooById(1L).with(paths).fire(new Receiver<SimpleFooProxy>() { @Override @@ -337,9 +396,11 @@ @SuppressWarnings("deprecation") @Override - public void onViolation(Set<com.google.web.bindery.requestfactory.shared.Violation> errors) { + public void onViolation( + Set<com.google.web.bindery.requestfactory.shared.Violation> errors) { assertEquals(1, errors.size()); - com.google.web.bindery.requestfactory.shared.Violation v = errors.iterator().next(); + com.google.web.bindery.requestfactory.shared.Violation v = + errors.iterator().next(); driver.setViolations(errors); assertEquals(1, editor.errors.size());