Revision: 9607
Author: gwt.mirror...@gmail.com
Date: Tue Jan 25 08:47:13 2011
Log: Allow Editor framework to handle primitive types.
Issue 5864.
Patch by: bobv
Review by: rjrjr
Review at http://gwt-code-reviews.appspot.com/1312802
http://code.google.com/p/google-web-toolkit/source/detail?r=9607
Modified:
/trunk/user/src/com/google/gwt/editor/rebind/model/EditorModel.java
/trunk/user/test/com/google/gwt/editor/client/Person.java
/trunk/user/test/com/google/gwt/editor/client/PersonEditor.java
/trunk/user/test/com/google/gwt/editor/client/SimpleBeanEditorTest.java
/trunk/user/test/com/google/gwt/editor/rebind/model/EditorModelTest.java
=======================================
--- /trunk/user/src/com/google/gwt/editor/rebind/model/EditorModel.java Fri
Jan 14 08:57:14 2011
+++ /trunk/user/src/com/google/gwt/editor/rebind/model/EditorModel.java Tue
Jan 25 08:47:13 2011
@@ -180,6 +180,8 @@
private final TreeLogger logger;
+ private final TypeOracle oracle;
+
private final EditorModel parentModel;
private boolean poisoned;
@@ -212,7 +214,7 @@
die(mustExtendMessage(driverType));
}
- TypeOracle oracle = intf.getOracle();
+ oracle = intf.getOracle();
editorIntf = oracle.findType(Editor.class.getName()).isGenericType();
assert editorIntf != null : "No Editor type";
isEditorIntf =
oracle.findType(IsEditor.class.getName()).isGenericType();
@@ -250,6 +252,7 @@
this.editorSoFar = subEditor;
this.isEditorIntf = parent.isEditorIntf;
this.leafValueEditorIntf = parent.leafValueEditorIntf;
+ this.oracle = parent.oracle;
this.parentModel = parent;
this.proxyType = proxyType;
this.typeData = parent.typeData;
@@ -467,6 +470,7 @@
if (parts[i].length() == 0) {
continue;
}
+ boolean lastPart = i == j - 1;
String getterName = camelCase("get", parts[i]);
for (JClassType search : lookingAt.getFlattenedSupertypeHierarchy())
{
@@ -475,12 +479,19 @@
for (JMethod maybeSetter : search.getOverloads(camelCase("set",
parts[i]))) {
if (maybeSetter.getReturnType().equals(JPrimitiveType.VOID)
- && maybeSetter.getParameters().length == 1
- &&
maybeSetter.getParameters()[0].getType().isClassOrInterface() != null
- &&
maybeSetter.getParameters()[0].getType().isClassOrInterface().isAssignableFrom(
- propertyType)) {
- setterName = maybeSetter.getName();
- break;
+ && maybeSetter.getParameters().length == 1) {
+ JType setterParamType =
maybeSetter.getParameters()[0].getType();
+ // Handle the case of setFoo(int) vs. Editor<Integer>
+ if (setterParamType.isPrimitive() != null) {
+ // Replace the int with Integer
+ setterParamType =
oracle.findType(setterParamType.isPrimitive().getQualifiedBoxedSourceName());
+ }
+ boolean matches =
setterParamType.isClassOrInterface().isAssignableFrom(
+ propertyType);
+ if (matches) {
+ setterName = maybeSetter.getName();
+ break;
+ }
}
}
}
@@ -489,7 +500,7 @@
if (getter != null) {
JType returnType = getter.getReturnType();
lookingAt = returnType.isClassOrInterface();
- if (lookingAt == null) {
+ if (!lastPart && lookingAt == null) {
poison(foundPrimitiveMessage(returnType,
interstitialGetters.toString(), path));
return;
=======================================
--- /trunk/user/test/com/google/gwt/editor/client/Person.java Mon Sep 13
09:30:34 2010
+++ /trunk/user/test/com/google/gwt/editor/client/Person.java Tue Jan 25
08:47:13 2011
@@ -19,13 +19,18 @@
* Simple data object used by multiple tests.
*/
public class Person {
- String name;
Address address;
Person manager;
+ String name;
+ long localTime;
public Address getAddress() {
return address;
}
+
+ public long getLocalTime() {
+ return localTime;
+ }
public Person getManager() {
return manager;
@@ -38,6 +43,10 @@
public void setAddress(Address address) {
this.address = address;
}
+
+ public void setLocalTime(long localTime) {
+ this.localTime = localTime;
+ }
public void setManager(Person manager) {
this.manager = manager;
=======================================
--- /trunk/user/test/com/google/gwt/editor/client/PersonEditor.java Wed Sep
15 02:26:39 2010
+++ /trunk/user/test/com/google/gwt/editor/client/PersonEditor.java Tue Jan
25 08:47:13 2011
@@ -22,6 +22,7 @@
*/
class PersonEditor implements Editor<Person> {
public AddressEditor addressEditor = new AddressEditor();
+ public SimpleEditor<Long> localTime =
SimpleEditor.of(System.currentTimeMillis());
public SimpleEditor<String> name =
SimpleEditor.of(SimpleBeanEditorTest.UNINITIALIZED);
@Path("manager.name")
public SimpleEditor<String> managerName =
SimpleEditor.of(SimpleBeanEditorTest.UNINITIALIZED);
=======================================
--- /trunk/user/test/com/google/gwt/editor/client/SimpleBeanEditorTest.java
Thu Jan 20 05:44:43 2011
+++ /trunk/user/test/com/google/gwt/editor/client/SimpleBeanEditorTest.java
Tue Jan 25 08:47:13 2011
@@ -267,6 +267,8 @@
static final String UNINITIALIZED = "uninitialized";
+ long now;
+
@Override
public String getModuleName() {
return "com.google.gwt.editor.Editor";
@@ -277,17 +279,20 @@
PersonEditor editor = new PersonEditor();
driver.initialize(editor);
driver.edit(person);
+ assertEquals(now, editor.localTime.getValue().longValue());
assertEquals("Alice", editor.name.getValue());
assertEquals("City", editor.addressEditor.city.getValue());
assertEquals("Street", editor.addressEditor.street.getValue());
assertEquals("Bill", editor.managerName.getValue());
+ editor.localTime.setValue(now + 1);
editor.name.setValue("Charles");
editor.addressEditor.city.setValue("Wootville");
editor.addressEditor.street.setValue("12345");
editor.managerName.setValue("David");
driver.flush();
+ assertEquals(now + 1, person.localTime);
assertEquals("Charles", person.name);
assertEquals("Wootville", person.address.city);
assertEquals("12345", person.address.street);
@@ -354,7 +359,7 @@
// Use the delegate to toggle the state
editor.delegate.setDirty(true);
assertTrue(driver.isDirty());
-
+
// Use the delegate to clear the state
editor.delegate.setDirty(false);
assertFalse(driver.isDirty());
@@ -370,23 +375,25 @@
public void testDirtyWithOptionalEditor() {
AddressEditor addressEditor = new AddressEditor();
- PersonEditorWithOptionalAddressEditor editor = new
PersonEditorWithOptionalAddressEditor(addressEditor);
+ PersonEditorWithOptionalAddressEditor editor = new
PersonEditorWithOptionalAddressEditor(
+ addressEditor);
PersonEditorWithOptionalAddressDriver driver =
GWT.create(PersonEditorWithOptionalAddressDriver.class);
driver.initialize(editor);
driver.edit(person);
-
+
// Freshly-initialized should not be dirty
assertFalse(driver.isDirty());
-
+
// Change the instance being edited
Address a = new Address();
editor.address.setValue(a);
assertTrue(driver.isDirty());
-
+
// Check restoration works
editor.address.setValue(personAddress);
assertFalse(driver.isDirty());
}
+
/**
* Test the use of the IsEditor interface that allows a view object to
* encapsulate its Editor.
@@ -677,6 +684,7 @@
person.address = personAddress;
person.name = "Alice";
person.manager = manager;
+ person.localTime = now = System.currentTimeMillis();
}
private <T extends Editor<Person>> void testLeafAddressEditor(
=======================================
---
/trunk/user/test/com/google/gwt/editor/rebind/model/EditorModelTest.java
Tue Jan 18 08:32:58 2011
+++
/trunk/user/test/com/google/gwt/editor/rebind/model/EditorModelTest.java
Tue Jan 25 08:47:13 2011
@@ -18,6 +18,7 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.javac.CompilationState;
import com.google.gwt.dev.javac.CompilationStateBuilder;
@@ -185,7 +186,7 @@
types.findType("t.CompositeEditorDriver"), rfedType);
EditorData[] data = m.getEditorData();
- assertEquals(6, data.length);
+ assertEquals(7, data.length);
String[] paths = new String[data.length];
String[] expressions = new String[data.length];
@@ -194,17 +195,19 @@
expressions[i] = data[i].getExpression();
}
assertEquals(Arrays.asList("address", "address.city", "address.street",
- "person", "person.name", "person.readonly"), Arrays.asList(paths));
+ "person", "person.lastModified", "person.name", "person.readonly"),
+ Arrays.asList(paths));
// address is a property, person is a method in CompositeEditor
assertEquals(Arrays.asList("address", "address.city", "address.street",
- "person()", "person().name", "person().readonly"),
- Arrays.asList(expressions));
+ "person()", "person().lastModified", "person().name",
+ "person().readonly"), Arrays.asList(expressions));
assertTrue(data[0].isDelegateRequired());
assertFalse(data[0].isLeafValueEditor() ||
data[0].isValueAwareEditor());
assertTrue(data[3].isDelegateRequired());
assertFalse(data[3].isLeafValueEditor() ||
data[3].isValueAwareEditor());
- checkPersonName(data[4]);
- checkPersonReadonly(data[5]);
+ checkPersonLastModified(data[4]);
+ checkPersonName(data[5]);
+ checkPersonReadonly(data[6]);
}
public void testCyclicDriver() {
@@ -254,12 +257,14 @@
EditorModel m = new EditorModel(logger,
types.findType("t.PersonEditorDriver"), rfedType);
EditorData[] fields = m.getEditorData();
- assertEquals(2, fields.length);
-
+ assertEquals(3, fields.length);
+
+ // lastModified
+ checkPersonLastModified(fields[0]);
// name
- checkPersonName(fields[0]);
+ checkPersonName(fields[1]);
// readonly
- checkPersonReadonly(fields[1]);
+ checkPersonReadonly(fields[2]);
}
public void testFlatData() throws UnableToCompleteException {
@@ -275,9 +280,10 @@
assertEquals("person", composite[1].getPropertyName());
EditorData[] person =
m.getEditorData(types.findType("t.PersonEditor"));
- assertEquals(2, person.length);
- assertEquals("name", person[0].getPropertyName());
- assertEquals("readonly", person[1].getPropertyName());
+ assertEquals(3, person.length);
+ assertEquals("lastModified", person[0].getPropertyName());
+ assertEquals("name", person[1].getPropertyName());
+ assertEquals("readonly", person[2].getPropertyName());
EditorData[] address =
m.getEditorData(types.findType("t.AddressEditor"));
assertEquals("city", address[0].getPropertyName());
@@ -401,6 +407,9 @@
builder.expectError(
EditorModel.tooManyInterfacesMessage(types.findType("t.TooManyInterfacesEditorDriver")),
null);
+
builder.expectError(EditorModel.foundPrimitiveMessage(JPrimitiveType.LONG,
+ "", "lastModified.foo"), null);
+ builder.expectError(EditorModel.poisonedMessage(), null);
UnitTestTreeLogger testLogger = builder.createLogger();
try {
@@ -419,6 +428,13 @@
fail("Should have thrown exception");
} catch (UnableToCompleteException expected) {
}
+ try {
+ new EditorModel(testLogger,
+ types.findType("t.PersonEditorWithBadPrimitiveAccessDriver"),
+ rfedType);
+ fail("Should have thrown exception");
+ } catch (UnableToCompleteException expected) {
+ }
testLogger.assertCorrectLogEntries();
}
@@ -447,7 +463,18 @@
EditorModel m = new EditorModel(logger,
types.findType("t.PersonEditorWithAliasedSubEditorsDriver"),
rfedType);
EditorData[] fields = m.getEditorData();
- assertEquals(6, fields.length);
+ assertEquals(8, fields.length);
+ }
+
+ private void checkPersonLastModified(EditorData editorField) {
+ assertNotNull(editorField);
+ assertEquals(types.findType(SimpleEditor.class.getName()),
+ editorField.getEditorType().isParameterized().getBaseType());
+ assertTrue(editorField.isLeafValueEditor());
+ assertFalse(editorField.isDelegateRequired());
+ assertFalse(editorField.isValueAwareEditor());
+ assertEquals(".getLastModified()", editorField.getGetterExpression());
+ assertEquals("setLastModified", editorField.getSetterName());
}
private void checkPersonName(EditorData editorField) {
@@ -639,8 +666,10 @@
code.append("interface PersonProxy extends EntityProxy {\n");
code.append("AddressProxy getAddress();\n");
code.append("String getName();\n");
- code.append("void setName(String name);\n");
+ code.append("long getLastModified();\n");
code.append("String getReadonly();\n");
+ code.append("void setName(String name);\n");
+ code.append("void setLastModified(long value);\n");
code.append("}");
return code;
}
@@ -652,6 +681,7 @@
code.append("import " + Editor.class.getName() + ";\n");
code.append("import " + SimpleEditor.class.getName() + ";\n");
code.append("class PersonEditor implements Editor<PersonProxy>
{\n");
+ code.append("SimpleEditor<Long> lastModified;\n");
code.append("public SimpleEditor<String> name;\n");
code.append("SimpleEditor<String> readonly;\n");
code.append("public static SimpleEditor ignoredStatic;\n");
@@ -685,6 +715,30 @@
code.append("}");
return code;
}
+ }, new MockJavaResource("t.PersonEditorWithBadPrimitiveAccess") {
+ @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 PersonEditorWithBadPrimitiveAccess implements
Editor<PersonProxy> {\n");
+ code.append("@Path(\"lastModified.foo\") SimpleEditor<String>
bad;\n");
+ code.append("}");
+ return code;
+ }
+ }, new MockJavaResource("t.PersonEditorWithBadPrimitiveAccessDriver") {
+ @Override
+ protected CharSequence getContent() {
+ StringBuilder code = new StringBuilder();
+ code.append("package t;\n");
+ code.append("import " + RequestFactoryEditorDriver.class.getName()
+ + ";\n");
+ code.append("interface PersonEditorWithBadPrimitiveAccessDriver
extends"
+ + " RequestFactoryEditorDriver<PersonProxy,
t.PersonEditorWithBadPrimitiveAccess> {\n");
+ code.append("}");
+ return code;
+ }
}, new MockJavaResource("t.PersonEditorUsingMethods") {
@Override
protected CharSequence getContent() {
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors