SPR-3389 Nicer handling of Java 5 enums by the Spring MVC form taglib.
The form:options and form:radiobuttons tags will now render a set of options automatically if the bind target is an Enum and items are not otherwise specified. The values of the enum are converted into form inputs where by default the form value is the enum's name() and the form label is the enum's toString().
This commit is contained in:
@@ -35,6 +35,7 @@ import org.springframework.util.StringUtils;
|
||||
* of '<code>checkbox</code>' or '<code>radio</code>'.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Scott Andrews
|
||||
* @since 2.5.2
|
||||
*/
|
||||
public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElementTag {
|
||||
@@ -191,6 +192,11 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
|
||||
String labelProperty =
|
||||
(itemLabel != null ? ObjectUtils.getDisplayString(evaluate("itemLabel", itemLabel)) : null);
|
||||
|
||||
Class<?> boundType = getBindStatus().getValueType();
|
||||
if (itemsObject == null && boundType != null && boundType.isEnum()) {
|
||||
itemsObject = boundType.getEnumConstants();
|
||||
}
|
||||
|
||||
if (itemsObject == null) {
|
||||
throw new IllegalArgumentException("Attribute 'items' is required and must be a Collection, an Array or a Map");
|
||||
}
|
||||
@@ -229,7 +235,16 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
|
||||
String labelProperty, Object item, int itemIndex) throws JspException {
|
||||
|
||||
BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(item);
|
||||
Object renderValue = (valueProperty != null ? wrapper.getPropertyValue(valueProperty) : item);
|
||||
Object renderValue;
|
||||
if (valueProperty != null) {
|
||||
renderValue = wrapper.getPropertyValue(valueProperty);
|
||||
}
|
||||
else if (item instanceof Enum) {
|
||||
renderValue = ((Enum<?>) item).name();
|
||||
}
|
||||
else {
|
||||
renderValue = item;
|
||||
}
|
||||
Object renderLabel = (labelProperty != null ? wrapper.getPropertyValue(labelProperty) : item);
|
||||
writeElementTag(tagWriter, item, renderValue, renderLabel, itemIndex);
|
||||
}
|
||||
|
||||
@@ -42,7 +42,8 @@ import org.springframework.web.servlet.support.BindStatus;
|
||||
* the <code>labelProperty</code>). These properties are then used when
|
||||
* rendering each element of the array/{@link Collection} as an '<code>option</code>'.
|
||||
* If either property name is omitted, the value of {@link Object#toString()} of
|
||||
* the corresponding array/{@link Collection} element is used instead.
|
||||
* the corresponding array/{@link Collection} element is used instead. However,
|
||||
* if the item is an enum, {@link Enum#name()} is used as the default value.
|
||||
* </p>
|
||||
* <h3>Using a {@link Map}:</h3>
|
||||
* <p>
|
||||
@@ -83,6 +84,7 @@ import org.springframework.web.servlet.support.BindStatus;
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @author Scott Andrews
|
||||
* @since 2.0
|
||||
*/
|
||||
class OptionWriter {
|
||||
@@ -134,6 +136,9 @@ class OptionWriter {
|
||||
else if (this.optionSource instanceof Map) {
|
||||
renderFromMap(tagWriter);
|
||||
}
|
||||
else if (this.optionSource instanceof Class && this.optionSource.getClass().isEnum()) {
|
||||
renderFromEnum(tagWriter);
|
||||
}
|
||||
else {
|
||||
throw new JspException(
|
||||
"Type [" + this.optionSource.getClass().getName() + "] is not valid for option items");
|
||||
@@ -177,6 +182,14 @@ class OptionWriter {
|
||||
doRenderFromCollection((Collection) this.optionSource, tagWriter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the inner '<code>option</code>' tags using the {@link #optionSource}.
|
||||
* @see #doRenderFromCollection(java.util.Collection, TagWriter)
|
||||
*/
|
||||
private void renderFromEnum(final TagWriter tagWriter) throws JspException {
|
||||
doRenderFromCollection(CollectionUtils.arrayToList(((Class) this.optionSource).getEnumConstants()), tagWriter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the inner '<code>option</code>' tags using the supplied {@link Collection} of
|
||||
* objects as the source. The value of the {@link #valueProperty} field is used
|
||||
@@ -187,7 +200,16 @@ class OptionWriter {
|
||||
for (Iterator it = optionCollection.iterator(); it.hasNext();) {
|
||||
Object item = it.next();
|
||||
BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(item);
|
||||
Object value = (this.valueProperty != null ? wrapper.getPropertyValue(this.valueProperty) : item);
|
||||
Object value;
|
||||
if (this.valueProperty != null) {
|
||||
value = wrapper.getPropertyValue(this.valueProperty);
|
||||
}
|
||||
else if (item instanceof Enum) {
|
||||
value = ((Enum<?>) item).name();
|
||||
}
|
||||
else {
|
||||
value = item;
|
||||
}
|
||||
Object label = (this.labelProperty != null ? wrapper.getPropertyValue(this.labelProperty) : item);
|
||||
renderOption(tagWriter, item, value, label);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.springframework.web.util.TagUtils;
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @author Scott Andrews
|
||||
* @since 2.0
|
||||
*/
|
||||
public class OptionsTag extends AbstractHtmlElementTag {
|
||||
@@ -146,7 +147,16 @@ public class OptionsTag extends AbstractHtmlElementTag {
|
||||
protected int writeTagContent(TagWriter tagWriter) throws JspException {
|
||||
assertUnderSelectTag();
|
||||
Object items = getItems();
|
||||
Object itemsObject = (items instanceof String ? evaluate("items", (String) items) : items);
|
||||
Object itemsObject = null;
|
||||
if (items != null) {
|
||||
itemsObject = (items instanceof String ? evaluate("items", (String) items) : items);
|
||||
} else {
|
||||
Class<?> selectTagBoundType = ((SelectTag) findAncestorWithClass(this, SelectTag.class))
|
||||
.getBindStatus().getValueType();
|
||||
if (selectTagBoundType != null && selectTagBoundType.isEnum()) {
|
||||
itemsObject = selectTagBoundType.getEnumConstants();
|
||||
}
|
||||
}
|
||||
if (itemsObject != null) {
|
||||
String itemValue = getItemValue();
|
||||
String itemLabel = getItemLabel();
|
||||
|
||||
Reference in New Issue
Block a user