final OwnerFieldClass ownerFieldClass = OwnerFieldClass.getFieldClass(type,
writer.getLogger());
// See if there's a factory method
JAbstractMethod creator = writer.getOwnerClass().getUiFactoryMethod(type);
if (creator == null) {
// If not, see if there's a @UiConstructor
creator = ownerFieldClass.getUiConstructor();
}
if (creator != null) {
for (JParameter param : creator.getParameters()) {
unfilledRequiredParams.put(param.getName(), param.getType());
}
}
// Work through the localized attribute values and assign them
// to appropriate constructor params or setters (which had better be
// ready to accept strings)
for (Entry<String, String> property : localizedValues.entrySet()) {
String key = property.getKey();
String value = property.getValue();
JType paramType = unfilledRequiredParams.get(key);
if (paramType != null) {
if (!isString(writer, paramType)) {
writer.die("In %s, cannot apply message attribute to non-string "
+ "constructor argument %s %s.", elem,
paramType.getSimpleSourceName(), key);
}
requiredValues.put(key, value);
unfilledRequiredParams.remove(key);
} else {
JMethod setter = ownerFieldClass.getSetter(key);
JParameter[] params = setter == null ? null : setter.getParameters();
if (setter == null || !(params.length == 1)
|| !isString(writer, params[0].getType())) {
writer.die("In %s, no method found to apply message attribute %s",
elem, key);
} else {
setterValues.put(key, value);
}
}
}
// Now go through the element and dispatch its attributes, remembering
// that constructor arguments get first dibs
for (int i = elem.getAttributeCount() - 1; i >= 0; i--) {
// Backward traversal b/c we're deleting attributes from the xml element
XMLAttribute attribute = elem.getAttribute(i);
// Ignore xmlns attributes
if (attribute.getName().startsWith("xmlns:")) {
continue;
}
String propertyName = attribute.getLocalName();
if (setterValues.keySet().contains(propertyName)
|| requiredValues.containsKey(propertyName)) {
writer.die("In %s, duplicate attribute name: %s", elem, propertyName);
}
if (unfilledRequiredParams.keySet().contains(propertyName)) {
JType paramType = unfilledRequiredParams.get(propertyName);
String value = elem.consumeAttributeWithDefault(attribute.getName(),
null, paramType);
if (value == null) {
writer.die("In %s, unable to parse %s as constructor argument "
+ "of type %s", elem, attribute, paramType.getSimpleSourceName());
}
requiredValues.put(propertyName, value);
unfilledRequiredParams.remove(propertyName);
} else {
JMethod setter = ownerFieldClass.getSetter(propertyName);
if (setter == null) {
writer.die("In %s, class %s has no appropriate set%s() method", elem,
elem.getLocalName(), initialCap(propertyName));
}
String n = attribute.getName();
String value = elem.consumeAttributeWithDefault(n,
null, getParamTypes(setter));
if (value == null) {
writer.die("In %s, unable to parse %s.", elem, attribute);
}
setterValues.put(propertyName, value);
}
}
if (!unfilledRequiredParams.isEmpty()) {
StringBuilder b = new StringBuilder(String.format(
"%s missing required attribute(s):", elem));
for (String name : unfilledRequiredParams.keySet()) {
b.append(" ").append(name);
}
writer.die(b.toString());
}
if (creator != null) {
String[] args = makeArgsList(requiredValues, creator);
if (creator instanceof JMethod) { // Factory method
String factoryMethod = String.format("owner.%s(%s)", creator.getName(),
UiBinderWriter.asCommaSeparatedList(args));
writer.setFieldInitializer(fieldName, factoryMethod);
} else { // Annotated Constructor
writer.setFieldInitializerAsConstructor(fieldName, type, args);
}