in taverna-uibuilder/src/main/java/org/apache/taverna/lang/uibuilder/UIBuilder.java [105:236]
static void buildEditor(Object target, List<String> fieldNames,
Map<String, Properties> fieldProps, Container contents,
String parent) throws NoSuchMethodException,
IllegalArgumentException, IllegalAccessException,
InvocationTargetException, ClassNotFoundException {
// Get all top level fields to render in this pass
List<String> activeFields = new ArrayList<String>();
for (String field : fieldNames) {
if (!field.contains(".")) {
activeFields.add(field);
}
}
// For each field generate the appropriate component
for (String field : activeFields) {
// Fetch the properties block for this field
Properties props = getProperties(field, parent, fieldProps);
// First check whether there are any subfields for this field, in
// which case we need to treat it differently
boolean simpleField = true;
for (String subField : fieldNames) {
if (!subField.equals(field) && subField.startsWith(field + ".")) {
simpleField = false;
break;
}
}
List<String> subFields = new ArrayList<String>();
// Create filtered list of the field names
// to ensure that this is now the top level
// field and recurse
String newParent = field;
if (!parent.equals("")) {
newParent = parent + "." + field;
}
for (String f : fieldNames) {
if (f.startsWith(field + ".")) {
subFields.add(f.substring(field.length() + 1));
}
}
// Secondly check whether this is a list
boolean listField = false;
Class<?> fieldType = BeanComponent.getPropertyType(target, field);
if (List.class.isAssignableFrom(fieldType)) {
listField = true;
}
// Now handle the four possible cases. If a non-list non-compound
// field we have a terminator and can obtain an appropriate subclass
// of BeanComponent to render it
if (!listField) {
// If a non-list non-compound field we have a terminator and can
// obtain an appropriate subclass of BeanComponent to render it
if (simpleField) {
if (fieldType.isEnum()) {
contents
.add(new BeanEnumComboBox(target, field, props));
} else if (Boolean.class.isAssignableFrom(fieldType)
|| boolean.class.isAssignableFrom(fieldType)) {
contents.add(new BeanCheckBox(target, field, props));
} else {
if (props.get("type") != null) {
if (props.get("type").equals("textarea")) {
BeanTextArea bta = new BeanTextArea(target,
field, props);
contents.add(bta);
} else {
contents.add(new BeanTextField(target, field,
props));
}
} else {
contents
.add(new BeanTextField(target, field, props));
}
}
} else {
Object value = BeanComponent.findMethodWithPrefix("get",
target, field).invoke(target);
if (value != null) {
String displayName = field;
if (props.containsKey("name")) {
displayName = props.getProperty("name");
}
JPanel itemContainer = new JPanel();
itemContainer.setOpaque(false);
itemContainer.setBorder(BorderFactory
.createTitledBorder(displayName));
itemContainer.setLayout(new BoxLayout(itemContainer,
BoxLayout.PAGE_AXIS));
buildEditor(value, subFields, fieldProps,
itemContainer, newParent);
contents.add(itemContainer);
}
}
} else {
// Handle the case where this is a simple field (i.e. no
// sub-fields defined) but is a list type. In this case we need
// to build an appropriate wrapper list panel around this
// returned list.
List value = (List) BeanComponent.findMethodWithPrefix("get",
target, field).invoke(target);
// If the 'new' property is defined then fetch the Class object
// to be used to instantiate new list items
Class<?> newItemClass = null;
if (props.containsKey("new")) {
String newItemClassName = props.getProperty("new");
newItemClass = target.getClass().getClassLoader()
.loadClass(newItemClassName);
}
if (value != null) {
if (simpleField) {
contents.add(new WrappedListComponent(field, value,
props, fieldProps, newItemClass, subFields,
newParent));
// contents.add(buildWrappedList(field, value, props,
// newItemClass));
} else {
contents.add(new RecursiveListComponent(field, value,
props, fieldProps, newItemClass, subFields,
newParent));
// contents.add(buildList(field, value, props,
// fieldProps,
// newItemClass, subFields, newParent));
}
}
}
}
// Finally align any labels where appropriate
Alignment.alignInContainer(contents);
}