Support is/has methods in Editor framework.
Issue 6040.
Patch by: bobv
Review by: rjrjr
Review at http://gwt-code-reviews.appspot.com/1443812
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10288 8db76d5a-ed1c-0410-87a9-c151d255dfc7
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 378cb4f..c17a709 100644
--- a/user/src/com/google/gwt/editor/rebind/model/EditorModel.java
+++ b/user/src/com/google/gwt/editor/rebind/model/EditorModel.java
@@ -22,13 +22,13 @@
import com.google.gwt.core.ext.typeinfo.JGenericType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
-import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
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 com.google.gwt.editor.client.LeafValueEditor;
+import com.google.web.bindery.autobean.gwt.rebind.model.JBeanMethod;
import java.util.ArrayList;
import java.util.Arrays;
@@ -376,13 +376,6 @@
return toReturn.toArray(new EditorData[toReturn.size()]);
}
- private String camelCase(String prefix, String name) {
- StringBuilder sb = new StringBuilder();
- sb.append(prefix).append(Character.toUpperCase(name.charAt(0))).append(
- name, 1, name.length());
- return sb.toString();
- }
-
private List<EditorData> createEditorData(EditorAccess access)
throws UnableToCompleteException {
TreeLogger subLogger = logger.branch(TreeLogger.DEBUG, "Examining "
@@ -471,64 +464,73 @@
continue;
}
boolean lastPart = i == j - 1;
- String getterName = camelCase("get", parts[i]);
+ boolean foundGetterForPart = false;
- for (JClassType search : lookingAt.getFlattenedSupertypeHierarchy()) {
- // If looking at the last element of the path, also look for a setter
- if (i == j - 1 && setterName == null) {
- for (JMethod maybeSetter : search.getOverloads(camelCase("set",
- parts[i]))) {
- if (maybeSetter.getReturnType().equals(JPrimitiveType.VOID)
- && maybeSetter.getParameters().length == 1) {
+ for (JMethod maybeSetter : lookingAt.getInheritableMethods()) {
+ JBeanMethod which = JBeanMethod.which(maybeSetter);
+ if (JBeanMethod.CALL.equals(which)) {
+ continue;
+ }
+ if (!which.inferName(maybeSetter).equals(parts[i])) {
+ continue;
+ }
+ switch (which) {
+ case GET: {
+ JType returnType = maybeSetter.getReturnType();
+ lookingAt = returnType.isClassOrInterface();
+ if (!lastPart && lookingAt == null) {
+ poison(foundPrimitiveMessage(returnType, interstitialGetters.toString(), path));
+ return;
+ }
+ interstitialGetters.append(".").append(maybeSetter.getName()).append("()");
+ interstitialGuard.append(" && %1$s").append(interstitialGetters).append(" != null");
+ builder.propertyOwnerType(maybeSetter.getEnclosingType());
+ foundGetterForPart = true;
+ if (!lastPart) {
+ continue part;
+ }
+ break;
+ }
+ case SET:
+ case SET_BUILDER: {
+ if (lastPart && setterName == null) {
+ /*
+ * If looking at the last element of the path, also look for a
+ * setter.
+ */
+
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());
+ setterParamType =
+ oracle.findType(setterParamType.isPrimitive().getQualifiedBoxedSourceName());
}
- boolean matches = setterParamType.isClassOrInterface().isAssignableFrom(
- propertyType);
+ boolean matches = setterParamType.isClassOrInterface().isAssignableFrom(propertyType);
if (matches) {
setterName = maybeSetter.getName();
- break;
}
}
+ break;
}
}
-
- JMethod getter = search.findMethod(getterName, new JType[0]);
- if (getter != null) {
- JType returnType = getter.getReturnType();
- lookingAt = returnType.isClassOrInterface();
- if (!lastPart && lookingAt == null) {
- poison(foundPrimitiveMessage(returnType,
- interstitialGetters.toString(), path));
- return;
- }
- interstitialGetters.append(".").append(getterName).append("()");
- interstitialGuard.append(" && %1$s").append(interstitialGetters).append(
- " != null");
- builder.propertyOwnerType(search);
- continue part;
- }
}
- poison(noGetterMessage(path, proxyType));
- return;
+ if (!foundGetterForPart) {
+ poison(noGetterMessage(path, proxyType));
+ return;
+ }
}
int idx = interstitialGetters.lastIndexOf(".");
- builder.beanOwnerExpression(idx <= 0 ? "" : interstitialGetters.substring(
- 0, idx));
+ builder.beanOwnerExpression(idx <= 0 ? "" : interstitialGetters.substring(0, idx));
if (parts.length > 1) {
// Strip after last && since null is a valid value
- interstitialGuard.delete(interstitialGuard.lastIndexOf(" &&"),
- interstitialGuard.length());
+ interstitialGuard.delete(interstitialGuard.lastIndexOf(" &&"), interstitialGuard.length());
builder.beanOwnerGuard(interstitialGuard.substring(8));
}
if (interstitialGetters.length() > 0) {
builder.getterExpression("."
- + interstitialGetters.substring(idx + 1,
- interstitialGetters.length() - 2) + "()");
+ + interstitialGetters.substring(idx + 1, interstitialGetters.length() - 2) + "()");
} else {
builder.getterExpression("");
}
diff --git a/user/test/com/google/gwt/editor/rebind/model/EditorModelTest.java b/user/test/com/google/gwt/editor/rebind/model/EditorModelTest.java
index ba3ae78..bb270d7 100644
--- a/user/test/com/google/gwt/editor/rebind/model/EditorModelTest.java
+++ b/user/test/com/google/gwt/editor/rebind/model/EditorModelTest.java
@@ -188,7 +188,7 @@
types.findType("t.CompositeEditorDriver"), rfedType);
EditorData[] data = m.getEditorData();
- assertEquals(7, data.length);
+ assertEquals(9, data.length);
String[] paths = new String[data.length];
String[] expressions = new String[data.length];
@@ -196,20 +196,22 @@
paths[i] = data[i].getPath();
expressions[i] = data[i].getExpression();
}
- assertEquals(Arrays.asList("address", "address.city", "address.street",
- "person", "person.lastModified", "person.name", "person.readonly"),
- Arrays.asList(paths));
+ assertEquals(Arrays.asList("address", "address.city", "address.street", "person", "person.has",
+ "person.is", "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().lastModified", "person().name",
+ assertEquals(Arrays.asList("address", "address.city", "address.street", "person()",
+ "person().has", "person().is", "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());
- checkPersonLastModified(data[4]);
- checkPersonName(data[5]);
- checkPersonReadonly(data[6]);
+ int fieldNum = 4;
+ checkPersonHasHas(data[fieldNum++]);
+ checkPersonIsIs(data[fieldNum++]);
+ checkPersonLastModified(data[fieldNum++]);
+ checkPersonName(data[fieldNum++]);
+ checkPersonReadonly(data[fieldNum++]);
}
public void testCyclicDriver() {
@@ -259,14 +261,19 @@
EditorModel m = new EditorModel(logger,
types.findType("t.PersonEditorDriver"), rfedType);
EditorData[] fields = m.getEditorData();
- assertEquals(3, fields.length);
+ assertEquals(5, fields.length);
+ int fieldNum = 0;
+ // hasHas
+ checkPersonHasHas(fields[fieldNum++]);
+ // isIs
+ checkPersonIsIs(fields[fieldNum++]);
// lastModified
- checkPersonLastModified(fields[0]);
+ checkPersonLastModified(fields[fieldNum++]);
// name
- checkPersonName(fields[1]);
+ checkPersonName(fields[fieldNum++]);
// readonly
- checkPersonReadonly(fields[2]);
+ checkPersonReadonly(fields[fieldNum++]);
}
public void testFlatData() throws UnableToCompleteException {
@@ -282,10 +289,13 @@
assertEquals("person", composite[1].getPropertyName());
EditorData[] person = m.getEditorData(types.findType("t.PersonEditor"));
- assertEquals(3, person.length);
- assertEquals("lastModified", person[0].getPropertyName());
- assertEquals("name", person[1].getPropertyName());
- assertEquals("readonly", person[2].getPropertyName());
+ assertEquals(5, person.length);
+ int fieldNum = 0;
+ assertEquals("has", person[fieldNum++].getPropertyName());
+ assertEquals("is", person[fieldNum++].getPropertyName());
+ assertEquals("lastModified", person[fieldNum++].getPropertyName());
+ assertEquals("name", person[fieldNum++].getPropertyName());
+ assertEquals("readonly", person[fieldNum++].getPropertyName());
EditorData[] address = m.getEditorData(types.findType("t.AddressEditor"));
assertEquals("city", address[0].getPropertyName());
@@ -465,7 +475,29 @@
EditorModel m = new EditorModel(logger,
types.findType("t.PersonEditorWithAliasedSubEditorsDriver"), rfedType);
EditorData[] fields = m.getEditorData();
- assertEquals(8, fields.length);
+ assertEquals(12, fields.length);
+ }
+
+ private void checkPersonHasHas(EditorData editorField) {
+ assertNotNull(editorField);
+ assertEquals(types.findType(SimpleEditor.class.getName()),
+ editorField.getEditorType().isParameterized().getBaseType());
+ assertTrue(editorField.isLeafValueEditor());
+ assertFalse(editorField.isDelegateRequired());
+ assertFalse(editorField.isValueAwareEditor());
+ assertEquals(".hasHas()", editorField.getGetterExpression());
+ assertEquals("setHas", editorField.getSetterName());
+ }
+
+ private void checkPersonIsIs(EditorData editorField) {
+ assertNotNull(editorField);
+ assertEquals(types.findType(SimpleEditor.class.getName()),
+ editorField.getEditorType().isParameterized().getBaseType());
+ assertTrue(editorField.isLeafValueEditor());
+ assertFalse(editorField.isDelegateRequired());
+ assertFalse(editorField.isValueAwareEditor());
+ assertEquals(".isIs()", editorField.getGetterExpression());
+ assertEquals("setIs", editorField.getSetterName());
}
private void checkPersonLastModified(EditorData editorField) {
@@ -676,6 +708,10 @@
code.append("String getName();\n");
code.append("long getLastModified();\n");
code.append("String getReadonly();\n");
+ code.append("boolean hasHas();\n");
+ code.append("boolean isIs();\n");
+ code.append("void setHas(boolean has);\n");
+ code.append("void setIs(boolean is);\n");
code.append("void setName(String name);\n");
code.append("void setLastModified(long value);\n");
code.append("}");
@@ -689,6 +725,8 @@
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<Boolean> has;\n");
+ code.append("SimpleEditor<Boolean> is;\n");
code.append("SimpleEditor<Long> lastModified;\n");
code.append("public SimpleEditor<String> name;\n");
code.append("SimpleEditor<String> readonly;\n");