001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.servlet.tags.form; 018 019import javax.servlet.jsp.JspException; 020 021import org.springframework.util.Assert; 022import org.springframework.util.StringUtils; 023 024/** 025 * Databinding-aware JSP tag for rendering an HTML '{@code label}' element 026 * that defines text that is associated with a single form element. 027 * 028 * <p>See the "formTags" showcase application that ships with the 029 * full Spring distribution for an example of this class in action. 030 * 031 * @author Rob Harrop 032 * @author Juergen Hoeller 033 * @since 2.0 034 */ 035@SuppressWarnings("serial") 036public class LabelTag extends AbstractHtmlElementTag { 037 038 /** 039 * The HTML '{@code label}' tag. 040 */ 041 private static final String LABEL_TAG = "label"; 042 043 /** 044 * The name of the '{@code for}' attribute. 045 */ 046 private static final String FOR_ATTRIBUTE = "for"; 047 048 049 /** 050 * The {@link TagWriter} instance being used. 051 * <p>Stored so we can close the tag on {@link #doEndTag()}. 052 */ 053 private TagWriter tagWriter; 054 055 /** 056 * The value of the '{@code for}' attribute. 057 */ 058 private String forId; 059 060 061 /** 062 * Set the value of the '{@code for}' attribute. 063 * <p>Defaults to the value of {@link #getPath}; may be a runtime expression. 064 * @throws IllegalArgumentException if the supplied value is {@code null} 065 */ 066 public void setFor(String forId) { 067 Assert.notNull(forId, "'forId' must not be null"); 068 this.forId = forId; 069 } 070 071 /** 072 * Get the value of the '{@code id}' attribute. 073 * <p>May be a runtime expression. 074 */ 075 public String getFor() { 076 return this.forId; 077 } 078 079 080 /** 081 * Writes the opening '{@code label}' tag and forces a block tag so 082 * that body content is written correctly. 083 * @return {@link javax.servlet.jsp.tagext.Tag#EVAL_BODY_INCLUDE} 084 */ 085 @Override 086 protected int writeTagContent(TagWriter tagWriter) throws JspException { 087 tagWriter.startTag(LABEL_TAG); 088 tagWriter.writeAttribute(FOR_ATTRIBUTE, resolveFor()); 089 writeDefaultAttributes(tagWriter); 090 tagWriter.forceBlock(); 091 this.tagWriter = tagWriter; 092 return EVAL_BODY_INCLUDE; 093 } 094 095 /** 096 * Overrides {@code #getName()} to always return {@code null}, 097 * because the '{@code name}' attribute is not supported by the 098 * '{@code label}' tag. 099 * @return the value for the HTML '{@code name}' attribute 100 */ 101 @Override 102 protected String getName() throws JspException { 103 // This also suppresses the 'id' attribute (which is okay for a <label/>) 104 return null; 105 } 106 107 /** 108 * Determine the '{@code for}' attribute value for this tag, 109 * autogenerating one if none specified. 110 * @see #getFor() 111 * @see #autogenerateFor() 112 */ 113 protected String resolveFor() throws JspException { 114 if (StringUtils.hasText(this.forId)) { 115 return getDisplayString(evaluate(FOR_ATTRIBUTE, this.forId)); 116 } 117 else { 118 return autogenerateFor(); 119 } 120 } 121 122 /** 123 * Autogenerate the '{@code for}' attribute value for this tag. 124 * <p>The default implementation delegates to {@link #getPropertyPath()}, 125 * deleting invalid characters (such as "[" or "]"). 126 */ 127 protected String autogenerateFor() throws JspException { 128 return StringUtils.deleteAny(getPropertyPath(), "[]"); 129 } 130 131 /** 132 * Close the '{@code label}' tag. 133 */ 134 @Override 135 public int doEndTag() throws JspException { 136 this.tagWriter.endTag(); 137 return EVAL_PAGE; 138 } 139 140 /** 141 * Disposes of the {@link TagWriter} instance. 142 */ 143 @Override 144 public void doFinally() { 145 super.doFinally(); 146 this.tagWriter = null; 147 } 148 149}