alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Spring Framework example source code file (OptionWriter.java)

This example Spring Framework source code file (OptionWriter.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Spring Framework tags/keywords

beanwrapper, beanwrapper, bindstatus, http, iterator, jspexception, jspexception, map, object, object, optionwriter, servlet, string, string, tagwriter, type, util

The Spring Framework OptionWriter.java source code

/*
 * Copyright 2002-2008 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.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.servlet.tags.form;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.jsp.JspException;

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.servlet.support.BindStatus;

/**
 * Provides supporting functionality to render a list of '<code>option'
 * tags based on some source object. This object can be either an array, a
 * {@link Collection}, or a {@link Map}.
 * <h3>Using an array or a {@link Collection}:
 * <p>
 * If you supply an array or {@link Collection} source object to render the
 * inner '<code>option' tags, you may optionally specify the name of
 * the property on the objects which corresponds to the <em>value of the
 * rendered '<code>option' (i.e., the valueProperty)
 * and the name of the property that corresponds to the <em>label (i.e.,
 * the <code>labelProperty). These properties are then used when
 * rendering each element of the array/{@link Collection} as an '<code>option'.
 * If either property name is omitted, the value of {@link Object#toString()} of
 * the corresponding array/{@link Collection} element is used instead.
 * </p>
 * <h3>Using a {@link Map}:
 * <p>
 * You can alternatively choose to render '<code>option' tags by
 * supplying a {@link Map} as the source object.
 * </p>
 * <p>
 * If you <strong>omit property names for the value and
 * <em>label:
 * </p>
 * <ul>
 * <li>the key of each {@link Map} entry will correspond to the
 * <em>value of the rendered 'option', and
 * <li>the value of each {@link Map} entry will correspond to
 * the <em>label of the rendered 'option'.
 * </ul>
 * <p>
 * If you <strong>supply property names for the value and
 * <em>label:
 * </p>
 * <ul>
 * <li>the value of the rendered 'option' will be
 * retrieved from the <code>valueProperty on the object
 * corresponding to the <code>key of each {@link Map} entry, and
 * <li>the label of the rendered 'option' will be
 * retrieved from the <code>labelProperty on the object
 * corresponding to the <code>value of each {@link Map} entry.
 * </ul>
 * <h3>When using either of these approaches:
 * <ul>
 * <li>Property names for the value and label are
 * specified as arguments to the
 * {@link #OptionWriter(Object, BindStatus, String, String, boolean) constructor}.</li>
 * <li>An 'option' is marked as 'selected' if its key
 * {@link #isOptionSelected matches} the value that is bound to the tag instance.</li>
 * </ul>
 *
 * @author Rob Harrop
 * @author Juergen Hoeller
 * @author Sam Brannen
 * @since 2.0
 */
class OptionWriter {

	private final Object optionSource;

	private final BindStatus bindStatus;

	private final String valueProperty;

	private final String labelProperty;

	private final boolean htmlEscape;


	/**
	 * Creates a new <code>OptionWriter for the supplied objectSource.
	 * @param optionSource the source of the <code>options (never 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
	 * (optional)
	 * @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) {

		Assert.notNull(optionSource, "'optionSource' must not be null");
		Assert.notNull(bindStatus, "'bindStatus' must not be null");
		this.optionSource = optionSource;
		this.bindStatus = bindStatus;
		this.valueProperty = valueProperty;
		this.labelProperty = labelProperty;
		this.htmlEscape = htmlEscape;
	}


	/**
	 * Write the '<code>option' tags for the configured {@link #optionSource} to
	 * the supplied {@link TagWriter}.
	 */
	public void writeOptions(TagWriter tagWriter) throws JspException {
		if (this.optionSource.getClass().isArray()) {
			renderFromArray(tagWriter);
		}
		else if (this.optionSource instanceof Collection) {
			renderFromCollection(tagWriter);
		}
		else if (this.optionSource instanceof Map) {
			renderFromMap(tagWriter);
		}
		else {
			throw new JspException(
					"Type [" + this.optionSource.getClass().getName() + "] is not valid for option items");
		}
	}

	/**
	 * Renders the inner '<code>option' tags using the {@link #optionSource}.
	 * @see #doRenderFromCollection(java.util.Collection, TagWriter)
	 */
	private void renderFromArray(TagWriter tagWriter) throws JspException {
		doRenderFromCollection(CollectionUtils.arrayToList(this.optionSource), tagWriter);
	}

	/**
	 * Renders the inner '<code>option' tags using the supplied
	 * {@link Map} as the source.
	 * @see #renderOption(TagWriter, Object, Object, Object)
	 */
	private void renderFromMap(final TagWriter tagWriter) throws JspException {
		Map optionMap = (Map) this.optionSource;
		for (Iterator iterator = optionMap.entrySet().iterator(); iterator.hasNext();) {
			Map.Entry entry = (Map.Entry) iterator.next();
			Object mapKey = entry.getKey();
			Object mapValue = entry.getValue();
			BeanWrapper mapKeyWrapper = PropertyAccessorFactory.forBeanPropertyAccess(mapKey);
			BeanWrapper mapValueWrapper = PropertyAccessorFactory.forBeanPropertyAccess(mapValue);
			Object renderValue = (this.valueProperty != null ?
					mapKeyWrapper.getPropertyValue(this.valueProperty) : mapKey.toString());
			Object renderLabel = (this.labelProperty != null ?
					mapValueWrapper.getPropertyValue(this.labelProperty) : mapValue.toString());
			renderOption(tagWriter, mapKey, renderValue, renderLabel);
		}
	}

	/**
	 * Renders the inner '<code>option' tags using the {@link #optionSource}.
	 * @see #doRenderFromCollection(java.util.Collection, TagWriter)
	 */
	private void renderFromCollection(TagWriter tagWriter) throws JspException {
		doRenderFromCollection((Collection) this.optionSource, tagWriter);
	}

	/**
	 * Renders 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 'option' and the value of the
	 * {@link #labelProperty} property is used when rendering the label.
	 */
	private void doRenderFromCollection(Collection optionCollection, TagWriter tagWriter) throws JspException {
		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 label = (this.labelProperty != null ? wrapper.getPropertyValue(this.labelProperty) : item);
			renderOption(tagWriter, item, value, label);
		}
	}

	/**
	 * Renders 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 {
		tagWriter.startTag("option");
		writeCommonAttributes(tagWriter);

		String valueDisplayString = getDisplayString(value);
		String labelDisplayString = getDisplayString(label);

		// allows render values to handle some strange browser compat issues.
		tagWriter.writeAttribute("value", valueDisplayString);

		if (isOptionSelected(value) || (value != item && isOptionSelected(item))) {
			tagWriter.writeAttribute("selected", "selected");
		}
		if (isOptionDisabled()) {
			tagWriter.writeAttribute("disabled", "disabled");
		}
		tagWriter.appendValue(labelDisplayString);
		tagWriter.endTag();
	}

	/**
	 * Determines the display value of the supplied <code>Object,
	 * HTML-escaped as required.
	 */
	private String getDisplayString(Object value) {
		return ValueFormatter.getDisplayString(value, this.bindStatus.getEditor(), this.htmlEscape);
	}

	/**
	 * Determine whether the supplied values matched the selected value.
	 * Delegates to {@link SelectedValueComparator#isSelected}.
	 */
	private boolean isOptionSelected(Object resolvedValue) {
		return SelectedValueComparator.isSelected(this.bindStatus, resolvedValue);
	}

	/**
	 * Determine whether the option fields should be disabled.
	 */
	protected boolean isOptionDisabled() {
		return false;
	}

	/**
	 * Writes default attributes configured to the supplied {@link TagWriter}.
	 */
	protected void writeCommonAttributes(TagWriter tagWriter) throws JspException {
	}

}

Other Spring Framework examples (source code examples)

Here is a short list of links related to this Spring Framework OptionWriter.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.