Nullability refinements in spring-webmvc
Includes revision of web.servlet.tags.form for non-null conventions. Issue: SPR-15540
This commit is contained in:
parent
4a147d26fc
commit
f74a631ea1
|
@ -51,7 +51,7 @@ public class ModelMap extends LinkedHashMap<String, Object> {
|
|||
* under the supplied name.
|
||||
* @see #addAttribute(String, Object)
|
||||
*/
|
||||
public ModelMap(String attributeName, Object attributeValue) {
|
||||
public ModelMap(String attributeName, @Nullable Object attributeValue) {
|
||||
addAttribute(attributeName, attributeValue);
|
||||
}
|
||||
|
||||
|
|
|
@ -280,12 +280,12 @@ public class ModelAndView {
|
|||
|
||||
/**
|
||||
* Add an attribute to the model.
|
||||
* @param attributeName name of the object to add to the model
|
||||
* @param attributeValue object to add to the model (never {@code null})
|
||||
* @param attributeName name of the object to add to the model (never {@code null})
|
||||
* @param attributeValue object to add to the model (can be {@code null})
|
||||
* @see ModelMap#addAttribute(String, Object)
|
||||
* @see #getModelMap()
|
||||
*/
|
||||
public ModelAndView addObject(String attributeName, Object attributeValue) {
|
||||
public ModelAndView addObject(String attributeName, @Nullable Object attributeValue) {
|
||||
getModelMap().addAttribute(attributeName, attributeValue);
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -51,17 +51,17 @@ public interface RequestDataValueProcessor {
|
|||
/**
|
||||
* Invoked when a form field value is rendered.
|
||||
* @param request the current request
|
||||
* @param name the form field name
|
||||
* @param name the form field name (if any)
|
||||
* @param value the form field value
|
||||
* @param type the form field type ("text", "hidden", etc.)
|
||||
* @return the form field value to use, possibly modified
|
||||
*/
|
||||
String processFormFieldValue(HttpServletRequest request, String name, String value, String type);
|
||||
String processFormFieldValue(HttpServletRequest request, @Nullable String name, String value, String type);
|
||||
|
||||
/**
|
||||
* Invoked after all form fields have been rendered.
|
||||
* @param request the current request
|
||||
* @return additional hidden form fields to be added, or {@code null}
|
||||
* @return additional hidden form fields to be added, or {@code null} if none
|
||||
*/
|
||||
@Nullable
|
||||
Map<String, String> getExtraHiddenFields(HttpServletRequest request);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -18,6 +18,8 @@ package org.springframework.web.servlet.tags.form;
|
|||
|
||||
import javax.servlet.jsp.JspException;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Abstract base class to provide common methods for
|
||||
* implementing databinding-aware JSP tags for rendering an HTML '{@code input}'
|
||||
|
@ -36,7 +38,7 @@ public abstract class AbstractCheckedElementTag extends AbstractHtmlInputElement
|
|||
* '{@code input}' element as 'checked' if the supplied value matches the
|
||||
* bound value.
|
||||
*/
|
||||
protected void renderFromValue(Object value, TagWriter tagWriter) throws JspException {
|
||||
protected void renderFromValue(@Nullable Object value, TagWriter tagWriter) throws JspException {
|
||||
renderFromValue(value, value, tagWriter);
|
||||
}
|
||||
|
||||
|
@ -45,7 +47,9 @@ public abstract class AbstractCheckedElementTag extends AbstractHtmlInputElement
|
|||
* '{@code input}' element as 'checked' if the supplied value matches the
|
||||
* bound value.
|
||||
*/
|
||||
protected void renderFromValue(Object item, Object value, TagWriter tagWriter) throws JspException {
|
||||
protected void renderFromValue(@Nullable Object item, @Nullable Object value, TagWriter tagWriter)
|
||||
throws JspException {
|
||||
|
||||
String displayValue = convertToDisplayString(value);
|
||||
tagWriter.writeAttribute("value", processFieldValue(getName(), displayValue, getInputType()));
|
||||
if (isOptionSelected(value) || (value != item && isOptionSelected(item))) {
|
||||
|
@ -57,7 +61,7 @@ public abstract class AbstractCheckedElementTag extends AbstractHtmlInputElement
|
|||
* Determines whether the supplied value matched the selected value
|
||||
* through delegating to {@link SelectedValueComparator#isSelected}.
|
||||
*/
|
||||
private boolean isOptionSelected(Object value) throws JspException {
|
||||
private boolean isOptionSelected(@Nullable Object value) throws JspException {
|
||||
return SelectedValueComparator.isSelected(getBindStatus(), value);
|
||||
}
|
||||
|
||||
|
@ -77,8 +81,10 @@ public abstract class AbstractCheckedElementTag extends AbstractHtmlInputElement
|
|||
* Return a unique ID for the bound name within the current PageContext.
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
protected String autogenerateId() throws JspException {
|
||||
return TagIdGenerator.nextId(super.autogenerateId(), this.pageContext);
|
||||
String id = super.autogenerateId();
|
||||
return (id != null ? TagIdGenerator.nextId(id, this.pageContext) : null);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -55,16 +55,19 @@ public abstract class AbstractDataBoundFormElementTag extends AbstractFormTag im
|
|||
/**
|
||||
* The property path from the {@link FormTag#setModelAttribute form object}.
|
||||
*/
|
||||
@Nullable
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* The value of the '{@code id}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* The {@link BindStatus} of this tag.
|
||||
*/
|
||||
@Nullable
|
||||
private BindStatus bindStatus;
|
||||
|
||||
|
||||
|
@ -91,7 +94,7 @@ public abstract class AbstractDataBoundFormElementTag extends AbstractFormTag im
|
|||
* Note that the default value may not be valid for certain tags.
|
||||
*/
|
||||
@Override
|
||||
public void setId(String id) {
|
||||
public void setId(@Nullable String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
@ -99,6 +102,7 @@ public abstract class AbstractDataBoundFormElementTag extends AbstractFormTag im
|
|||
* Get the value of the '{@code id}' attribute.
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
@ -179,6 +183,7 @@ public abstract class AbstractDataBoundFormElementTag extends AbstractFormTag im
|
|||
* Get the value of the nested path that may have been exposed by the
|
||||
* {@link NestedPathTag}.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getNestedPath() {
|
||||
return (String) this.pageContext.getAttribute(NESTED_PATH_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
|
||||
}
|
||||
|
@ -225,7 +230,7 @@ public abstract class AbstractDataBoundFormElementTag extends AbstractFormTag im
|
|||
* Get a display String for the given value, converted by a PropertyEditor
|
||||
* that the BindStatus may have registered for the value's Class.
|
||||
*/
|
||||
protected String convertToDisplayString(Object value) throws JspException {
|
||||
protected String convertToDisplayString(@Nullable Object value) throws JspException {
|
||||
PropertyEditor editor = (value != null ? getBindStatus().findEditor(value.getClass()) : null);
|
||||
return getDisplayString(value, editor);
|
||||
}
|
||||
|
@ -234,10 +239,10 @@ public abstract class AbstractDataBoundFormElementTag extends AbstractFormTag im
|
|||
* Process the given form field through a {@link RequestDataValueProcessor}
|
||||
* instance if one is configured or otherwise returns the same value.
|
||||
*/
|
||||
protected final String processFieldValue(String name, String value, String type) {
|
||||
protected final String processFieldValue(@Nullable String name, String value, String type) {
|
||||
RequestDataValueProcessor processor = getRequestContext().getRequestDataValueProcessor();
|
||||
ServletRequest request = this.pageContext.getRequest();
|
||||
if (processor != null && (request instanceof HttpServletRequest)) {
|
||||
if (processor != null && request instanceof HttpServletRequest) {
|
||||
value = processor.processFormFieldValue((HttpServletRequest) request, name, value, type);
|
||||
}
|
||||
return value;
|
||||
|
|
|
@ -45,7 +45,8 @@ public abstract class AbstractFormTag extends HtmlEscapingAwareTag {
|
|||
* Evaluate the supplied value for the supplied attribute name.
|
||||
* <p>The default implementation simply returns the given value as-is.
|
||||
*/
|
||||
protected Object evaluate(String attributeName, Object value) throws JspException {
|
||||
@Nullable
|
||||
protected Object evaluate(String attributeName, @Nullable Object value) throws JspException {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -89,7 +90,7 @@ public abstract class AbstractFormTag extends HtmlEscapingAwareTag {
|
|||
* Get the display value of the supplied {@code Object}, HTML escaped
|
||||
* as required. This version is <strong>not</strong> {@link PropertyEditor}-aware.
|
||||
*/
|
||||
protected String getDisplayString(Object value) {
|
||||
protected String getDisplayString(@Nullable Object value) {
|
||||
return ValueFormatter.getDisplayString(value, isHtmlEscape());
|
||||
}
|
||||
|
||||
|
@ -99,7 +100,7 @@ public abstract class AbstractFormTag extends HtmlEscapingAwareTag {
|
|||
* {@link PropertyEditor} is not null then the {@link PropertyEditor} is used
|
||||
* to obtain the display value.
|
||||
*/
|
||||
protected String getDisplayString(Object value, PropertyEditor propertyEditor) {
|
||||
protected String getDisplayString(@Nullable Object value, @Nullable PropertyEditor propertyEditor) {
|
||||
return ValueFormatter.getDisplayString(value, propertyEditor, isHtmlEscape());
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ import javax.servlet.jsp.JspException;
|
|||
import javax.servlet.jsp.tagext.BodyContent;
|
||||
import javax.servlet.jsp.tagext.BodyTag;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
|
@ -35,8 +37,10 @@ import org.springframework.util.StringUtils;
|
|||
@SuppressWarnings("serial")
|
||||
public abstract class AbstractHtmlElementBodyTag extends AbstractHtmlElementTag implements BodyTag {
|
||||
|
||||
@Nullable
|
||||
private BodyContent bodyContent;
|
||||
|
||||
@Nullable
|
||||
private TagWriter tagWriter;
|
||||
|
||||
|
||||
|
@ -57,11 +61,12 @@ public abstract class AbstractHtmlElementBodyTag extends AbstractHtmlElementTag
|
|||
* If {@link #shouldRender rendering}, flush any buffered
|
||||
* {@link BodyContent} or, if no {@link BodyContent} is supplied,
|
||||
* {@link #renderDefaultContent render the default content}.
|
||||
* @return a {@link Tag#EVAL_PAGE} result
|
||||
* @return a {@link javax.servlet.jsp.tagext.Tag#EVAL_PAGE} result
|
||||
*/
|
||||
@Override
|
||||
public int doEndTag() throws JspException {
|
||||
if (shouldRender()) {
|
||||
Assert.state(this.tagWriter != null, "No TagWriter set");
|
||||
if (this.bodyContent != null && StringUtils.hasText(this.bodyContent.getString())) {
|
||||
renderFromBodyContent(this.bodyContent, this.tagWriter);
|
||||
}
|
||||
|
@ -79,7 +84,7 @@ public abstract class AbstractHtmlElementBodyTag extends AbstractHtmlElementTag
|
|||
* override this to add additional content to the output.
|
||||
*/
|
||||
protected void renderFromBodyContent(BodyContent bodyContent, TagWriter tagWriter) throws JspException {
|
||||
flushBufferedBodyContent(this.bodyContent);
|
||||
flushBufferedBodyContent(bodyContent);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.util.Map;
|
|||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.tagext.DynamicAttributes;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
@ -76,40 +77,58 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
public static final String ONKEYDOWN_ATTRIBUTE = "onkeydown";
|
||||
|
||||
|
||||
@Nullable
|
||||
private String cssClass;
|
||||
|
||||
@Nullable
|
||||
private String cssErrorClass;
|
||||
|
||||
@Nullable
|
||||
private String cssStyle;
|
||||
|
||||
@Nullable
|
||||
private String lang;
|
||||
|
||||
@Nullable
|
||||
private String title;
|
||||
|
||||
@Nullable
|
||||
private String dir;
|
||||
|
||||
@Nullable
|
||||
private String tabindex;
|
||||
|
||||
@Nullable
|
||||
private String onclick;
|
||||
|
||||
@Nullable
|
||||
private String ondblclick;
|
||||
|
||||
@Nullable
|
||||
private String onmousedown;
|
||||
|
||||
@Nullable
|
||||
private String onmouseup;
|
||||
|
||||
@Nullable
|
||||
private String onmouseover;
|
||||
|
||||
@Nullable
|
||||
private String onmousemove;
|
||||
|
||||
@Nullable
|
||||
private String onmouseout;
|
||||
|
||||
@Nullable
|
||||
private String onkeypress;
|
||||
|
||||
@Nullable
|
||||
private String onkeyup;
|
||||
|
||||
@Nullable
|
||||
private String onkeydown;
|
||||
|
||||
@Nullable
|
||||
private Map<String, Object> dynamicAttributes;
|
||||
|
||||
|
||||
|
@ -125,6 +144,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
* Get the value of the '{@code class}' attribute.
|
||||
* May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getCssClass() {
|
||||
return this.cssClass;
|
||||
}
|
||||
|
@ -141,6 +161,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
* The CSS class to use when the field bound to a particular tag has errors.
|
||||
* May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getCssErrorClass() {
|
||||
return this.cssErrorClass;
|
||||
}
|
||||
|
@ -157,6 +178,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
* Get the value of the '{@code style}' attribute.
|
||||
* May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getCssStyle() {
|
||||
return this.cssStyle;
|
||||
}
|
||||
|
@ -173,6 +195,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
* Get the value of the '{@code lang}' attribute.
|
||||
* May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getLang() {
|
||||
return this.lang;
|
||||
}
|
||||
|
@ -189,6 +212,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
* Get the value of the '{@code title}' attribute.
|
||||
* May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
@ -205,6 +229,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
* Get the value of the '{@code dir}' attribute.
|
||||
* May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getDir() {
|
||||
return this.dir;
|
||||
}
|
||||
|
@ -221,6 +246,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
* Get the value of the '{@code tabindex}' attribute.
|
||||
* May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getTabindex() {
|
||||
return this.tabindex;
|
||||
}
|
||||
|
@ -237,6 +263,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
* Get the value of the '{@code onclick}' attribute.
|
||||
* May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getOnclick() {
|
||||
return this.onclick;
|
||||
}
|
||||
|
@ -253,6 +280,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
* Get the value of the '{@code ondblclick}' attribute.
|
||||
* May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getOndblclick() {
|
||||
return this.ondblclick;
|
||||
}
|
||||
|
@ -269,6 +297,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
* Get the value of the '{@code onmousedown}' attribute.
|
||||
* May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getOnmousedown() {
|
||||
return this.onmousedown;
|
||||
}
|
||||
|
@ -285,6 +314,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
* Get the value of the '{@code onmouseup}' attribute.
|
||||
* May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getOnmouseup() {
|
||||
return this.onmouseup;
|
||||
}
|
||||
|
@ -301,6 +331,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
* Get the value of the '{@code onmouseover}' attribute.
|
||||
* May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getOnmouseover() {
|
||||
return this.onmouseover;
|
||||
}
|
||||
|
@ -317,6 +348,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
* Get the value of the '{@code onmousemove}' attribute.
|
||||
* May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getOnmousemove() {
|
||||
return this.onmousemove;
|
||||
}
|
||||
|
@ -332,6 +364,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
* Get the value of the '{@code onmouseout}' attribute.
|
||||
* May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getOnmouseout() {
|
||||
return this.onmouseout;
|
||||
}
|
||||
|
@ -348,6 +381,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
* Get the value of the '{@code onkeypress}' attribute.
|
||||
* May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getOnkeypress() {
|
||||
return this.onkeypress;
|
||||
}
|
||||
|
@ -364,6 +398,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
* Get the value of the '{@code onkeyup}' attribute.
|
||||
* May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getOnkeyup() {
|
||||
return this.onkeyup;
|
||||
}
|
||||
|
@ -380,6 +415,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
* Get the value of the '{@code onkeydown}' attribute.
|
||||
* May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getOnkeydown() {
|
||||
return this.onkeydown;
|
||||
}
|
||||
|
@ -387,6 +423,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
/**
|
||||
* Get the map of dynamic attributes.
|
||||
*/
|
||||
@Nullable
|
||||
protected Map<String, Object> getDynamicAttributes() {
|
||||
return this.dynamicAttributes;
|
||||
}
|
||||
|
@ -395,7 +432,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setDynamicAttribute(String uri, String localName, Object value ) throws JspException {
|
||||
public void setDynamicAttribute(String uri, String localName, Object value) throws JspException {
|
||||
if (this.dynamicAttributes == null) {
|
||||
this.dynamicAttributes = new HashMap<>();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -18,6 +18,8 @@ package org.springframework.web.servlet.tags.form;
|
|||
|
||||
import javax.servlet.jsp.JspException;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Base class for databinding-aware JSP tags that render HTML form input element.
|
||||
*
|
||||
|
@ -63,12 +65,16 @@ public abstract class AbstractHtmlInputElementTag extends AbstractHtmlElementTag
|
|||
public static final String READONLY_ATTRIBUTE = "readonly";
|
||||
|
||||
|
||||
@Nullable
|
||||
private String onfocus;
|
||||
|
||||
@Nullable
|
||||
private String onblur;
|
||||
|
||||
@Nullable
|
||||
private String onchange;
|
||||
|
||||
@Nullable
|
||||
private String accesskey;
|
||||
|
||||
private boolean disabled;
|
||||
|
@ -87,6 +93,7 @@ public abstract class AbstractHtmlInputElementTag extends AbstractHtmlElementTag
|
|||
/**
|
||||
* Get the value of the '{@code onfocus}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getOnfocus() {
|
||||
return this.onfocus;
|
||||
}
|
||||
|
@ -102,6 +109,7 @@ public abstract class AbstractHtmlInputElementTag extends AbstractHtmlElementTag
|
|||
/**
|
||||
* Get the value of the '{@code onblur}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getOnblur() {
|
||||
return this.onblur;
|
||||
}
|
||||
|
@ -117,6 +125,7 @@ public abstract class AbstractHtmlInputElementTag extends AbstractHtmlElementTag
|
|||
/**
|
||||
* Get the value of the '{@code onchange}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getOnchange() {
|
||||
return this.onchange;
|
||||
}
|
||||
|
@ -132,6 +141,7 @@ public abstract class AbstractHtmlInputElementTag extends AbstractHtmlElementTag
|
|||
/**
|
||||
* Get the value of the '{@code accesskey}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getAccesskey() {
|
||||
return this.accesskey;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -23,6 +23,7 @@ import javax.servlet.jsp.JspException;
|
|||
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.PropertyAccessorFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
@ -50,17 +51,20 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
|
|||
* The {@link java.util.Collection}, {@link java.util.Map} or array of objects
|
||||
* used to generate the '{@code input type="checkbox/radio"}' tags.
|
||||
*/
|
||||
@Nullable
|
||||
private Object items;
|
||||
|
||||
/**
|
||||
* The name of the property mapped to the '{@code value}' attribute
|
||||
* of the '{@code input type="checkbox/radio"}' tag.
|
||||
*/
|
||||
@Nullable
|
||||
private String itemValue;
|
||||
|
||||
/**
|
||||
* The value to be displayed as part of the '{@code input type="checkbox/radio"}' tag.
|
||||
*/
|
||||
@Nullable
|
||||
private String itemLabel;
|
||||
|
||||
/**
|
||||
|
@ -71,6 +75,7 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
|
|||
/**
|
||||
* Delimiter to use between each '{@code input type="checkbox/radio"}' tags.
|
||||
*/
|
||||
@Nullable
|
||||
private String delimiter;
|
||||
|
||||
|
||||
|
@ -89,6 +94,7 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
|
|||
* Get the {@link java.util.Collection}, {@link java.util.Map} or array of objects
|
||||
* used to generate the '{@code input type="checkbox/radio"}' tags.
|
||||
*/
|
||||
@Nullable
|
||||
protected Object getItems() {
|
||||
return this.items;
|
||||
}
|
||||
|
@ -107,6 +113,7 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
|
|||
* Get the name of the property mapped to the '{@code value}' attribute
|
||||
* of the '{@code input type="checkbox/radio"}' tag.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getItemValue() {
|
||||
return this.itemValue;
|
||||
}
|
||||
|
@ -125,6 +132,7 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
|
|||
* Get the value to be displayed as part of the
|
||||
* '{@code input type="checkbox/radio"}' tag.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getItemLabel() {
|
||||
return this.itemLabel;
|
||||
}
|
||||
|
@ -142,6 +150,7 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
|
|||
* Return the delimiter to be used between each
|
||||
* '{@code input type="radio"}' tag.
|
||||
*/
|
||||
@Nullable
|
||||
public String getDelimiter() {
|
||||
return this.delimiter;
|
||||
}
|
||||
|
@ -236,8 +245,8 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
|
|||
return SKIP_BODY;
|
||||
}
|
||||
|
||||
private void writeObjectEntry(TagWriter tagWriter, String valueProperty,
|
||||
String labelProperty, Object item, int itemIndex) throws JspException {
|
||||
private void writeObjectEntry(TagWriter tagWriter, @Nullable String valueProperty,
|
||||
@Nullable String labelProperty, Object item, int itemIndex) throws JspException {
|
||||
|
||||
BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(item);
|
||||
Object renderValue;
|
||||
|
@ -254,8 +263,8 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
|
|||
writeElementTag(tagWriter, item, renderValue, renderLabel, itemIndex);
|
||||
}
|
||||
|
||||
private void writeMapEntry(TagWriter tagWriter, String valueProperty,
|
||||
String labelProperty, Map.Entry<?, ?> entry, int itemIndex) throws JspException {
|
||||
private void writeMapEntry(TagWriter tagWriter, @Nullable String valueProperty,
|
||||
@Nullable String labelProperty, Map.Entry<?, ?> entry, int itemIndex) throws JspException {
|
||||
|
||||
Object mapKey = entry.getKey();
|
||||
Object mapValue = entry.getValue();
|
||||
|
@ -268,8 +277,8 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
|
|||
writeElementTag(tagWriter, mapKey, renderValue, renderLabel, itemIndex);
|
||||
}
|
||||
|
||||
private void writeElementTag(TagWriter tagWriter, Object item, Object value, Object label, int itemIndex)
|
||||
throws JspException {
|
||||
private void writeElementTag(TagWriter tagWriter, Object item, @Nullable Object value,
|
||||
@Nullable Object label, int itemIndex) throws JspException {
|
||||
|
||||
tagWriter.startTag(getElement());
|
||||
if (itemIndex > 0) {
|
||||
|
@ -280,6 +289,7 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
|
|||
}
|
||||
tagWriter.startTag("input");
|
||||
String id = resolveId();
|
||||
Assert.state(id != null, "Attribute 'id' is required");
|
||||
writeOptionalAttribute(tagWriter, "id", id);
|
||||
writeOptionalAttribute(tagWriter, "name", getName());
|
||||
writeOptionalAttributes(tagWriter);
|
||||
|
|
|
@ -18,6 +18,9 @@ package org.springframework.web.servlet.tags.form;
|
|||
|
||||
import javax.servlet.jsp.JspException;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Abstract base class to provide common methods for implementing
|
||||
* databinding-aware JSP tags for rendering a <i>single</i>
|
||||
|
@ -33,11 +36,13 @@ public abstract class AbstractSingleCheckedElementTag extends AbstractCheckedEle
|
|||
/**
|
||||
* The value of the '{@code value}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
private Object value;
|
||||
|
||||
/**
|
||||
* The value of the '{@code label}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
private Object label;
|
||||
|
||||
|
||||
|
@ -52,6 +57,7 @@ public abstract class AbstractSingleCheckedElementTag extends AbstractCheckedEle
|
|||
/**
|
||||
* Get the value of the '{@code value}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected Object getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
@ -67,6 +73,7 @@ public abstract class AbstractSingleCheckedElementTag extends AbstractCheckedEle
|
|||
/**
|
||||
* Get the value of the '{@code label}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected Object getLabel() {
|
||||
return this.label;
|
||||
}
|
||||
|
@ -89,6 +96,7 @@ public abstract class AbstractSingleCheckedElementTag extends AbstractCheckedEle
|
|||
|
||||
Object resolvedLabel = evaluate("label", getLabel());
|
||||
if (resolvedLabel != null) {
|
||||
Assert.state(id != null, "Label id is required");
|
||||
tagWriter.startTag("label");
|
||||
tagWriter.writeAttribute("for", id);
|
||||
tagWriter.appendValue(convertToDisplayString(resolvedLabel));
|
||||
|
|
|
@ -18,6 +18,8 @@ package org.springframework.web.servlet.tags.form;
|
|||
|
||||
import javax.servlet.jsp.JspException;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.servlet.support.RequestDataValueProcessor;
|
||||
|
||||
/**
|
||||
|
@ -77,10 +79,13 @@ public class ButtonTag extends AbstractHtmlElementTag {
|
|||
public static final String DISABLED_ATTRIBUTE = "disabled";
|
||||
|
||||
|
||||
@Nullable
|
||||
private TagWriter tagWriter;
|
||||
|
||||
@Nullable
|
||||
private String name;
|
||||
|
||||
@Nullable
|
||||
private String value;
|
||||
|
||||
private boolean disabled;
|
||||
|
@ -97,6 +102,7 @@ public class ButtonTag extends AbstractHtmlElementTag {
|
|||
* Set the value of the '{@code name}' attribute.
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
@ -104,13 +110,14 @@ public class ButtonTag extends AbstractHtmlElementTag {
|
|||
/**
|
||||
* Set the value of the '{@code value}' attribute.
|
||||
*/
|
||||
public void setValue(String value) {
|
||||
public void setValue(@Nullable String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the '{@code value}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
@ -150,7 +157,7 @@ public class ButtonTag extends AbstractHtmlElementTag {
|
|||
* when the value is written.
|
||||
*/
|
||||
protected void writeValue(TagWriter tagWriter) throws JspException {
|
||||
String valueToUse = (getValue() != null) ? getValue() : getDefaultValue();
|
||||
String valueToUse = (getValue() != null ? getValue() : getDefaultValue());
|
||||
tagWriter.writeAttribute("value", processFieldValue(getName(), valueToUse, getType()));
|
||||
}
|
||||
|
||||
|
@ -176,6 +183,7 @@ public class ButtonTag extends AbstractHtmlElementTag {
|
|||
*/
|
||||
@Override
|
||||
public int doEndTag() throws JspException {
|
||||
Assert.state(this.tagWriter != null, "No TagWriter set");
|
||||
this.tagWriter.endTag();
|
||||
return EVAL_PAGE;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import javax.servlet.jsp.JspException;
|
|||
import javax.servlet.jsp.PageContext;
|
||||
import javax.servlet.jsp.tagext.BodyTag;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
@ -209,6 +210,7 @@ public class ErrorsTag extends AbstractHtmlElementBodyTag implements BodyTag {
|
|||
/**
|
||||
* Stores any value that existed in the 'errors messages' before the tag was started.
|
||||
*/
|
||||
@Nullable
|
||||
private Object oldMessages;
|
||||
|
||||
private boolean errorMessagesWereExposed;
|
||||
|
@ -270,6 +272,7 @@ public class ErrorsTag extends AbstractHtmlElementBodyTag implements BodyTag {
|
|||
* is not a validate attribute for the '{@code span}' element.
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
protected String getName() throws JspException {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ import javax.servlet.jsp.PageContext;
|
|||
import org.springframework.beans.PropertyAccessor;
|
||||
import org.springframework.core.Conventions;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
@ -288,33 +290,44 @@ public class FormTag extends AbstractHtmlElementTag {
|
|||
private static final String TYPE_ATTRIBUTE = "type";
|
||||
|
||||
|
||||
@Nullable
|
||||
private TagWriter tagWriter;
|
||||
|
||||
private String modelAttribute = DEFAULT_COMMAND_NAME;
|
||||
|
||||
@Nullable
|
||||
private String name;
|
||||
|
||||
@Nullable
|
||||
private String action;
|
||||
|
||||
@Nullable
|
||||
private String servletRelativeAction;
|
||||
|
||||
private String method = DEFAULT_METHOD;
|
||||
|
||||
@Nullable
|
||||
private String target;
|
||||
|
||||
@Nullable
|
||||
private String enctype;
|
||||
|
||||
@Nullable
|
||||
private String acceptCharset;
|
||||
|
||||
@Nullable
|
||||
private String onsubmit;
|
||||
|
||||
@Nullable
|
||||
private String onreset;
|
||||
|
||||
@Nullable
|
||||
private String autocomplete;
|
||||
|
||||
private String methodParam = DEFAULT_METHOD_PARAM;
|
||||
|
||||
/** Caching a previous nested path, so that it may be reset. */
|
||||
@Nullable
|
||||
private String previousNestedPath;
|
||||
|
||||
|
||||
|
@ -347,6 +360,7 @@ public class FormTag extends AbstractHtmlElementTag {
|
|||
* Get the value of the '{@code name}' attribute.
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
protected String getName() throws JspException {
|
||||
return this.name;
|
||||
}
|
||||
|
@ -355,13 +369,14 @@ public class FormTag extends AbstractHtmlElementTag {
|
|||
* Set the value of the '{@code action}' attribute.
|
||||
* <p>May be a runtime expression.
|
||||
*/
|
||||
public void setAction(String action) {
|
||||
public void setAction(@Nullable String action) {
|
||||
this.action = (action != null ? action : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the '{@code action}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getAction() {
|
||||
return this.action;
|
||||
}
|
||||
|
@ -372,14 +387,15 @@ public class FormTag extends AbstractHtmlElementTag {
|
|||
* <p>May be a runtime expression.
|
||||
* @since 3.2.3
|
||||
*/
|
||||
public void setServletRelativeAction(String servletRelativeAction) {
|
||||
this.servletRelativeAction = (servletRelativeAction != null ? servletRelativeAction : "");
|
||||
public void setServletRelativeAction(@Nullable String servletRelativeAction) {
|
||||
this.servletRelativeAction = servletRelativeAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the servlet-relative value of the '{@code action}' attribute.
|
||||
* @since 3.2.3
|
||||
*/
|
||||
@Nullable
|
||||
protected String getServletRelativeAction() {
|
||||
return this.servletRelativeAction;
|
||||
}
|
||||
|
@ -410,6 +426,7 @@ public class FormTag extends AbstractHtmlElementTag {
|
|||
/**
|
||||
* Get the value of the '{@code target}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
public String getTarget() {
|
||||
return this.target;
|
||||
}
|
||||
|
@ -425,6 +442,7 @@ public class FormTag extends AbstractHtmlElementTag {
|
|||
/**
|
||||
* Get the value of the '{@code enctype}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getEnctype() {
|
||||
return this.enctype;
|
||||
}
|
||||
|
@ -440,6 +458,7 @@ public class FormTag extends AbstractHtmlElementTag {
|
|||
/**
|
||||
* Get the value of the '{@code acceptCharset}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getAcceptCharset() {
|
||||
return this.acceptCharset;
|
||||
}
|
||||
|
@ -455,6 +474,7 @@ public class FormTag extends AbstractHtmlElementTag {
|
|||
/**
|
||||
* Get the value of the '{@code onsubmit}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getOnsubmit() {
|
||||
return this.onsubmit;
|
||||
}
|
||||
|
@ -470,6 +490,7 @@ public class FormTag extends AbstractHtmlElementTag {
|
|||
/**
|
||||
* Get the value of the '{@code onreset}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getOnreset() {
|
||||
return this.onreset;
|
||||
}
|
||||
|
@ -485,6 +506,7 @@ public class FormTag extends AbstractHtmlElementTag {
|
|||
/**
|
||||
* Get the value of the '{@code autocomplete}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getAutocomplete() {
|
||||
return this.autocomplete;
|
||||
}
|
||||
|
@ -670,6 +692,7 @@ public class FormTag extends AbstractHtmlElementTag {
|
|||
if (processor != null && request instanceof HttpServletRequest) {
|
||||
writeHiddenFields(processor.getExtraHiddenFields((HttpServletRequest) request));
|
||||
}
|
||||
Assert.state(this.tagWriter != null, "No TagWriter set");
|
||||
this.tagWriter.endTag();
|
||||
return EVAL_PAGE;
|
||||
}
|
||||
|
@ -677,8 +700,9 @@ public class FormTag extends AbstractHtmlElementTag {
|
|||
/**
|
||||
* Writes the given values as hidden fields.
|
||||
*/
|
||||
private void writeHiddenFields(Map<String, String> hiddenFields) throws JspException {
|
||||
private void writeHiddenFields(@Nullable Map<String, String> hiddenFields) throws JspException {
|
||||
if (!CollectionUtils.isEmpty(hiddenFields)) {
|
||||
Assert.state(this.tagWriter != null, "No TagWriter set");
|
||||
this.tagWriter.appendValue("<div>\n");
|
||||
for (String name : hiddenFields.keySet()) {
|
||||
this.tagWriter.appendValue("<input type=\"hidden\" ");
|
||||
|
|
|
@ -16,8 +16,11 @@
|
|||
|
||||
package org.springframework.web.servlet.tags.form;
|
||||
|
||||
import java.util.Map;
|
||||
import javax.servlet.jsp.JspException;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* The {@code <input>} tag renders an HTML 'input' tag with type 'text' using
|
||||
* the bound value.
|
||||
|
@ -241,19 +244,22 @@ public class InputTag extends AbstractHtmlInputElementTag {
|
|||
|
||||
public static final String ONSELECT_ATTRIBUTE = "onselect";
|
||||
|
||||
public static final String READONLY_ATTRIBUTE = "readonly";
|
||||
|
||||
public static final String AUTOCOMPLETE_ATTRIBUTE = "autocomplete";
|
||||
|
||||
|
||||
@Nullable
|
||||
private String size;
|
||||
|
||||
@Nullable
|
||||
private String maxlength;
|
||||
|
||||
@Nullable
|
||||
private String alt;
|
||||
|
||||
@Nullable
|
||||
private String onselect;
|
||||
|
||||
@Nullable
|
||||
private String autocomplete;
|
||||
|
||||
|
||||
|
@ -268,6 +274,7 @@ public class InputTag extends AbstractHtmlInputElementTag {
|
|||
/**
|
||||
* Get the value of the '{@code size}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getSize() {
|
||||
return this.size;
|
||||
}
|
||||
|
@ -283,6 +290,7 @@ public class InputTag extends AbstractHtmlInputElementTag {
|
|||
/**
|
||||
* Get the value of the '{@code maxlength}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getMaxlength() {
|
||||
return this.maxlength;
|
||||
}
|
||||
|
@ -298,6 +306,7 @@ public class InputTag extends AbstractHtmlInputElementTag {
|
|||
/**
|
||||
* Get the value of the '{@code alt}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getAlt() {
|
||||
return this.alt;
|
||||
}
|
||||
|
@ -313,6 +322,7 @@ public class InputTag extends AbstractHtmlInputElementTag {
|
|||
/**
|
||||
* Get the value of the '{@code onselect}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getOnselect() {
|
||||
return this.onselect;
|
||||
}
|
||||
|
@ -328,6 +338,7 @@ public class InputTag extends AbstractHtmlInputElementTag {
|
|||
/**
|
||||
* Get the value of the '{@code autocomplete}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getAutocomplete() {
|
||||
return this.autocomplete;
|
||||
}
|
||||
|
@ -343,7 +354,8 @@ public class InputTag extends AbstractHtmlInputElementTag {
|
|||
tagWriter.startTag("input");
|
||||
|
||||
writeDefaultAttributes(tagWriter);
|
||||
if (!hasDynamicTypeAttribute()) {
|
||||
Map<String, Object> attributes = getDynamicAttributes();
|
||||
if (attributes == null || !attributes.containsKey("type")) {
|
||||
tagWriter.writeAttribute("type", getType());
|
||||
}
|
||||
writeValue(tagWriter);
|
||||
|
@ -359,10 +371,6 @@ public class InputTag extends AbstractHtmlInputElementTag {
|
|||
return SKIP_BODY;
|
||||
}
|
||||
|
||||
private boolean hasDynamicTypeAttribute() {
|
||||
return getDynamicAttributes() != null && getDynamicAttributes().containsKey("type");
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the '{@code value}' attribute to the supplied {@link TagWriter}.
|
||||
* Subclasses may choose to override this implementation to control exactly
|
||||
|
@ -370,7 +378,14 @@ public class InputTag extends AbstractHtmlInputElementTag {
|
|||
*/
|
||||
protected void writeValue(TagWriter tagWriter) throws JspException {
|
||||
String value = getDisplayString(getBoundValue(), getPropertyEditor());
|
||||
String type = hasDynamicTypeAttribute() ? (String) getDynamicAttributes().get("type") : getType();
|
||||
String type = null;
|
||||
Map<String, Object> attributes = getDynamicAttributes();
|
||||
if (attributes != null) {
|
||||
type = (String) getDynamicAttributes().get("type");
|
||||
}
|
||||
if (type == null) {
|
||||
type = getType();
|
||||
}
|
||||
tagWriter.writeAttribute("value", processFieldValue(getName(), value, type));
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.springframework.web.servlet.tags.form;
|
|||
|
||||
import javax.servlet.jsp.JspException;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
@ -190,21 +191,21 @@ public class LabelTag extends AbstractHtmlElementTag {
|
|||
* The {@link TagWriter} instance being used.
|
||||
* <p>Stored so we can close the tag on {@link #doEndTag()}.
|
||||
*/
|
||||
@Nullable
|
||||
private TagWriter tagWriter;
|
||||
|
||||
/**
|
||||
* The value of the '{@code for}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
private String forId;
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of the '{@code for}' attribute.
|
||||
* <p>Defaults to the value of {@link #getPath}; may be a runtime expression.
|
||||
* @throws IllegalArgumentException if the supplied value is {@code null}
|
||||
*/
|
||||
public void setFor(String forId) {
|
||||
Assert.notNull(forId, "'forId' must not be null");
|
||||
this.forId = forId;
|
||||
}
|
||||
|
||||
|
@ -212,7 +213,8 @@ public class LabelTag extends AbstractHtmlElementTag {
|
|||
* Get the value of the '{@code id}' attribute.
|
||||
* <p>May be a runtime expression.
|
||||
*/
|
||||
public String getFor() {
|
||||
@Nullable
|
||||
protected String getFor() {
|
||||
return this.forId;
|
||||
}
|
||||
|
||||
|
@ -239,6 +241,7 @@ public class LabelTag extends AbstractHtmlElementTag {
|
|||
* @return the value for the HTML '{@code name}' attribute
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
protected String getName() throws JspException {
|
||||
// This also suppresses the 'id' attribute (which is okay for a <label/>)
|
||||
return null;
|
||||
|
@ -273,6 +276,7 @@ public class LabelTag extends AbstractHtmlElementTag {
|
|||
*/
|
||||
@Override
|
||||
public int doEndTag() throws JspException {
|
||||
Assert.state(this.tagWriter != null, "No TagWriter set");
|
||||
this.tagWriter.endTag();
|
||||
return EVAL_PAGE;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -20,7 +20,7 @@ import javax.servlet.jsp.JspException;
|
|||
import javax.servlet.jsp.tagext.BodyContent;
|
||||
import javax.servlet.jsp.tagext.BodyTag;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.servlet.support.BindStatus;
|
||||
import org.springframework.web.util.TagUtils;
|
||||
|
||||
|
@ -228,15 +228,19 @@ public class OptionTag extends AbstractHtmlElementBodyTag implements BodyTag {
|
|||
/**
|
||||
* The 'value' attribute of the rendered HTML {@code <option>} tag.
|
||||
*/
|
||||
@Nullable
|
||||
private Object value;
|
||||
|
||||
/**
|
||||
* The text body of the rendered HTML {@code <option>} tag.
|
||||
*/
|
||||
@Nullable
|
||||
private String label;
|
||||
|
||||
@Nullable
|
||||
private Object oldValue;
|
||||
|
||||
@Nullable
|
||||
private Object oldDisplayValue;
|
||||
|
||||
private boolean disabled;
|
||||
|
@ -252,6 +256,7 @@ public class OptionTag extends AbstractHtmlElementBodyTag implements BodyTag {
|
|||
/**
|
||||
* Get the 'value' attribute of the rendered HTML {@code <option>} tag.
|
||||
*/
|
||||
@Nullable
|
||||
protected Object getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
@ -275,13 +280,13 @@ public class OptionTag extends AbstractHtmlElementBodyTag implements BodyTag {
|
|||
* <p>May be a runtime expression.
|
||||
*/
|
||||
public void setLabel(String label) {
|
||||
Assert.notNull(label, "'label' must not be null");
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text body of the rendered HTML {@code <option>} tag.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getLabel() {
|
||||
return this.label;
|
||||
}
|
||||
|
@ -365,8 +370,8 @@ public class OptionTag extends AbstractHtmlElementBodyTag implements BodyTag {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the label for this '{@code option}' element.
|
||||
* If the {@link #setLabel label} property is set then the resolved value
|
||||
* Return the value of the label for this '{@code option}' element.
|
||||
* <p>If the {@link #setLabel label} property is set then the resolved value
|
||||
* of that property is used, otherwise the value of the {@code resolvedValue}
|
||||
* argument is used.
|
||||
*/
|
||||
|
@ -388,6 +393,7 @@ public class OptionTag extends AbstractHtmlElementBodyTag implements BodyTag {
|
|||
return SelectedValueComparator.isSelected(getBindStatus(), resolvedValue);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Object resolveValue() throws JspException {
|
||||
return evaluate(VALUE_VARIABLE_NAME, getValue());
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import javax.servlet.jsp.JspException;
|
|||
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.PropertyAccessorFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.servlet.support.BindStatus;
|
||||
|
@ -92,15 +93,17 @@ class OptionWriter {
|
|||
|
||||
private final BindStatus bindStatus;
|
||||
|
||||
@Nullable
|
||||
private final String valueProperty;
|
||||
|
||||
@Nullable
|
||||
private final String labelProperty;
|
||||
|
||||
private final boolean htmlEscape;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@code OptionWriter} for the supplied {@code objectSource}.
|
||||
* Create a new {@code OptionWriter} for the supplied {@code objectSource}.
|
||||
* @param optionSource the source of the {@code options} (never {@code null})
|
||||
* @param bindStatus the {@link BindStatus} for the bound value (never {@code null})
|
||||
* @param valueProperty the name of the property used to render {@code option} values
|
||||
|
@ -108,8 +111,8 @@ class OptionWriter {
|
|||
* @param labelProperty the name of the property used to render {@code option} labels
|
||||
* (optional)
|
||||
*/
|
||||
public OptionWriter(
|
||||
Object optionSource, BindStatus bindStatus, String valueProperty, String labelProperty, boolean htmlEscape) {
|
||||
public OptionWriter(Object optionSource, BindStatus bindStatus,
|
||||
@Nullable String valueProperty, @Nullable String labelProperty, boolean htmlEscape) {
|
||||
|
||||
Assert.notNull(optionSource, "'optionSource' must not be null");
|
||||
Assert.notNull(bindStatus, "'bindStatus' must not be null");
|
||||
|
@ -145,7 +148,7 @@ class OptionWriter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Renders the inner '{@code option}' tags using the {@link #optionSource}.
|
||||
* Render the inner '{@code option}' tags using the {@link #optionSource}.
|
||||
* @see #doRenderFromCollection(java.util.Collection, TagWriter)
|
||||
*/
|
||||
private void renderFromArray(TagWriter tagWriter) throws JspException {
|
||||
|
@ -153,7 +156,7 @@ class OptionWriter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Renders the inner '{@code option}' tags using the supplied
|
||||
* Render the inner '{@code option}' tags using the supplied
|
||||
* {@link Map} as the source.
|
||||
* @see #renderOption(TagWriter, Object, Object, Object)
|
||||
*/
|
||||
|
@ -173,7 +176,7 @@ class OptionWriter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Renders the inner '{@code option}' tags using the {@link #optionSource}.
|
||||
* Render the inner '{@code option}' tags using the {@link #optionSource}.
|
||||
* @see #doRenderFromCollection(java.util.Collection, TagWriter)
|
||||
*/
|
||||
private void renderFromCollection(TagWriter tagWriter) throws JspException {
|
||||
|
@ -181,7 +184,7 @@ class OptionWriter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Renders the inner '{@code option}' tags using the {@link #optionSource}.
|
||||
* Render the inner '{@code option}' tags using the {@link #optionSource}.
|
||||
* @see #doRenderFromCollection(java.util.Collection, TagWriter)
|
||||
*/
|
||||
private void renderFromEnum(TagWriter tagWriter) throws JspException {
|
||||
|
@ -189,7 +192,7 @@ class OptionWriter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Renders the inner '{@code option}' tags using the supplied {@link Collection} of
|
||||
* Render the inner '{@code option}' tags using the supplied {@link Collection} of
|
||||
* objects as the source. The value of the {@link #valueProperty} field is used
|
||||
* when rendering the '{@code value}' of the '{@code option}' and the value of the
|
||||
* {@link #labelProperty} property is used when rendering the label.
|
||||
|
@ -213,10 +216,12 @@ class OptionWriter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Renders an HTML '{@code option}' with the supplied value and label. Marks the
|
||||
* Render an HTML '{@code option}' with the supplied value and label. Marks the
|
||||
* value as 'selected' if either the item itself or its value match the bound value.
|
||||
*/
|
||||
private void renderOption(TagWriter tagWriter, Object item, Object value, Object label) throws JspException {
|
||||
private void renderOption(TagWriter tagWriter, Object item, @Nullable Object value, @Nullable Object label)
|
||||
throws JspException {
|
||||
|
||||
tagWriter.startTag("option");
|
||||
writeCommonAttributes(tagWriter);
|
||||
|
||||
|
@ -239,17 +244,17 @@ class OptionWriter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Determines the display value of the supplied {@code Object},
|
||||
* Determine the display value of the supplied {@code Object},
|
||||
* HTML-escaped as required.
|
||||
*/
|
||||
private String getDisplayString(Object value) {
|
||||
private String getDisplayString(@Nullable Object value) {
|
||||
PropertyEditor editor = (value != null ? this.bindStatus.findEditor(value.getClass()) : null);
|
||||
return ValueFormatter.getDisplayString(value, editor, this.htmlEscape);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the option value before it is written.
|
||||
* The default implementation simply returns the same value unchanged.
|
||||
* <p>The default implementation simply returns the same value unchanged.
|
||||
*/
|
||||
protected String processOptionValue(String resolvedValue) {
|
||||
return resolvedValue;
|
||||
|
@ -257,9 +262,9 @@ class OptionWriter {
|
|||
|
||||
/**
|
||||
* Determine whether the supplied values matched the selected value.
|
||||
* Delegates to {@link SelectedValueComparator#isSelected}.
|
||||
* <p>Delegates to {@link SelectedValueComparator#isSelected}.
|
||||
*/
|
||||
private boolean isOptionSelected(Object resolvedValue) {
|
||||
private boolean isOptionSelected(@Nullable Object resolvedValue) {
|
||||
return SelectedValueComparator.isSelected(this.bindStatus, resolvedValue);
|
||||
}
|
||||
|
||||
|
@ -271,7 +276,7 @@ class OptionWriter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Writes default attributes configured to the supplied {@link TagWriter}.
|
||||
* Write default attributes configured to the supplied {@link TagWriter}.
|
||||
*/
|
||||
protected void writeCommonAttributes(TagWriter tagWriter) throws JspException {
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -18,6 +18,7 @@ package org.springframework.web.servlet.tags.form;
|
|||
|
||||
import javax.servlet.jsp.JspException;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
@ -196,18 +197,21 @@ public class OptionsTag extends AbstractHtmlElementTag {
|
|||
* The {@link java.util.Collection}, {@link java.util.Map} or array of
|
||||
* objects used to generate the inner '{@code option}' tags.
|
||||
*/
|
||||
@Nullable
|
||||
private Object items;
|
||||
|
||||
/**
|
||||
* The name of the property mapped to the '{@code value}' attribute
|
||||
* of the '{@code option}' tag.
|
||||
*/
|
||||
@Nullable
|
||||
private String itemValue;
|
||||
|
||||
/**
|
||||
* The name of the property mapped to the inner text of the
|
||||
* '{@code option}' tag.
|
||||
*/
|
||||
@Nullable
|
||||
private String itemLabel;
|
||||
|
||||
private boolean disabled;
|
||||
|
@ -229,6 +233,7 @@ public class OptionsTag extends AbstractHtmlElementTag {
|
|||
* of objects used to generate the inner '{@code option}' tags.
|
||||
* <p>Typically a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected Object getItems() {
|
||||
return this.items;
|
||||
}
|
||||
|
@ -248,6 +253,7 @@ public class OptionsTag extends AbstractHtmlElementTag {
|
|||
* Return the name of the property mapped to the '{@code value}'
|
||||
* attribute of the '{@code option}' tag.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getItemValue() {
|
||||
return this.itemValue;
|
||||
}
|
||||
|
@ -265,6 +271,7 @@ public class OptionsTag extends AbstractHtmlElementTag {
|
|||
* Get the name of the property mapped to the label (inner text) of the
|
||||
* '{@code option}' tag.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getItemLabel() {
|
||||
return this.itemLabel;
|
||||
}
|
||||
|
@ -342,9 +349,12 @@ public class OptionsTag extends AbstractHtmlElementTag {
|
|||
*/
|
||||
private class OptionsWriter extends OptionWriter {
|
||||
|
||||
@Nullable
|
||||
private final String selectName;
|
||||
|
||||
public OptionsWriter(String selectName, Object optionSource, String valueProperty, String labelProperty) {
|
||||
public OptionsWriter(@Nullable String selectName, Object optionSource,
|
||||
@Nullable String valueProperty, @Nullable String labelProperty) {
|
||||
|
||||
super(optionSource, getBindStatus(), valueProperty, labelProperty, isHtmlEscape());
|
||||
this.selectName = selectName;
|
||||
}
|
||||
|
@ -364,7 +374,6 @@ public class OptionsTag extends AbstractHtmlElementTag {
|
|||
protected String processOptionValue(String value) {
|
||||
return processFieldValue(this.selectName, value, "option");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Collection;
|
|||
import java.util.Map;
|
||||
import javax.servlet.jsp.JspException;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.servlet.support.BindStatus;
|
||||
|
@ -255,39 +256,45 @@ public class SelectTag extends AbstractHtmlInputElementTag {
|
|||
|
||||
|
||||
/**
|
||||
* The {@link Collection}, {@link Map} or array of objects used to generate the inner
|
||||
* '{@code option}' tags.
|
||||
* The {@link Collection}, {@link Map} or array of objects used to generate
|
||||
* the inner '{@code option}' tags.
|
||||
*/
|
||||
@Nullable
|
||||
private Object items;
|
||||
|
||||
/**
|
||||
* The name of the property mapped to the '{@code value}' attribute
|
||||
* of the '{@code option}' tag.
|
||||
*/
|
||||
@Nullable
|
||||
private String itemValue;
|
||||
|
||||
/**
|
||||
* The name of the property mapped to the inner text of the
|
||||
* '{@code option}' tag.
|
||||
*/
|
||||
@Nullable
|
||||
private String itemLabel;
|
||||
|
||||
/**
|
||||
* The value of the HTML '{@code size}' attribute rendered
|
||||
* on the final '{@code select}' element.
|
||||
*/
|
||||
@Nullable
|
||||
private String size;
|
||||
|
||||
/**
|
||||
* Indicates whether or not the '{@code select}' tag allows
|
||||
* multiple-selections.
|
||||
*/
|
||||
@Nullable
|
||||
private Object multiple;
|
||||
|
||||
/**
|
||||
* The {@link TagWriter} instance that the output is being written.
|
||||
* <p>Only used in conjunction with nested {@link OptionTag OptionTags}.
|
||||
*/
|
||||
@Nullable
|
||||
private TagWriter tagWriter;
|
||||
|
||||
|
||||
|
@ -299,7 +306,7 @@ public class SelectTag extends AbstractHtmlInputElementTag {
|
|||
* <p>Typically a runtime expression.
|
||||
* @param items the items that comprise the options of this selection
|
||||
*/
|
||||
public void setItems(Object items) {
|
||||
public void setItems(@Nullable Object items) {
|
||||
this.items = (items != null ? items : EMPTY);
|
||||
}
|
||||
|
||||
|
@ -307,6 +314,7 @@ public class SelectTag extends AbstractHtmlInputElementTag {
|
|||
* Get the value of the '{@code items}' attribute.
|
||||
* <p>May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected Object getItems() {
|
||||
return this.items;
|
||||
}
|
||||
|
@ -326,6 +334,7 @@ public class SelectTag extends AbstractHtmlInputElementTag {
|
|||
* Get the value of the '{@code itemValue}' attribute.
|
||||
* <p>May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getItemValue() {
|
||||
return this.itemValue;
|
||||
}
|
||||
|
@ -343,6 +352,7 @@ public class SelectTag extends AbstractHtmlInputElementTag {
|
|||
* Get the value of the '{@code itemLabel}' attribute.
|
||||
* <p>May be a runtime expression.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getItemLabel() {
|
||||
return this.itemLabel;
|
||||
}
|
||||
|
@ -358,6 +368,7 @@ public class SelectTag extends AbstractHtmlInputElementTag {
|
|||
/**
|
||||
* Get the value of the '{@code size}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getSize() {
|
||||
return this.size;
|
||||
}
|
||||
|
@ -374,6 +385,7 @@ public class SelectTag extends AbstractHtmlInputElementTag {
|
|||
* Get the value of the HTML '{@code multiple}' attribute rendered
|
||||
* on the final '{@code select}' element.
|
||||
*/
|
||||
@Nullable
|
||||
protected Object getMultiple() {
|
||||
return this.multiple;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -21,6 +21,7 @@ import java.util.Collection;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.servlet.support.BindStatus;
|
||||
|
@ -59,11 +60,7 @@ abstract class SelectedValueComparator {
|
|||
* the supplied {@link BindStatus}. Equality in this case differs from standard Java equality and
|
||||
* is described in more detail <a href="#equality-contract">here</a>.
|
||||
*/
|
||||
public static boolean isSelected(BindStatus bindStatus, Object candidateValue) {
|
||||
if (bindStatus == null) {
|
||||
return (candidateValue == null);
|
||||
}
|
||||
|
||||
public static boolean isSelected(BindStatus bindStatus, @Nullable Object candidateValue) {
|
||||
// Check obvious equality matches with the candidate first,
|
||||
// both with the rendered value and with the original value.
|
||||
Object boundValue = bindStatus.getValue();
|
||||
|
@ -85,14 +82,16 @@ abstract class SelectedValueComparator {
|
|||
// Non-null value but no obvious equality with the candidate value:
|
||||
// go into more exhaustive comparisons.
|
||||
boolean selected = false;
|
||||
if (boundValue.getClass().isArray()) {
|
||||
selected = collectionCompare(CollectionUtils.arrayToList(boundValue), candidateValue, bindStatus);
|
||||
}
|
||||
else if (boundValue instanceof Collection) {
|
||||
selected = collectionCompare((Collection<?>) boundValue, candidateValue, bindStatus);
|
||||
}
|
||||
else if (boundValue instanceof Map) {
|
||||
selected = mapCompare((Map<?, ?>) boundValue, candidateValue, bindStatus);
|
||||
if (candidateValue != null) {
|
||||
if (boundValue.getClass().isArray()) {
|
||||
selected = collectionCompare(CollectionUtils.arrayToList(boundValue), candidateValue, bindStatus);
|
||||
}
|
||||
else if (boundValue instanceof Collection) {
|
||||
selected = collectionCompare((Collection<?>) boundValue, candidateValue, bindStatus);
|
||||
}
|
||||
else if (boundValue instanceof Map) {
|
||||
selected = mapCompare((Map<?, ?>) boundValue, candidateValue, bindStatus);
|
||||
}
|
||||
}
|
||||
if (!selected) {
|
||||
selected = exhaustiveCompare(boundValue, candidateValue, bindStatus.getEditor(), null);
|
||||
|
@ -100,8 +99,8 @@ abstract class SelectedValueComparator {
|
|||
return selected;
|
||||
}
|
||||
|
||||
private static boolean collectionCompare(Collection<?> boundCollection, Object candidateValue,
|
||||
BindStatus bindStatus) {
|
||||
private static boolean collectionCompare(
|
||||
Collection<?> boundCollection, Object candidateValue, BindStatus bindStatus) {
|
||||
try {
|
||||
if (boundCollection.contains(candidateValue)) {
|
||||
return true;
|
||||
|
@ -128,7 +127,7 @@ abstract class SelectedValueComparator {
|
|||
private static boolean exhaustiveCollectionCompare(
|
||||
Collection<?> collection, Object candidateValue, BindStatus bindStatus) {
|
||||
|
||||
Map<PropertyEditor, Object> convertedValueCache = new HashMap<>(1);
|
||||
Map<PropertyEditor, Object> convertedValueCache = new HashMap<>();
|
||||
PropertyEditor editor = null;
|
||||
boolean candidateIsString = (candidateValue instanceof String);
|
||||
if (!candidateIsString) {
|
||||
|
@ -145,8 +144,8 @@ abstract class SelectedValueComparator {
|
|||
return false;
|
||||
}
|
||||
|
||||
private static boolean exhaustiveCompare(Object boundValue, Object candidate,
|
||||
PropertyEditor editor, Map<PropertyEditor, Object> convertedValueCache) {
|
||||
private static boolean exhaustiveCompare(@Nullable Object boundValue, @Nullable Object candidate,
|
||||
@Nullable PropertyEditor editor, @Nullable Map<PropertyEditor, Object> convertedValueCache) {
|
||||
|
||||
String candidateDisplayString = ValueFormatter.getDisplayString(candidate, editor, false);
|
||||
if (boundValue != null && boundValue.getClass().isEnum()) {
|
||||
|
|
|
@ -195,7 +195,7 @@ public class TagWriter {
|
|||
}
|
||||
|
||||
private TagStateEntry currentState() {
|
||||
return this.tagState.peek();
|
||||
return this.tagState.element();
|
||||
}
|
||||
|
||||
|
||||
|
@ -232,8 +232,10 @@ public class TagWriter {
|
|||
*/
|
||||
private static final class SafeWriter {
|
||||
|
||||
@Nullable
|
||||
private PageContext pageContext;
|
||||
|
||||
@Nullable
|
||||
private Writer writer;
|
||||
|
||||
public SafeWriter(PageContext pageContext) {
|
||||
|
@ -255,7 +257,9 @@ public class TagWriter {
|
|||
}
|
||||
|
||||
private Writer getWriterToUse() {
|
||||
return (this.pageContext != null ? this.pageContext.getOut() : this.writer);
|
||||
Writer writer = (this.pageContext != null ? this.pageContext.getOut() : this.writer);
|
||||
Assert.state(writer != null, "No Writer available");
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ package org.springframework.web.servlet.tags.form;
|
|||
|
||||
import javax.servlet.jsp.JspException;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* The {@code <textarea>} tag renders an HTML 'textarea'.
|
||||
*
|
||||
|
@ -225,13 +227,14 @@ public class TextareaTag extends AbstractHtmlInputElementTag {
|
|||
|
||||
public static final String ONSELECT_ATTRIBUTE = "onselect";
|
||||
|
||||
public static final String READONLY_ATTRIBUTE = "readonly";
|
||||
|
||||
|
||||
@Nullable
|
||||
private String rows;
|
||||
|
||||
@Nullable
|
||||
private String cols;
|
||||
|
||||
@Nullable
|
||||
private String onselect;
|
||||
|
||||
|
||||
|
@ -246,6 +249,7 @@ public class TextareaTag extends AbstractHtmlInputElementTag {
|
|||
/**
|
||||
* Get the value of the '{@code rows}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getRows() {
|
||||
return this.rows;
|
||||
}
|
||||
|
@ -261,6 +265,7 @@ public class TextareaTag extends AbstractHtmlInputElementTag {
|
|||
/**
|
||||
* Get the value of the '{@code cols}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getCols() {
|
||||
return this.cols;
|
||||
}
|
||||
|
@ -276,6 +281,7 @@ public class TextareaTag extends AbstractHtmlInputElementTag {
|
|||
/**
|
||||
* Get the value of the '{@code onselect}' attribute.
|
||||
*/
|
||||
@Nullable
|
||||
protected String getOnselect() {
|
||||
return this.onselect;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -18,6 +18,7 @@ package org.springframework.web.servlet.tags.form;
|
|||
|
||||
import java.beans.PropertyEditor;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.util.HtmlUtils;
|
||||
|
||||
|
@ -43,7 +44,7 @@ abstract class ValueFormatter {
|
|||
* as required. This version is <strong>not</strong> {@link PropertyEditor}-aware.
|
||||
* @see #getDisplayString(Object, java.beans.PropertyEditor, boolean)
|
||||
*/
|
||||
public static String getDisplayString(Object value, boolean htmlEscape) {
|
||||
public static String getDisplayString(@Nullable Object value, boolean htmlEscape) {
|
||||
String displayValue = ObjectUtils.getDisplayString(value);
|
||||
return (htmlEscape ? HtmlUtils.htmlEscape(displayValue) : displayValue);
|
||||
}
|
||||
|
@ -55,7 +56,9 @@ abstract class ValueFormatter {
|
|||
* to obtain the display value.
|
||||
* @see #getDisplayString(Object, boolean)
|
||||
*/
|
||||
public static String getDisplayString(Object value, PropertyEditor propertyEditor, boolean htmlEscape) {
|
||||
public static String getDisplayString(
|
||||
@Nullable Object value, @Nullable PropertyEditor propertyEditor, boolean htmlEscape) {
|
||||
|
||||
if (propertyEditor != null && !(value instanceof String)) {
|
||||
try {
|
||||
propertyEditor.setValue(value);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/**
|
||||
* Spring's form tag library for JSP 2.0+.
|
||||
* Supports JSP view implementations for Spring's web MVC framework.
|
||||
* Spring's form tag library for JSP views in Spring's Web MVC framework.
|
||||
* For more details on each tag, see the list of tags below with links to
|
||||
* individual tag classes, or check the {@code spring-form.tld} file:
|
||||
*
|
||||
|
@ -22,4 +21,9 @@
|
|||
* <li>{@link org.springframework.web.servlet.tags.form.TextareaTag The textarea tag}
|
||||
* </ul>
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
package org.springframework.web.servlet.tags.form;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
|
|
Loading…
Reference in New Issue