using System;
namespace UniversalEditor
{
///
/// The type of comparison to use with the conditional statement.
///
[Flags()]
public enum ConditionComparison
{
///
/// Returns true if the two values are equal by value.
///
Equal = 1,
///
/// Returns true if the two values are equal by reference (or by value if they are value types).
///
ReferenceEqual = 2,
///
/// Returns true if the first value is greater than the second value.
///
GreaterThan = 4,
///
/// Returns true if the first value is less than the second value.
///
LessThan = 8,
///
/// Negates the conditional comparison.
///
Not = 16
}
///
/// The type of combination applied to a series of conditional statements.
///
public enum ConditionCombination
{
///
/// Returns true if all of the conditional statements in this group are true.
///
And,
///
/// Returns true if at least one of the conditional statements in this group are true.
///
Or,
Xor
}
///
/// Defines the minimum functionality required to implement a conditional statement (either a
/// itself or a of multiple
/// s.
///
public interface IConditionalStatement
{
///
/// Evaluates the conditional statement based on the given criteria.
///
/// The set of values against which to evaluate the conditional statement.
/// True if the conditions are satisfied; false otherwise.
bool Test(params System.Collections.Generic.KeyValuePair[] propertyValues);
///
/// Evaluates the conditional statement based on the given criteria.
///
/// The set of values against which to evaluate the conditional statement.
/// True if the conditions are satisfied; false otherwise.
bool Test(System.Collections.Generic.Dictionary propertyValues);
///
/// Evaluates the conditional statement based on the given criterion.
///
/// The value against which to evaluate the conditional statement.
/// True if the conditions are satisfied; false otherwise.
bool Test (object value);
}
///
/// A collection of s
///
public class ConditionalStatementCollection
: System.Collections.ObjectModel.Collection
{
}
///
/// A group of s joined by a .
///
public class ConditionGroup : IConditionalStatement
{
///
/// Creates a new with no conditional statements specified and a
/// default of .
///
public ConditionGroup()
{
// I know it's initialized to this but I'm doing it here for clarity's sake (and because
// it's documented here... if you change it, make sure to update the documentation! don't
// rely on the field initializer)
mvarCombination = ConditionCombination.And;
}
///
/// Creates a new with the specified
/// and s.
///
/// The used to join s when testing this .
/// The s and s that are part of this .
public ConditionGroup(ConditionCombination combination, params IConditionalStatement[] statements)
{
mvarCombination = combination;
for (int i = 0; i < statements.Length; i++)
{
mvarConditions.Add (statements[i]);
}
}
private ConditionalStatementCollection mvarConditions = new ConditionalStatementCollection();
///
/// Gets all s in this .
///
public ConditionalStatementCollection Conditions
{
get { return mvarConditions; }
}
private ConditionCombination mvarCombination = ConditionCombination.And;
///
/// The type of combination used to join the s in this
/// .
///
public ConditionCombination Combination
{
get { return mvarCombination; }
set { mvarCombination = value; }
}
///
/// Evaluates the conditional statement based on the given criteria.
///
/// The set of values against which to evaluate the conditional statement.
/// True if the conditions are satisfied; false otherwise.
public bool Test (params System.Collections.Generic.KeyValuePair[] propertyValues)
{
bool retval = false;
if (mvarCombination == ConditionCombination.And)
{
retval = true;
}
for (int i = 0; i < mvarConditions.Count; i++)
{
switch (mvarCombination)
{
case ConditionCombination.And:
retval &= mvarConditions[i].Test (propertyValues);
break;
case ConditionCombination.Or:
retval |= mvarConditions[i].Test (propertyValues);
break;
case ConditionCombination.Xor:
retval ^= mvarConditions[i].Test (propertyValues);
break;
}
}
return retval;
}
///
/// Evaluates the conditional statement based on the given criteria.
///
/// The set of values against which to evaluate the conditional statement.
/// True if the conditions are satisfied; false otherwise.
public bool Test(System.Collections.Generic.Dictionary propertyValues)
{
bool retval = false;
if (mvarCombination == ConditionCombination.And)
{
retval = true;
}
for (int i = 0; i < mvarConditions.Count; i++)
{
switch (mvarCombination)
{
case ConditionCombination.And:
retval &= mvarConditions[i].Test(propertyValues);
break;
case ConditionCombination.Or:
retval |= mvarConditions[i].Test(propertyValues);
break;
case ConditionCombination.Xor:
retval ^= mvarConditions[i].Test(propertyValues);
break;
}
}
return retval;
}
///
/// Evaluates the conditional statement based on the given criterion.
///
/// The value against which to evaluate the conditional statement.
/// True if the conditions are satisfied; false otherwise.
public bool Test (object value)
{
bool retval = true;
for (int i = 0; i < mvarConditions.Count; i++)
{
switch (mvarCombination)
{
case ConditionCombination.And:
retval &= mvarConditions[i].Test (value);
break;
case ConditionCombination.Or:
retval |= mvarConditions[i].Test (value);
break;
case ConditionCombination.Xor:
retval ^= mvarConditions[i].Test (value);
break;
}
}
return retval;
}
}
public class Condition : IConditionalStatement
{
private string mvarPropertyName = String.Empty;
///
/// The name of the property against which to test when the method is called
/// passing in a property reference.
///
public string PropertyName
{
get { return mvarPropertyName; }
set { mvarPropertyName = value; }
}
private ConditionComparison mvarComparison = ConditionComparison.Equal;
///
/// The type of comparison to use when testing this .
///
public ConditionComparison Comparison
{
get { return mvarComparison; }
set { mvarComparison = value; }
}
private object mvarValue = null;
///
/// The value against which to test when the method is called.
///
public object Value
{
get { return mvarValue; }
set { mvarValue = value; }
}
///
/// Creates a with the specified property name, comparison, and value.
///
/// The name of the property against which to test when the method is called passing in a property reference.
/// The type of comparison to use.
/// The value against which to test when the method is called.
public Condition(string propertyName, ConditionComparison comparison, object value)
{
mvarPropertyName = propertyName;
mvarComparison = comparison;
mvarValue = value;
}
///
/// Evaluates the conditional statement based on the given criteria.
///
/// The set of values against which to evaluate the conditional statement.
/// True if the conditions are satisfied; false otherwise.
public bool Test(params System.Collections.Generic.KeyValuePair[] propertyValues)
{
bool retval = true;
foreach (System.Collections.Generic.KeyValuePair propertyValue in propertyValues)
{
if (propertyValue.Key == mvarPropertyName)
{
retval &= Test(propertyValue.Value);
}
}
return retval;
}
///
/// Evaluates the conditional statement based on the given criteria.
///
/// The set of values against which to evaluate the conditional statement.
/// True if the conditions are satisfied; false otherwise.
public bool Test(System.Collections.Generic.Dictionary propertyValues)
{
bool retval = true;
foreach (System.Collections.Generic.KeyValuePair propertyValue in propertyValues)
{
if (propertyValue.Key == mvarPropertyName)
{
retval &= Test(propertyValue.Value);
}
}
return retval;
}
///
/// Evaluates the conditional statement based on the given criterion.
///
/// The value against which to evaluate the conditional statement.
/// True if the conditions are satisfied; false otherwise.
public bool Test (object propertyValue)
{
// would you like meatballs with your spaghetti code?
bool returnValue = false;
if ((mvarComparison & ConditionComparison.Equal) == ConditionComparison.Equal)
{
if (propertyValue == null)
{
// our comparison object is null, so we can't .Equals it
// just do regular == with the constant null in that case
returnValue |= (mvarValue == null);
}
else
{
returnValue |= (propertyValue.Equals(mvarValue));
}
}
if ((mvarComparison & ConditionComparison.ReferenceEqual) == ConditionComparison.ReferenceEqual)
{
if (propertyValue == null)
{
// our comparison object is null, so we can't .Equals it
// just do regular == with the constant null in that case
returnValue |= (mvarValue == null);
}
else
{
returnValue |= (propertyValue == mvarValue);
}
}
if (((mvarComparison & ConditionComparison.GreaterThan) == ConditionComparison.GreaterThan) && (propertyValue is IComparable))
{
if (propertyValue == null)
{
// can ANYTHING ever be greater than or less than null?
returnValue |= false;
}
else
{
// we need to directly invoke IComparable.CompareTo here since we can't (usually)
// do > or < on objects... not sure what to do if the object doesn't implement
// IComparable though
returnValue |= ((propertyValue as IComparable).CompareTo(mvarValue) > 0);
}
}
if (((mvarComparison & ConditionComparison.LessThan) == ConditionComparison.LessThan) && (propertyValue is IComparable))
{
if (propertyValue == null)
{
// can ANYTHING ever be greater than or less than null?
returnValue |= false;
}
else
{
// we need to directly invoke IComparable.CompareTo here since we can't (usually)
// do > or < on objects... not sure what to do if the object doesn't implement
// IComparable though
returnValue |= ((propertyValue as IComparable).CompareTo(mvarValue) < 0);
}
}
if ((mvarComparison & ConditionComparison.Not) == ConditionComparison.Not)
{
// we have a Not in there, so negate our return value
returnValue = !returnValue;
}
// did you have as much fun reading this as I did writing it?
bool from_hell = returnValue;
return from_hell;
}
}
}