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.lang.Nullable;
022
023/**
024 * Abstract base class to provide common methods for
025 * implementing databinding-aware JSP tags for rendering an HTML '{@code input}'
026 * element with a '{@code type}' of '{@code checkbox}' or '{@code radio}'.
027 *
028 * @author Thomas Risberg
029 * @author Juergen Hoeller
030 * @author Rossen Stoyanchev
031 * @since 2.5
032 */
033@SuppressWarnings("serial")
034public abstract class AbstractCheckedElementTag extends AbstractHtmlInputElementTag {
035
036        /**
037         * Render the '{@code input(checkbox)}' with the supplied value, marking the
038         * '{@code input}' element as 'checked' if the supplied value matches the
039         * bound value.
040         */
041        protected void renderFromValue(@Nullable Object value, TagWriter tagWriter) throws JspException {
042                renderFromValue(value, value, tagWriter);
043        }
044
045        /**
046         * Render the '{@code input(checkbox)}' with the supplied value, marking the
047         * '{@code input}' element as 'checked' if the supplied value matches the
048         * bound value.
049         */
050        protected void renderFromValue(@Nullable Object item, @Nullable Object value, TagWriter tagWriter)
051                        throws JspException {
052
053                String displayValue = convertToDisplayString(value);
054                tagWriter.writeAttribute("value", processFieldValue(getName(), displayValue, getInputType()));
055                if (isOptionSelected(value) || (value != item && isOptionSelected(item))) {
056                        tagWriter.writeAttribute("checked", "checked");
057                }
058        }
059
060        /**
061         * Determines whether the supplied value matched the selected value
062         * through delegating to {@link SelectedValueComparator#isSelected}.
063         */
064        private boolean isOptionSelected(@Nullable Object value) throws JspException {
065                return SelectedValueComparator.isSelected(getBindStatus(), value);
066        }
067
068        /**
069         * Render the '{@code input(checkbox)}' with the supplied value, marking
070         * the '{@code input}' element as 'checked' if the supplied Boolean is
071         * {@code true}.
072         */
073        protected void renderFromBoolean(Boolean boundValue, TagWriter tagWriter) throws JspException {
074                tagWriter.writeAttribute("value", processFieldValue(getName(), "true", getInputType()));
075                if (boundValue) {
076                        tagWriter.writeAttribute("checked", "checked");
077                }
078        }
079
080        /**
081         * Return a unique ID for the bound name within the current PageContext.
082         */
083        @Override
084        @Nullable
085        protected String autogenerateId() throws JspException {
086                String id = super.autogenerateId();
087                return (id != null ? TagIdGenerator.nextId(id, this.pageContext) : null);
088        }
089
090
091        /**
092         * Writes the '{@code input}' element to the supplied
093         * {@link TagWriter},
094         * marking it as 'checked' if appropriate.
095         */
096        @Override
097        protected abstract int writeTagContent(TagWriter tagWriter) throws JspException;
098
099        /**
100         * Flags "type" as an illegal dynamic attribute.
101         */
102        @Override
103        protected boolean isValidDynamicAttribute(String localName, Object value) {
104                return !"type".equals(localName);
105        }
106
107        /**
108         * Return the type of the HTML input element to generate:
109         * "checkbox" or "radio".
110         */
111        protected abstract String getInputType();
112
113}