Revision: 8754
Author: [email protected]
Date: Fri Sep 10 12:29:13 2010
Log: Initial add of IsEditor interface to allow views to work in an Editor
hierarchy without being an Editor.
This patch will serve as a base for an error-aware Editor decorator panel.
Patch by: bobv
Review by: rjrjr
Review at http://gwt-code-reviews.appspot.com/858801
http://code.google.com/p/google-web-toolkit/source/detail?r=8754
Added:
/trunk/user/src/com/google/gwt/editor/client/IsEditor.java
Modified:
/trunk/user/src/com/google/gwt/editor/client/Editor.java
/trunk/user/src/com/google/gwt/editor/client/impl/AbstractEditorDelegate.java
/trunk/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java
/trunk/user/src/com/google/gwt/editor/rebind/model/EditorAccess.java
/trunk/user/src/com/google/gwt/editor/rebind/model/EditorModel.java
/trunk/user/test/com/google/gwt/editor/client/SimpleBeanEditorTest.java
/trunk/user/test/com/google/gwt/editor/rebind/model/EditorModelTest.java
=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/editor/client/IsEditor.java Fri Sep 10
12:29:13 2010
@@ -0,0 +1,34 @@
+/*
+ * 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.editor.client;
+
+/**
+ * Extended by view objects that wish to participate in an Editor
hierarchy, but
+ * that do not implement the {...@link Editor} contract directly.
+ * <p>
+ * It is legal for a type to implement both Editor and IsEditor. In this
case,
+ * the Editor returned from {...@link #asEditor()} will be a co-Editor of the
+ * IsEditor instance.
+ *
+ * @param <E> the type of Editor the view object will provide
+ * @see CompositeEditor
+ */
+public interface IsEditor<E extends Editor<?>> {
+ /**
+ * Returns the Editor encapsulated by the view object.
+ */
+ E asEditor();
+}
=======================================
--- /trunk/user/src/com/google/gwt/editor/client/Editor.java Thu Sep 2
10:32:07 2010
+++ /trunk/user/src/com/google/gwt/editor/client/Editor.java Fri Sep 10
12:29:13 2010
@@ -39,6 +39,10 @@
* <li>Sub-Editors may be null. In this case, the Editor framework will
ignore
* these sub-editors.</li>
* </ul>
+ * Any exposed field or method whose type is Editor may also use the
+ * {...@link IsEditor} interface to provide an Editor instance. This allows
view
+ * objects to be written that can be attached to an Editor hierarchy
without the
+ * view directly implementing an Editor interface.
*
* @param <T> the type of object the editor displays.
*/
=======================================
---
/trunk/user/src/com/google/gwt/editor/client/impl/AbstractEditorDelegate.java
Thu Sep 9 11:46:06 2010
+++
/trunk/user/src/com/google/gwt/editor/client/impl/AbstractEditorDelegate.java
Fri Sep 10 12:29:13 2010
@@ -97,8 +97,8 @@
if (getObject() == null) {
return;
}
- flushSubEditors();
setObject(ensureMutable(getObject()));
+ flushSubEditors();
flushValues();
}
=======================================
---
/trunk/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java
Thu Sep 9 11:46:06 2010
+++
/trunk/user/src/com/google/gwt/editor/rebind/AbstractEditorDriverGenerator.java
Fri Sep 10 12:29:13 2010
@@ -21,6 +21,7 @@
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
+import com.google.gwt.dev.generator.NameFactory;
import com.google.gwt.dev.util.Name;
import com.google.gwt.dev.util.Name.BinaryName;
import com.google.gwt.editor.rebind.model.EditorData;
@@ -29,7 +30,9 @@
import com.google.gwt.user.rebind.SourceWriter;
import java.io.PrintWriter;
+import java.util.IdentityHashMap;
import java.util.List;
+import java.util.Map;
/**
* A base class for generating Editor drivers.
@@ -85,6 +88,8 @@
protected String getEditorDelegate(EditorData delegateData) {
JClassType edited = delegateData.getEditedType();
JClassType editor = delegateData.getEditorType();
+ Map<EditorData, String> delegateFields = new
IdentityHashMap<EditorData, String>();
+ NameFactory nameFactory = new NameFactory();
/*
* The binary name of the edited type is included so that the same
editor
@@ -139,11 +144,14 @@
// Fields for the sub-delegates that must be managed
for (EditorData d : data) {
if (d.isBeanEditor() || d.isValueAwareEditor()) {
- sw.println("%s<%s, %s> %sDelegate;",
+ String fieldName = nameFactory.createName(d.getPropertyName()
+ + "Delegate");
+ delegateFields.put(d, fieldName);
+ sw.println("%s<%s, %s> %s;",
Name.getSourceNameForClass(getEditorDelegateType()),
d.getEditedType().getParameterizedQualifiedSourceName(),
d.getEditorType().getParameterizedQualifiedSourceName(),
- d.getPropertyName());
+ fieldName);
}
}
@@ -156,8 +164,7 @@
String subDelegateType = getEditorDelegate(d);
sw.println("if (editor.%s != null) {", d.getSimpleExpression());
sw.indent();
- sw.println("%sDelegate = new %s();", d.getPropertyName(),
- subDelegateType);
+ sw.println("%s = new %s();", delegateFields.get(d),
subDelegateType);
writeDelegateInitialization(sw, d);
sw.outdent();
sw.println("}");
@@ -171,13 +178,17 @@
sw.indent();
for (EditorData d : data) {
if (d.isBeanEditor() || d.isValueAwareEditor()) {
- sw.println("if (%1$sDelegate != null) { %1$sDelegate.flush();",
- d.getPropertyName());
+ sw.println("if (%1$s != null) { %1$s.flush();",
delegateFields.get(d));
if (d.getSetterName() != null) {
- String mutableObjectExpression =
mutableObjectExpression(String.format(
- "getObject()%s", d.getBeanOwnerExpression()));
- sw.println("%s.%s(%sDelegate.getObject());",
- mutableObjectExpression, d.getSetterName(),
d.getPropertyName());
+ String mutableObjectExpression;
+ if (d.getBeanOwnerExpression().length() > 0) {
+ mutableObjectExpression =
mutableObjectExpression(String.format(
+ "getObject()%s", d.getBeanOwnerExpression()));
+ } else {
+ mutableObjectExpression = "getObject()";
+ }
+ sw.println("%s.%s(%s.getObject());", mutableObjectExpression,
+ d.getSetterName(), delegateFields.get(d));
}
sw.println("}");
}
=======================================
--- /trunk/user/src/com/google/gwt/editor/rebind/model/EditorAccess.java
Thu Sep 9 11:46:06 2010
+++ /trunk/user/src/com/google/gwt/editor/rebind/model/EditorAccess.java
Fri Sep 10 12:29:13 2010
@@ -18,7 +18,10 @@
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JField;
import com.google.gwt.core.ext.typeinfo.JMethod;
+import com.google.gwt.core.ext.typeinfo.JType;
+import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.editor.client.Editor;
+import com.google.gwt.editor.client.IsEditor;
import com.google.gwt.editor.client.Editor.Path;
/**
@@ -30,6 +33,14 @@
public static EditorAccess root(JClassType rootType) {
return new EditorAccess("", rootType, "");
}
+
+ /**
+ * Constructs an EditorAccess for an IsEditor type.
+ */
+ public static EditorAccess via(EditorAccess access, JClassType type) {
+ return new EditorAccess(access.getPath(), type, access.getExpresson()
+ + ".asEditor()");
+ }
public static EditorAccess via(JField field) {
String path = field.getName();
@@ -57,6 +68,16 @@
method.getName() + "()");
}
+ private static boolean isEditor(JType type) {
+ JClassType classType = type.isClassOrInterface();
+ if (classType == null) {
+ return false;
+ }
+ TypeOracle oracle = classType.getOracle();
+ return
oracle.findType(IsEditor.class.getName()).isAssignableFrom(classType);
+ }
+
+ private final boolean isEditor;
private final String expression;
private final String path;
private final JClassType type;
@@ -65,6 +86,7 @@
this.expression = expression;
this.path = path;
this.type = type;
+ isEditor = isEditor(type);
}
public JClassType getEditorType() {
@@ -78,6 +100,14 @@
public String getPath() {
return path;
}
+
+ /**
+ * Returns <code> true if the editor accessed by this EditorAccess
+ * implements the IsEditor interface.
+ */
+ public boolean isEditor() {
+ return isEditor;
+ }
/**
* For debugging use only.
=======================================
--- /trunk/user/src/com/google/gwt/editor/rebind/model/EditorModel.java Thu
Sep 9 11:46:06 2010
+++ /trunk/user/src/com/google/gwt/editor/rebind/model/EditorModel.java Fri
Sep 10 12:29:13 2010
@@ -27,6 +27,7 @@
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.editor.client.CompositeEditor;
import com.google.gwt.editor.client.Editor;
+import com.google.gwt.editor.client.IsEditor;
import java.util.ArrayList;
import java.util.Arrays;
@@ -77,18 +78,29 @@
throws UnableToCompleteException {
JClassType editorIntf = editorType.getOracle().findType(
Editor.class.getName());
- assert editorIntf.isAssignableFrom(editorType) :
editorType.getQualifiedSourceName()
- + " is not an Editor";
-
- for (JClassType supertype :
editorType.getFlattenedSupertypeHierarchy()) {
- JParameterizedType parameterized = supertype.isParameterized();
- if (parameterized != null) {
- // Found the Editor<Foo> supertype
- if (editorIntf.equals(parameterized.getBaseType())) {
- assert parameterized.getTypeArgs().length == 1;
- return parameterized.getTypeArgs()[0].isClassOrInterface();
- }
- }
+ JClassType parameterization[] = findParameterizationOf(editorIntf,
+ editorType);
+ if (parameterization != null) {
+ return parameterization[0];
+ }
+ logger.log(TreeLogger.ERROR,
noEditorParameterizationMessage(editorIntf,
+ editorType));
+ throw new UnableToCompleteException();
+ }
+
+ /**
+ * Given type assignable to <code>IsEditor<Foo, FooEditor></code>,
return
+ * <code>FooEditor</code>. It is an error to call this method with a
type not
+ * assignable to {...@link IsEditor}.
+ */
+ static JClassType calculateIsEditedType(TreeLogger logger,
+ JClassType editorType) throws UnableToCompleteException {
+ JClassType editorIntf = editorType.getOracle().findType(
+ IsEditor.class.getName());
+ JClassType[] parameterization = findParameterizationOf(editorIntf,
+ editorType);
+ if (parameterization != null) {
+ return parameterization[0];
}
logger.log(TreeLogger.ERROR,
noEditorParameterizationMessage(editorIntf,
editorType));
@@ -142,6 +154,25 @@
return String.format("Unexpected input type: %s is not assignable
from %s",
driverType.getQualifiedSourceName(),
intf.getQualifiedSourceName());
}
+
+ private static JClassType[] findParameterizationOf(JClassType intfType,
+ JClassType subType) {
+ assert intfType.isAssignableFrom(subType) :
subType.getParameterizedQualifiedSourceName()
+ + " is not assignable to "
+ + subType.getParameterizedQualifiedSourceName();
+
+ for (JClassType supertype : subType.getFlattenedSupertypeHierarchy()) {
+ JParameterizedType parameterized = supertype.isParameterized();
+ if (parameterized != null) {
+ // Found the desired supertype
+ if (intfType.equals(parameterized.getBaseType())) {
+ assert parameterized.getTypeArgs().length == 1;
+ return parameterized.getTypeArgs();
+ }
+ }
+ }
+ return null;
+ }
/**
* The structural model.
@@ -156,6 +187,11 @@
private final EditorData editorSoFar;
+ /**
+ * A reference to {...@link IsEditor}.
+ */
+ private final JGenericType isEditorIntf;
+
private final TreeLogger logger;
private final EditorModel parentModel;
@@ -193,6 +229,8 @@
TypeOracle oracle = intf.getOracle();
editorIntf = oracle.findType(Editor.class.getName()).isGenericType();
assert editorIntf != null : "No Editor type";
+ isEditorIntf =
oracle.findType(IsEditor.class.getName()).isGenericType();
+ assert isEditorIntf != null : "No IsEditor type";
JClassType[] interfaces = intf.getImplementedInterfaces();
if (interfaces.length != 1) {
@@ -218,6 +256,7 @@
this.editorIntf = parent.editorIntf;
this.editorType = editorType;
this.editorSoFar = subEditor;
+ this.isEditorIntf = parent.isEditorIntf;
this.parentModel = parent;
this.proxyType = proxyType;
this.typeData = parent.typeData;
@@ -266,14 +305,15 @@
if (field.isPrivate() || field.isStatic()) {
continue;
}
- JClassType fieldClassType = field.getType().isClassOrInterface();
- if (fieldClassType != null
- && editorIntf.isAssignableFrom(fieldClassType)) {
- EditorData data = createEditorData(EditorAccess.via(field));
- flatData.add(data);
- toReturn.add(data);
- if (!data.isLeafValueEditor()) {
- descendIntoSubEditor(toReturn, data);
+ JType fieldClassType = field.getType();
+ if (shouldExamine(fieldClassType)) {
+ List<EditorData> data =
createEditorData(EditorAccess.via(field));
+ flatData.addAll(data);
+ toReturn.addAll(data);
+ for (EditorData d : data) {
+ if (!d.isLeafValueEditor()) {
+ descendIntoSubEditor(toReturn, d);
+ }
}
}
}
@@ -281,15 +321,22 @@
if (method.isPrivate() || method.isStatic()) {
continue;
}
- JClassType methodReturnType =
method.getReturnType().isClassOrInterface();
- if (methodReturnType != null
- && editorIntf.isAssignableFrom(methodReturnType)
+ JType methodReturnType = method.getReturnType();
+ if (shouldExamine(methodReturnType)
&& method.getParameters().length == 0) {
- EditorData data = createEditorData(EditorAccess.via(method));
- flatData.add(data);
- toReturn.add(data);
- if (!data.isLeafValueEditor()) {
- descendIntoSubEditor(toReturn, data);
+ EditorAccess access = EditorAccess.via(method);
+ if (access.getPath().equals("as")
+ && isEditorIntf.isAssignableFrom(editorType)) {
+ // Ignore IsEditor.asEditor()
+ continue;
+ }
+ List<EditorData> data = createEditorData(access);
+ flatData.addAll(data);
+ toReturn.addAll(data);
+ for (EditorData d : data) {
+ if (!d.isLeafValueEditor()) {
+ descendIntoSubEditor(toReturn, d);
+ }
}
}
}
@@ -310,10 +357,25 @@
return sb.toString();
}
- private EditorData createEditorData(EditorAccess access)
+ private List<EditorData> createEditorData(EditorAccess access)
throws UnableToCompleteException {
TreeLogger subLogger = logger.branch(TreeLogger.DEBUG, "Examining "
+ access.toString());
+
+ List<EditorData> toReturn = new ArrayList<EditorData>();
+
+ // Are we looking at a view that implements IsEditor?
+ if (access.isEditor()) {
+ EditorAccess subAccess = EditorAccess.via(access,
calculateIsEditedType(
+ subLogger, access.getEditorType()));
+ toReturn = createEditorData(subAccess);
+
+ // If an object only implements IsEditor, return now
+ if (!editorIntf.isAssignableFrom(access.getEditorType())) {
+ return toReturn;
+ }
+ }
+
// Determine the Foo in Editor<Foo>
JClassType expectedToEdit = calculateEditedType(subLogger,
access.getEditorType());
@@ -322,8 +384,10 @@
String[] methods = findBeanPropertyMethods(access.getPath(),
expectedToEdit);
assert methods.length == 3;
- return new EditorData(subLogger, editorSoFar, access, methods[0],
- methods[1], methods[2]);
+ EditorData data = new EditorData(subLogger, editorSoFar, access,
+ methods[0], methods[1], methods[2]);
+ toReturn.add(data);
+ return toReturn;
}
/**
@@ -347,7 +411,8 @@
if (!data.isLeafValueEditor()) {
EditorModel subModel = new EditorModel(this, data.getEditorType(),
data,
calculateEditedType(logger, data.getEditorType()));
- accumulator.addAll(Arrays.asList(subModel.getEditorData()));
+ accumulator.addAll(accumulator.indexOf(data) + 1,
+ Arrays.asList(subModel.getEditorData()));
poisoned |= subModel.poisoned;
}
}
@@ -431,4 +496,17 @@
logger.log(TreeLogger.ERROR, message);
poisoned = true;
}
-}
+
+ /**
+ * Returns <code>true</code> if the given type participates in Editor
+ * hierarchies.
+ */
+ private boolean shouldExamine(JType type) {
+ JClassType classType = type.isClassOrInterface();
+ if (classType == null) {
+ return false;
+ }
+ return editorIntf.isAssignableFrom(classType)
+ || isEditorIntf.isAssignableFrom(classType);
+ }
+}
=======================================
--- /trunk/user/test/com/google/gwt/editor/client/SimpleBeanEditorTest.java
Thu Sep 9 11:46:06 2010
+++ /trunk/user/test/com/google/gwt/editor/client/SimpleBeanEditorTest.java
Fri Sep 10 12:29:13 2010
@@ -60,6 +60,23 @@
SimpleEditor<String> city = SimpleEditor.of(UNINITIALIZED);
SimpleEditor<String> street = SimpleEditor.of(UNINITIALIZED);
}
+
+ class AddressCoEditorView extends LeafAddressEditor implements
+ IsEditor<LeafAddressEditor> {
+ private LeafAddressEditor addressEditor = new LeafAddressEditor();
+
+ public LeafAddressEditor asEditor() {
+ return addressEditor;
+ }
+ }
+
+ class AddressEditorView implements IsEditor<LeafAddressEditor> {
+ LeafAddressEditor addressEditor = new LeafAddressEditor();
+
+ public LeafAddressEditor asEditor() {
+ return addressEditor;
+ }
+ }
class LeafAddressEditor extends AddressEditor implements
LeafValueEditor<Address> {
@@ -127,6 +144,24 @@
interface PersonEditorDriver extends
SimpleBeanEditorDriver<Person, PersonEditor> {
}
+
+ class PersonEditorWithAddressEditorView implements Editor<Person> {
+ AddressEditorView addressEditor = new AddressEditorView();
+ SimpleEditor<String> name = SimpleEditor.of(UNINITIALIZED);
+ }
+
+ interface PersonEditorWithAddressEditorViewDriver extends
+ SimpleBeanEditorDriver<Person, PersonEditorWithAddressEditorView> {
+ }
+
+ class PersonEditorWithCoAddressEditorView implements Editor<Person> {
+ AddressCoEditorView addressEditor = new AddressCoEditorView();
+ SimpleEditor<String> name = SimpleEditor.of(UNINITIALIZED);
+ }
+
+ interface PersonEditorWithCoAddressEditorViewDriver extends
+ SimpleBeanEditorDriver<Person, PersonEditorWithCoAddressEditorView> {
+ }
class PersonEditorWithLeafAddressEditor implements Editor<Person> {
LeafAddressEditor addressEditor = new LeafAddressEditor();
@@ -244,6 +279,38 @@
assertEquals("12345", person.address.street);
assertEquals("David", person.manager.name);
}
+
+ /**
+ * Test the use of the IsEditor interface that allows a view object to
+ * encapsulate its Editor.
+ */
+ public void testIsEditorView() {
+ PersonEditorWithAddressEditorView personEditor = new
PersonEditorWithAddressEditorView();
+ PersonEditorWithAddressEditorViewDriver driver =
GWT.create(PersonEditorWithAddressEditorViewDriver.class);
+ testLeafAddressEditor(driver, personEditor,
+ personEditor.addressEditor.asEditor());
+ }
+
+ /**
+ * Test the use of the IsEditor interface that allows a view object to
+ * encapsulate its Editor as well as be an editor itself.
+ */
+ public void testIsEditorViewWithCoEditorA() {
+ PersonEditorWithCoAddressEditorView personEditor = new
PersonEditorWithCoAddressEditorView();
+ PersonEditorWithCoAddressEditorViewDriver driver =
GWT.create(PersonEditorWithCoAddressEditorViewDriver.class);
+ testLeafAddressEditor(driver, personEditor,
personEditor.addressEditor);
+ }
+
+ /**
+ * Test the use of the IsEditor interface that allows a view object to
+ * encapsulate its Editor as well as be an editor itself.
+ */
+ public void testIsEditorViewWithCoEditorB() {
+ PersonEditorWithCoAddressEditorView personEditor = new
PersonEditorWithCoAddressEditorView();
+ PersonEditorWithCoAddressEditorViewDriver driver =
GWT.create(PersonEditorWithCoAddressEditorViewDriver.class);
+ testLeafAddressEditor(driver, personEditor,
+ personEditor.addressEditor.asEditor());
+ }
/**
* We want to verify that the sub-editors of a LeafValueEditor are not
@@ -359,6 +426,14 @@
assertEquals(editors, new ArrayList<SimpleEditor<String>>(
positionMap.values()));
}
+
+ public void testValueAwareEditorInDeclaredSlot() {
+ PersonEditorWithValueAwareAddressEditorDriver driver =
GWT.create(PersonEditorWithValueAwareAddressEditorDriver.class);
+ PersonEditorWithValueAwareAddressEditor personEditor = new
PersonEditorWithValueAwareAddressEditor();
+ ValueAwareAddressEditor addressEditor = personEditor.addressEditor;
+
+ testValueAwareAddressEditor(driver, personEditor, addressEditor);
+ }
public void testValueAwareEditorInPlainSlot() {
PersonEditorDriver driver = GWT.create(PersonEditorDriver.class);
@@ -371,14 +446,6 @@
testValueAwareAddressEditor(driver, personEditor, addressEditor);
}
-
- public void testValueAwareEditorInDeclaredSlot() {
- PersonEditorWithValueAwareAddressEditorDriver driver =
GWT.create(PersonEditorWithValueAwareAddressEditorDriver.class);
- PersonEditorWithValueAwareAddressEditor personEditor = new
PersonEditorWithValueAwareAddressEditor();
- ValueAwareAddressEditor addressEditor = personEditor.addressEditor;
-
- testValueAwareAddressEditor(driver, personEditor, addressEditor);
- }
public void testValueAwareLeafValueEditorInDeclaredSlot() {
PersonEditorWithValueAwareLeafAddressEditor personEditor = new
PersonEditorWithValueAwareLeafAddressEditor();
@@ -419,52 +486,52 @@
person.manager = manager;
}
- private <T extends Editor<Person>> void testValueAwareAddressEditor(
+ private <T extends Editor<Person>> void testLeafAddressEditor(
SimpleBeanEditorDriver<Person, T> driver, T personEditor,
- ValueAwareAddressEditor addressEditor) {
+ LeafAddressEditor addressEditor) {
Address oldAddress = person.address;
// Initialize
driver.initialize(personEditor);
assertEquals(0, addressEditor.setValueCalled);
- assertEquals(0, addressEditor.setDelegateCalled);
- assertEquals(0, addressEditor.flushCalled);
+ assertEquals(0, addressEditor.getValueCalled);
// Edit
driver.edit(person);
assertEquals(1, addressEditor.setValueCalled);
- assertEquals(1, addressEditor.setDelegateCalled);
- assertEquals(0, addressEditor.flushCalled);
- assertEquals("City", addressEditor.city.getValue());
+ assertEquals(0, addressEditor.getValueCalled);
+ assertEquals(UNINITIALIZED, addressEditor.city.getValue());
// Flush
driver.flush();
assertEquals(1, addressEditor.setValueCalled);
- assertEquals(1, addressEditor.setDelegateCalled);
- assertEquals(1, addressEditor.flushCalled);
- assertSame(oldAddress, person.address);
+ assertEquals(1, addressEditor.getValueCalled);
+ assertNotSame(oldAddress, person.address);
assertSame(person.address, addressEditor.value);
}
- private <T extends Editor<Person>> void testLeafAddressEditor(
+ private <T extends Editor<Person>> void testValueAwareAddressEditor(
SimpleBeanEditorDriver<Person, T> driver, T personEditor,
- LeafAddressEditor addressEditor) {
+ ValueAwareAddressEditor addressEditor) {
Address oldAddress = person.address;
// Initialize
driver.initialize(personEditor);
assertEquals(0, addressEditor.setValueCalled);
- assertEquals(0, addressEditor.getValueCalled);
+ assertEquals(0, addressEditor.setDelegateCalled);
+ assertEquals(0, addressEditor.flushCalled);
// Edit
driver.edit(person);
assertEquals(1, addressEditor.setValueCalled);
- assertEquals(0, addressEditor.getValueCalled);
- assertEquals(UNINITIALIZED, addressEditor.city.getValue());
+ assertEquals(1, addressEditor.setDelegateCalled);
+ assertEquals(0, addressEditor.flushCalled);
+ assertEquals("City", addressEditor.city.getValue());
// Flush
driver.flush();
assertEquals(1, addressEditor.setValueCalled);
- assertEquals(1, addressEditor.getValueCalled);
- assertNotSame(oldAddress, person.address);
+ assertEquals(1, addressEditor.setDelegateCalled);
+ assertEquals(1, addressEditor.flushCalled);
+ assertSame(oldAddress, person.address);
assertSame(person.address, addressEditor.value);
}
}
=======================================
---
/trunk/user/test/com/google/gwt/editor/rebind/model/EditorModelTest.java
Thu Sep 9 11:46:06 2010
+++
/trunk/user/test/com/google/gwt/editor/rebind/model/EditorModelTest.java
Fri Sep 10 12:29:13 2010
@@ -29,6 +29,7 @@
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
import com.google.gwt.editor.client.CompositeEditor;
import com.google.gwt.editor.client.Editor;
+import com.google.gwt.editor.client.IsEditor;
import com.google.gwt.editor.client.LeafValueEditor;
import com.google.gwt.editor.client.ValueAwareEditor;
import com.google.gwt.editor.client.adapters.SimpleEditor;
@@ -236,6 +237,44 @@
assertEquals("city", address[0].getPropertyName());
assertEquals("street", address[1].getPropertyName());
}
+
+ /**
+ * Tests a plain IsEditor that allows the editor instance to be swapped
in by
+ * a view object.
+ */
+ public void testIsEditor() throws UnableToCompleteException {
+ EditorModel m = new EditorModel(logger,
+ types.findType("t.UsesIsEditorDriver"), rfedType);
+
+ EditorData[] data = m.getEditorData();
+ assertNotNull(data);
+ assertEquals(2, data.length);
+ assertEquals(Arrays.asList("b", "b.string"), Arrays.asList(
+ data[0].getPath(), data[1].getPath()));
+ assertEquals(Arrays.asList("bEditor().asEditor()", "stringEditor()"),
+ Arrays.asList(data[0].getSimpleExpression(),
+ data[1].getSimpleExpression()));
+ }
+
+ /**
+ * Tests the case where an IsEditor also implements the Editor interface.
+ */
+ public void testIsEditorAndEditor() throws UnableToCompleteException {
+ EditorModel m = new EditorModel(logger,
+ types.findType("t.UsesIsEditorAndEditorDriver"), rfedType);
+
+ EditorData[] data = m.getEditorData();
+ assertNotNull(data);
+ assertEquals(4, data.length);
+ assertEquals(Arrays.asList("b", "b.string", "b", "b.string"),
+ Arrays.asList(data[0].getPath(), data[1].getPath(),
data[2].getPath(),
+ data[3].getPath()));
+ assertEquals(Arrays.asList("bEditor().asEditor()",
+ "bEditor().asEditor().coEditor()", "bEditor()",
+ "bEditor().viewEditor()"), Arrays.asList(data[0].getExpression(),
+ data[1].getExpression(), data[2].getExpression(),
+ data[3].getExpression()));
+ }
public void testListDriver() throws UnableToCompleteException {
EditorModel m = new EditorModel(logger,
@@ -628,6 +667,64 @@
code.append("}");
return code;
}
+ }, new MockJavaResource("t.UsesIsEditorDriver") {
+ // Tests error-detection when the editor structure doesn't match the
proxy
+ @Override
+ protected CharSequence getContent() {
+ StringBuilder code = new StringBuilder();
+ code.append("package t;\n");
+ code.append("import " + Editor.class.getName() + ";\n");
+ code.append("import " + IsEditor.class.getName() + ";\n");
+ code.append("import " + EntityProxy.class.getName() + ";\n");
+ code.append("import " + RequestFactoryEditorDriver.class.getName()
+ + ";\n");
+ code.append("import " + SimpleEditor.class.getName() + ";\n");
+ code.append("interface UsesIsEditorDriver extends"
+ + " RequestFactoryEditorDriver<UsesIsEditorDriver.AProxy,"
+ + " UsesIsEditorDriver.AEditor> {\n");
+ code.append(" interface AProxy extends EntityProxy { BProxy
getB();}");
+ code.append(" interface BProxy extends EntityProxy { String
getString();}");
+ code.append(" interface AEditor extends Editor<AProxy> {");
+ code.append(" BView bEditor();");
+ code.append(" }");
+ code.append(" interface BView extends IsEditor<BEditor> {");
+ code.append(" @Editor.Path(\"string\") BEditor unseen();");
+ code.append(" }");
+ code.append(" interface BEditor extends Editor<BProxy> {");
+ code.append(" SimpleEditor<String> stringEditor();");
+ code.append(" }");
+ code.append("}");
+ return code;
+ }
+ }, new MockJavaResource("t.UsesIsEditorAndEditorDriver") {
+ // Tests error-detection when the editor structure doesn't match the
proxy
+ @Override
+ protected CharSequence getContent() {
+ StringBuilder code = new StringBuilder();
+ code.append("package t;\n");
+ code.append("import " + Editor.class.getName() + ";\n");
+ code.append("import " + IsEditor.class.getName() + ";\n");
+ code.append("import " + EntityProxy.class.getName() + ";\n");
+ code.append("import " + RequestFactoryEditorDriver.class.getName()
+ + ";\n");
+ code.append("import " + SimpleEditor.class.getName() + ";\n");
+ code.append("interface UsesIsEditorAndEditorDriver extends"
+ + "
RequestFactoryEditorDriver<UsesIsEditorAndEditorDriver.AProxy,"
+ + " UsesIsEditorAndEditorDriver.AEditor> {\n");
+ code.append(" interface AProxy extends EntityProxy { BProxy
getB();}");
+ code.append(" interface BProxy extends EntityProxy { String
getString();}");
+ code.append(" interface AEditor extends Editor<AProxy> {");
+ code.append(" BView bEditor();");
+ code.append(" }");
+ code.append(" interface BView extends IsEditor<BEditor>,
Editor<BProxy> {");
+ code.append(" @Editor.Path(\"string\") SimpleEditor<String>
viewEditor();");
+ code.append(" }");
+ code.append(" interface BEditor extends Editor<BProxy> {");
+ code.append(" @Editor.Path(\"string\") SimpleEditor<String>
coEditor();");
+ code.append(" }");
+ code.append("}");
+ return code;
+ }
}, new MockJavaResource("java.util.List") {
// Tests a Driver interface that extends more than RFED
@Override
@@ -646,6 +743,7 @@
new RealJavaResource(Editor.class),
new EmptyMockJavaResource(EventBus.class),
new RealJavaResource(HasText.class),
+ new RealJavaResource(IsEditor.class),
new RealJavaResource(LeafValueEditor.class),
new EmptyMockJavaResource(Property.class),
new EmptyMockJavaResource(EntityProxy.class),
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors