#region License
/*
* 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.
*/
#endregion
#region Imports
using System;
using System.Collections;
using Spring.Collections;
using Spring.Core;
using Spring.Util;
#endregion
namespace Spring.Web.Support{
/// <summary>
/// The default implementation of the <see cref="IResultWebNavigator"/> interface.
/// </summary>
public class DefaultResultWebNavigator : IResultWebNavigator
{
private IWebNavigator _parentNavigator;
private bool _ignoreCase;
private IDictionary _results;
/// <summary>
/// Indicates, whether result names are treated case sensitive by this navigator.
/// </summary>
public bool IsCaseSensitive
{
get { return !_ignoreCase; }
}
/// <summary>
/// Get/Set the parent of this navigator.
/// </summary>
/// <exception cref="InvalidOperationException">if this navigator already has a parent.</exception>
public virtual IWebNavigator ParentNavigator
{
get { return _parentNavigator; }
set
{
if (_parentNavigator != null)
{
throw new InvalidOperationException("Can't set parent navigator because this navigator already has a parent");
}
_parentNavigator = value;
}
}
/// <summary>
/// Gets or sets map of result names to <see cref="IResult"/> instances or their textual representations.
/// See <see cref="ResultFactoryRegistry"/> for information on parsing textual <see cref="IResult"/> representations.
/// </summary>
/// <seealso cref="IResult"/>
/// <seealso cref="ResultFactoryRegistry"/>
/// <seealso cref="IResultFactory"/>
/// <seealso cref="DefaultResultFactory"/>
public IDictionary Results
{
get
{
return _results;
}
set
{
_results = CreateResultsDictionary( value );
}
}
/// <summary>
/// Creates and initializes a new instance.
/// </summary>
public DefaultResultWebNavigator()
: this( null, null, true )
{ }
/// <summary>
/// Creates and initializes a new instance.
/// </summary>
/// <param name="parent">the parent of this instance. May be null.</param>
/// <param name="initialResults">a dictionary of result name to result mappings. May be null.</param>
/// <param name="ignoreCase">sets, how this navigator treats case sensitivity of result names</param>
public DefaultResultWebNavigator( IWebNavigator parent, IDictionary initialResults, bool ignoreCase )
{
this._parentNavigator = parent;
this._ignoreCase = ignoreCase;
this._results = CreateResultsDictionary( initialResults );
}
/// <summary>
/// Create the dictionary instance to be used by this navigator component.
/// </summary>
/// <param name="initialResults">a dictionary of intitial result mappings</param>
/// <returns>the dictionary, that will be used by this navigator.</returns>
/// <remarks>
/// Implementors may override this for creating custom dictionaries.
/// </remarks>
protected virtual IDictionary CreateResultsDictionary( IDictionary initialResults )
{
IDictionary newResults = (_ignoreCase) ? new CaseInsensitiveHashtable() : new Hashtable();
if (initialResults != null)
{
foreach (DictionaryEntry entry in initialResults)
{
newResults[entry.Key.ToString()] = entry.Value;
}
}
return newResults;
}
/// <summary>
/// Determines, whether this navigator or one of its parents can
/// navigate to the destination specified in <paramref name="destination"/>.
/// </summary>
/// <param name="destination">the name of the navigation destination</param>
/// <returns>true, if this navigator can navigate to the destination.</returns>
public virtual bool CanNavigateTo( string destination )
{
if (_results.Contains( destination ))
{
return true;
}
return (ParentNavigator != null) ? ParentNavigator.CanNavigateTo( destination ) : false;
}
/// <summary>
/// Redirects user to a URL mapped to specified result name.
/// </summary>
/// <param name="destination">Name of the result.</param>
/// <param name="sender">the instance that issued this request</param>
/// <param name="context">The context to use for evaluating the SpEL expression in the Result.</param>
public virtual void NavigateTo( string destination, object sender, object context )
{
IResult result = GetResult( destination );
if (result == null)
{
if (ParentNavigator != null)
{
ParentNavigator.NavigateTo( destination, sender, context );
return;
}
HandleUnknownDestination(destination, sender, context);
return;
}
// If no context, 'sender' is context
if (context == null)
{
context = sender;
}
result.Navigate( context );
}
/// <summary>
/// Returns a redirect url string that points to the
/// <see cref="Spring.Web.Support.Result.TargetPage"/> defined by this
/// result evaluated using this Page for expression
/// </summary>
/// <param name="resultName">Name of the result.</param>
/// <param name="sender">the instance that issued this request</param>
/// <param name="context">The context to use for evaluating the SpEL expression in the Result</param>
/// <returns>A redirect url string.</returns>
public virtual string GetResultUri( string resultName, object sender, object context )
{
IResult result = GetResult( resultName );
if (result == null)
{
if (ParentNavigator != null)
{
return result.GetRedirectUri( context );
}
return HandleUnknownDestination( resultName, sender, context );
}
// If no context, 'sender' is context
if (context == null)
{
context = sender;
}
return result.GetRedirectUri( context );
}
/// <summary>
/// Obtain the named result instance from the <see cref="Results"/> dictionary. If necessary, the actual representation of the result
/// will be converted to an <see cref="IResult"/> instance by this method.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
protected IResult GetResult( string name )
{
object val = _results[name];
if (val == null)
{
return null;
}
else if (val is IResult)
{
return (IResult)val;
}
else if (val is String)
{
return ResultFactoryRegistry.CreateResult( (string)val );
}
return HandleUnknownResultType(name, val);
}
/// <summary>
/// Handle an unknown result object.
/// </summary>
/// <param name="name">the name of the result</param>
/// <param name="val">the result instance obtained from the <see cref="Results"/> dictionary</param>
/// <remarks>
/// By default, this method throws a <see cref="TypeMismatchException"/>.
/// </remarks>
protected virtual IResult HandleUnknownResultType(string name, object val)
{
throw new TypeMismatchException("Unable to create result object. Please use either String or Result instances to define results." );
}
/// <summary>
/// Handle an unknown destination.
/// </summary>
/// <param name="destination">the destination that could not be resolved.</param>
/// <param name="sender">the sender that issued the request</param>
/// <param name="context">the context to be used for evaluating any dynamic parts of the destination</param>
/// <returns>the uri as being returned from <see cref="GetResultUri"/></returns>
/// <remarks>
/// By default, this method throws a <see cref="ArgumentOutOfRangeException"/>.
/// </remarks>
protected virtual string HandleUnknownDestination( string destination, object sender, object context )
{
throw new ArgumentOutOfRangeException( "destination", string.Format( "No mapping found for the specified destination '{0}'.", destination ) );
}
}
}
|