FormPopulator.java
// license-header java merge-point
// Generated by andromda-jsf cartridge (utils\FormPopulator.java.vsl) DO NOT EDIT!
package org.andromda.presentation.jsf;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.PropertyUtils;
/**
* Provides utilities for population of forms
* when using JSF.
*
* @author Chad Brandon
*/
public class FormPopulator
implements Serializable
{
private static final long serialVersionUID = 1L;
/**
* Copies the properties from the <code>fromForm</code> to the <code>toForm</code>. Only passes not-null values to the toForm.
*
* @param fromForm the form from which we're populating
* @param toForm the form to which we're populating
*/
public static final void populateForm(final Object fromForm, final Object toForm)
{
populateForm(fromForm, toForm, false);
}
/**
* Copies the properties from the <code>fromForm</code> to the <code>toForm</code>. Only passes not-null values to the toForm.
*
* @param fromForm the form from which we're populating
* @param toForm the form to which we're populating
* @param override whether or not properties that have already been copied, should be overridden.
*/
@SuppressWarnings("unchecked") // apache commons-beanutils PropertyUtils has no generics
public static final void populateForm(final Object fromForm, final Object toForm, boolean override)
{
if (fromForm != null && toForm != null)
{
try
{
final Map<String, Object> parameters = PropertyUtils.describe(fromForm);
for (final Iterator<String> iterator = parameters.keySet().iterator(); iterator.hasNext();)
{
final String name = iterator.next();
if (PropertyUtils.isWriteable(toForm, name))
{
// - the property name used for checking whether or not the property value has been set
final String isSetPropertyName = name + "Set";
Boolean isToFormPropertySet = null;
Boolean isFromFormPropertySet = null;
// - only if override isn't true do we care whether or not the to property has been populated
if (!override)
{
if (PropertyUtils.isReadable(toForm, isSetPropertyName))
{
isToFormPropertySet = (Boolean)PropertyUtils.getProperty(toForm, isSetPropertyName);
}
}
// - only if override is set to true, we check to see if the from form property has been set
if (override)
{
if (PropertyUtils.isReadable(fromForm, isSetPropertyName))
{
isFromFormPropertySet = (Boolean)PropertyUtils.getProperty(fromForm, isSetPropertyName);
}
}
if (!override || (override && isFromFormPropertySet != null && isFromFormPropertySet.booleanValue()))
{
if (override || (isToFormPropertySet == null || !isToFormPropertySet.booleanValue()))
{
final PropertyDescriptor toDescriptor =
PropertyUtils.getPropertyDescriptor(toForm, name);
if (toDescriptor != null)
{
Object fromValue = parameters.get(name);
// - only populate if not null
if (fromValue != null)
{
final PropertyDescriptor fromDescriptor =
PropertyUtils.getPropertyDescriptor(fromForm, name);
// - only attempt to set if the types match
if (fromDescriptor.getPropertyType() == toDescriptor.getPropertyType())
{
PropertyUtils.setProperty(toForm, name, fromValue);
}
}
}
}
}
}
}
}
catch (final Throwable throwable)
{
throw new RuntimeException(throwable);
}
}
}
/**
* Populates the form from the attributes contained in the request object.
*
* @param form the form to populate.
* @param formatters any date or time formatters.
* @param override whether or not to override properties already set on the given form.
* @param assignableTypesOnly whether or not copying should be attempted only if the property types are assignable.
*/
public static final void populateFormFromRequestAttributes(final Object form, final Map<String, DateFormat> formatters, boolean override, boolean assignableTypesOnly)
{
final FacesContext context = FacesContext.getCurrentInstance();
final String[] names = JsfUtils.getAttributeNames(context.getExternalContext().getRequest());
final Map<String, Object> attributes = new LinkedHashMap<String, Object>();
if (names != null)
{
for (final String name : names)
{
attributes.put(name, JsfUtils.getAttribute(context.getExternalContext().getRequest(), name));
}
}
populateFormFromPropertyMap(form, formatters, attributes, null, override, assignableTypesOnly);
}
/**
* Populates the form from the attributes contained in the request object.
*
* @param form the form to populate.
* @param formatters any date or time formatters.
* @param override whether or not to override properties already set on the given form.
*/
public static final void populateFormFromRequestAttributes(final Object form, final Map<String, DateFormat> formatters, boolean override)
{
populateFormFromRequestAttributes(form, formatters, override, false);
}
/**
* Populates the form from the given map of properties. If a matching property is null or an empty
* string, then null is placed on the form.
*
* @param form the form to populate.
* @param formatters any date or time formatters.
* @param properties the properties to populate from.
* @param override whether or not to override properties already set on the given form.
*/
public static final void populateFormFromPropertyMap(final Object form, final Map<String, DateFormat> formatters, final Map<String, ?> properties, boolean override)
{
populateFormFromPropertyMap(form, formatters, properties, null, override, false);
}
/**
* Populates the form from the given map of properties. If a matching property is null or an empty
* string, then null is placed on the form.
*
* @param form the form to populate.
* @param formatters any date or time formatters.
* @param properties the properties to populate from.
*/
public static final void populateFormFromPropertyMap(final Object form, final Map<String, DateFormat> formatters, final Map<String, ?> properties)
{
populateFormFromPropertyMap(form, formatters, properties, null, true, false);
}
/**
* Populates the form from the given map of properties and populates only if the types
* the properties are assignable. If a matching property is null or an empty
* string, then null is placed on the form.
*
* @param form the form to populate.
* @param formatters any date or time formatters.
* @param properties the properties to populate from.
*/
public static final void populateFormFromPropertyMapAssignableTypesOnly(final Object form, final Map<String, DateFormat> formatters, final Map<String, ?> properties)
{
populateFormFromPropertyMap(form, formatters, properties, null, true, true);
}
/**
* Populates the form from the given map of properties. If a matching property is null or an empty
* string, then null is placed on the form.
*
* @param form the form to populate.
* @param formatters any date or time formatters.
* @param properties the properties to populate from.
* @param ignoreProperties names of any properties to ignore when it comes to populating on the form.
*/
public static final void populateFormFromPropertyMap(final Object form, final Map<String, DateFormat> formatters,
final Map<String, ?> properties, final String[] ignoreProperties)
{
populateFormFromPropertyMap(form, formatters, properties, ignoreProperties, true, false);
}
/**
* Populates the form from the given map of properties. If a matching property is null or an empty
* string, then null is placed on the form.
*
* @param form the form to populate.
* @param formatters any date or time formatters.
* @param properties the properties to populate from.
* @param ignoreProperties names of any properties to ignore when it comes to populating on the form.
* @param override whether or not to override properties already set on the given form.
* @param assignableTypesOnly whether or not copying should be attempted only if the property types are assignable.
*/
@SuppressWarnings("unchecked") // apache commons-beanutils PropertyUtils has no generics
public static final void populateFormFromPropertyMap(final Object form, final Map<String, DateFormat> formatters,
final Map<String, ?> properties, final String[] ignoreProperties, boolean override, boolean assignableTypesOnly)
{
if (properties != null)
{
try
{
final Collection<String> ignoredProperties = ignoreProperties != null ? Arrays.asList(ignoreProperties) : new ArrayList<String>();
final Map<String, Object> formProperties = PropertyUtils.describe(form);
for (final Iterator<String> iterator = formProperties.keySet().iterator(); iterator.hasNext();)
{
final String name = iterator.next();
if (PropertyUtils.isWriteable(form, name) && !ignoredProperties.contains(name))
{
final PropertyDescriptor descriptor =
PropertyUtils.getPropertyDescriptor(form, name);
if (descriptor != null)
{
boolean populateProperty = true;
if (!override)
{
final String isSetPropertyName = name + "Set";
if (PropertyUtils.isReadable(form, isSetPropertyName))
{
final Boolean isPropertySet = (Boolean)PropertyUtils.getProperty(form, isSetPropertyName);
if (isPropertySet.booleanValue())
{
populateProperty = false;
}
}
}
if (populateProperty)
{
final Object property = properties.get(name);
// - only convert if the string is not empty
if (property != null)
{
Object value = null;
if (property instanceof String)
{
final String propertyAsString = (String)property;
if (propertyAsString.trim().length() > 0)
{
DateFormat formatter = formatters != null ? formatters.get(name) : null;
// - if the formatter is available we use that, otherwise we attempt to convert
if (formatter != null)
{
try
{
value = formatter.parse(propertyAsString);
}
catch (ParseException parseException)
{
// - try the default formatter (handles the default java.util.Date.toString() format)
formatter = formatters != null ? formatters.get(null) : null;
value = formatter.parse(propertyAsString);
}
}
else
{
value = ConvertUtils.convert(propertyAsString, descriptor.getPropertyType());
}
}
// - don't attempt to set null on primitive fields
if (value != null || !descriptor.getPropertyType().isPrimitive())
{
PropertyUtils.setProperty(form, name, value);
}
}
else
{
value = property;
try
{
if (!assignableTypesOnly || descriptor.getPropertyType().isAssignableFrom(value.getClass()))
{
PropertyUtils.setProperty(form, name, value);
}
}
catch (Exception exception)
{
final String valueTypeName = value.getClass().getName();
final String propertyTypeName = descriptor.getPropertyType().getName();
final StringBuilder message = new StringBuilder("Can not set form property '"
+ name + "' of type: " + propertyTypeName + " with value: "
+ value);
if (!descriptor.getPropertyType().isAssignableFrom(value.getClass()))
{
message.append("; " + valueTypeName + " is not assignable to " + propertyTypeName);
}
throw new IllegalArgumentException(message + ": " + exception.toString());
}
}
}
}
}
}
}
}
catch (final Throwable throwable)
{
throw new RuntimeException(throwable);
}
}
}
}