for (AutoBeanMethod method : type.getMethods()) {
if (!method.getAction().equals(Action.GET)) {
continue;
}
AutoBeanMethod setter = null;
// If it's not a simple bean type, try to find a real setter method
if (!type.isSimpleBean()) {
for (AutoBeanMethod maybeSetter : type.getMethods()) {
if (maybeSetter.getAction().equals(Action.SET)
&& maybeSetter.getPropertyName().equals(method.getPropertyName())) {
setter = maybeSetter;
break;
}
}
}
// The type of property influences the visitation
String valueExpression = String.format(
"%1$s value = (%1$s) %2$s.getAutoBean(as().%3$s());",
AbstractAutoBean.class.getCanonicalName(),
AutoBeanUtils.class.getCanonicalName(), method.getMethod().getName());
String visitMethod;
Class<?> propertyContextType;
if (method.isCollection()) {
propertyContextType = CollectionPropertyContext.class;
visitMethod = "Collection";
} else if (method.isMap()) {
propertyContextType = MapPropertyContext.class;
visitMethod = "Map";
} else if (method.isValueType()) {
propertyContextType = PropertyContext.class;
valueExpression = String.format("Object value = as().%s();",
method.getMethod().getName());
visitMethod = "Value";
} else {
visitMethod = "Reference";
propertyContextType = PropertyContext.class;
}
/*
* Make the PropertyContext that lets us call the setter. We allow
* multiple methods to be bound to the same property (e.g. to allow JSON
* payloads to be interpreted as different types). The leading underscore
* allows purely numeric property names, which are valid JSON map keys.
*/
String propertyContextName = names.createName("_"
+ method.getPropertyName() + "PropertyContext");
sw.println("class %s implements %s {", propertyContextName,
propertyContextType.getCanonicalName());
sw.indent();
sw.println("public boolean canSet() { return %s; }", type.isSimpleBean()
|| setter != null);
if (method.isCollection()) {
// Will return the collection's element type or null if not a collection
sw.println(
"public Class<?> getElementType() { return %s.class; }",
ModelUtils.ensureBaseType(method.getElementType()).getQualifiedSourceName());
} else if (method.isMap()) {
// Will return the map's value type
sw.println(
"public Class<?> getValueType() { return %s.class; }",
ModelUtils.ensureBaseType(method.getValueType()).getQualifiedSourceName());
// Will return the map's key type
sw.println(
"public Class<?> getKeyType() { return %s.class; }",
ModelUtils.ensureBaseType(method.getKeyType()).getQualifiedSourceName());
}
// Return the property type
sw.println(
"public Class<?> getType() { return %s.class; }",
ModelUtils.ensureBaseType(method.getMethod().getReturnType()).getQualifiedSourceName());
sw.println("public void set(Object obj) { ");
if (setter != null) {
// Prefer the setter if one exists
// as().setFoo((Foo) obj);
sw.indentln(
"as().%s((%s) obj);",
setter.getMethod().getName(),
ModelUtils.ensureBaseType(
setter.getMethod().getParameters()[0].getType()).getQualifiedSourceName());
} else if (type.isSimpleBean()) {
// Otherwise, fall back to a map assignment
sw.indentln("values.put(\"%s\", obj);", method.getPropertyName());
} else {
sw.indentln("throw new UnsupportedOperationException(\"No setter\");");