using System;
using System.Collections;
using System.Collections.Specialized;
using System.Reflection;
using System.Web;
using Spring.Core;
using Spring.Expressions;
using Spring.Globalization;
using Spring.Objects;
using Spring.Util;
using Spring.Validation;
namespace Spring.DataBinding{
/// <summary>
/// Binds agroup of HTTP request multi-valued items to the data model.
/// </summary>
/// <remarks>
/// Due to the fact, that browsers don't send the values of unchecked checkboxes, you
/// can't use <see cref="HttpRequestListBindingContainer"/> for binding to checkboxes.
/// </remarks>
/// <author>Aleksandar Seovic</author>
public class HttpRequestListBindingContainer : BaseBindingContainer
{
private string[] requestParams;
private ConstructorInfo itemCtor;
private IExpression targetExpression;
/// <summary>
/// Creates a new instance of <see cref="HttpRequestListBindingContainer"/>.
/// </summary>
/// <param name="requestParams">
/// Comma separated list of multi-valued request parameters that
/// should be used to create a target item.
/// </param>
/// <param name="targetList">
/// Expression that identifies a target list items should be added to.
/// </param>
/// <param name="itemType">
/// The type of the target item.
/// </param>
public HttpRequestListBindingContainer(string requestParams, string targetList, Type itemType)
{
this.requestParams = requestParams.Split(',');
this.targetExpression = Expression.Parse(targetList);
this.itemCtor = itemType.GetConstructor(Type.EmptyTypes);
if (this.itemCtor == null)
{
throw new ArgumentException("Type [{0}] does not have a default constructor. " +
"A default constructor for the item type is required for collection data binding.",
itemType.FullName);
}
}
/// <summary>
/// Adds the <see cref="SimpleExpressionBinding"/> binding.
/// </summary>
/// <remarks>
/// This is a convinience method for adding <b>SimpleExpressionBinding</b>,
/// one of the most often used binding types, to the bindings list.
/// </remarks>
/// <param name="sourceExpression">
/// The source expression.
/// </param>
/// <param name="targetExpression">
/// The target expression.
/// </param>
/// <param name="direction">
/// Binding direction.
/// </param>
/// <param name="formatter">
/// <see cref="IFormatter"/> to use for value formatting and parsing.
/// </param>
/// <returns>
/// Added <see cref="SimpleExpressionBinding"/> instance.
/// </returns>
public override IBinding AddBinding(string sourceExpression, string targetExpression, BindingDirection direction,
IFormatter formatter)
{
// setup variable for each HTTP request parameter
return base.AddBinding("#" + sourceExpression, targetExpression, direction, formatter);
}
/// <summary>
/// Binds source object to target object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
/// <param name="variables">
/// Variables that should be used during expression evaluation.
/// </param>
public override void BindSourceToTarget(object source, object target, IValidationErrors validationErrors, IDictionary variables)
{
NameValueCollection parameters = VirtualEnvironment.RequestParams;
IList targetList = targetExpression.GetValue(target) as IList;
if (targetList == null)
{
throw new ArgumentException("Target property has to be initialized to an instance of IList interface.");
}
if (parameters.GetValues(requestParams[0]) != null)
{
int valueCount = parameters.GetValues(requestParams[0]).Length;
for (int i = 0; i < valueCount; i++)
{
IDictionary vars = new Hashtable();
foreach (string paramName in requestParams)
{
vars[paramName] = parameters.GetValues(paramName)[i];
}
object targetItem;
bool addToList;
if (i < targetList.Count)
{
targetItem = targetList[i];
addToList = false;
}
else
{
targetItem = itemCtor.Invoke(ObjectUtils.EmptyObjects);
addToList = true;
}
foreach (IBinding binding in Bindings)
{
binding.BindSourceToTarget(null, targetItem, validationErrors, vars);
}
if (addToList)
{
targetList.Add(targetItem);
}
}
}
}
/// <summary>
/// Binds target object to source object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
/// <param name="variables">
/// Variables that should be used during expression evaluation.
/// </param>
public override void BindTargetToSource(object source, object target, IValidationErrors validationErrors, IDictionary variables)
{
// can't bind to a read-only Request object...
}
}
}
|