blob: 52c0fd7d079e502aee514643f2ef24c088873e7c [file] [log] [blame]
using System;
using System.Collections;
using Agility.Nexus.Validators;
using Nexus.Core.Tables;
namespace Nexus.Core.Validators
{
/// <summary>
/// Provide a base class to use when implementating Validators.
/// </summary>
/// <remarks>
/// Subclasses must provide a NexusExecute method.
/// </remarks>
public abstract class ProcessorCommand : RequestCommand, IProcessorCommand
{
#region IRequestCommand
public override bool RequestExecute(IRequestContext context)
{
ProcessRelated(context);
ProcessRequired(context);
return context.HasAlerts;
}
#endregion
#region IProcessorCommand
private string _Template = null;
public virtual string Required
{
get { return _Template; }
set { _Template = value; }
}
/// <summary>
/// Convert input for fields that do not have a Processor.
/// </summary>
/// <remarks>
/// The default behavior is to pass through the objects, verbatim.
/// </remarks>
/// <param name="context">The IProcessorContext</param>
public virtual bool ConvertInput(IProcessorContext context)
{
context.Target = context.Source;
return true;
}
public virtual bool ExecuteConvert(IProcessorContext context)
{
bool okay;
string id = context.FieldKey;
IFieldTable table = context.FieldTable;
IFieldContext fieldContext = table.GetFieldContext(id); // enforces Strict
if ((fieldContext == null))
{
ConvertInput(context);
return true;
}
IProcessor processor = fieldContext.Processor;
if (processor == null)
okay = ConvertInput(context);
else
{
okay = processor.ConvertInput(context);
}
return okay;
}
/// <summary>
/// Format output for fields that do not have a Processor.
/// </summary>
/// <remarks>
/// The default behavior is to pass through nulls and ICollection types
/// and to call ToString on everything else.
/// </remarks>
/// <param name="context">The IProcessorContext</param>
public virtual bool FormatOutput(IProcessorContext context)
{
if (context.Source != null)
{
Type sourceType = context.Source.GetType();
if (IsCollectionType(sourceType)) context.Target = context.Source;
else context.Target = context.Source.ToString();
}
return true;
}
public virtual bool ExecuteFormat(IProcessorContext context)
{
bool okay = false;
string id = context.FieldKey;
object source = context.Source;
IFieldTable table = context.FieldTable;
IFieldContext fieldContext = table.GetFieldContext(id); // Enforces Strict
if ((fieldContext == null))
{
if (source == null)
context.Target = null;
else okay = FormatOutput(context);
return okay;
}
IProcessor processor = fieldContext.Processor;
if (processor == null)
okay = FormatOutput(context);
else
{
okay = processor.FormatOutput(context);
}
return okay;
}
private bool IsCollectionType(Type dataType)
{
bool v = (typeof (ICollection)).IsAssignableFrom(dataType);
return (v);
}
public abstract bool ExecuteProcess(IProcessorContext context);
#endregion
#region ProcessRequired
private void AssertProcessRequired(IRequestContext context)
{
IDictionary criteria = context.Criteria;
if (null == criteria)
throw new ArgumentNullException("Criteria==null", "BaseValidator.NexusExecute.AssertProcessRequired");
}
private void ProcessRequired(IRequestContext context)
{
IList requiredIDs = context.CommandBin.RequiredIDs; // inner list
if (requiredIDs == null) return;
IList runtimeIDs = context.CommandBin.RuntimeIDs; // inner list
if (runtimeIDs != null)
{
IEnumerator runtime = runtimeIDs.GetEnumerator();
while (runtime.MoveNext())
{
string id = runtime.Current as string;
requiredIDs.Remove(id);
}
}
IEnumerator required = requiredIDs.GetEnumerator();
while (required.MoveNext())
{
string id = required.Current as string;
bool okay = (context.Contains(id) && (null != context[id]) && (!String.Empty.Equals(context[id].ToString())));
if (!okay)
{
context.AddAlertRequired(id);
}
}
}
#endregion
#region ProcessRelated
private void AssertProcessRelated(IRequestContext context)
{
AssertProcessRequired(context);
IFieldTable table = context.FieldTable;
if (null == table)
throw new ArgumentNullException("FieldTable==null", "BaseValidator.NexusExecute.AssertProcessRelated");
}
private void ProcessRelated(IRequestContext context)
{
AssertProcessRelated(context);
ICollection related = CombinedIDs(context);
foreach (string key in related)
{
IProcessorContext _context = new ProcessorContext(key, context);
ExecuteProcess(_context);
}
}
private ICollection CombinedIDs(IRequestContext context)
{
IDictionary combined = new Hashtable();
IList relatedIDs = context.CommandBin.RelatedIDs; // outer list
// Add Command ID to related list (since we store outcome under our own ID)
// This code relies on RelatedIDs being lazily instantiated.
string id = context.CommandBin.ID;
bool found_self = relatedIDs.Contains(id);
if (!found_self) relatedIDs.Add(id);
foreach (string i in relatedIDs) combined[i] = i;
IList requiredIDs = context.CommandBin.RequiredIDs; // inner list
if (requiredIDs != null) foreach (string i in requiredIDs) combined[i] = i;
return combined.Keys;
}
#endregion
}
}