|
using System.Collections;
using System.Collections.Generic;
namespace DataDriven
{
public delegate bool InputPredicate(ProcessInput input);
public class ProcessInputRequirements : IEnumerable<KeyValuePair<InputRequirement, int>>, IEnumerable<InputRequirement>
{
// requirement => number of inputs which must satisfy it;
readonly Dictionary<InputRequirement, int> requirements = new Dictionary<InputRequirement, int>();
private readonly List<InputRequirement> overAllRequirements = new List<InputRequirement>();
//internal ProcessContainer Process;
public ProcessInputRequirements(params InputPredicate[] predicates)
{
foreach (InputPredicate predicate in predicates)
requirements.Add(new PredicateRequirement(predicate), 1);
}
public void AddOverAllRequirement(InputRequirement requirement)
{
overAllRequirements.Add(requirement);
}
public void Add(InputRequirement requirement, int quantity)
{
requirements.Add(requirement, quantity);
}
public void Add(InputRequirement requirement)
{
requirements.Add(requirement, 1);
}
public bool IsSatisfiedBy(InputSet inputSet)
{
var dataList = new LinkedList<DataContainer>(inputSet.AllData());
foreach (var pair in requirements)
{
int quantity = pair.Value;
InputRequirement requirement = pair.Key;
for (LinkedListNode<DataContainer> node = dataList.First; node != null; node = node.Next)
if (node.Value != null && requirement.IsSatisfiedBy(new ProcessInput(node.Value)))
{
quantity--;
node.Value = null;
if (quantity == 0)
break;
//dataList.Remove(node);
}
if (quantity != 0)
return false;
}
foreach (DataContainer o in inputSet.AllData())
foreach (InputRequirement overAllRequirement in overAllRequirements)
if (!overAllRequirement.IsSatisfiedBy(new ProcessInput(o)))
return false;
return true;
}
internal IEnumerable<InputRequirement> GetRequirementFor(DataContainer input)
{
if (SatisfiedByOverall(input))
foreach (InputRequirement requirement in requirements.Keys)
if (requirement.IsSatisfiedBy(new ProcessInput(input)))
yield return requirement;
}
bool SatisfiedByOverall(DataContainer input)
{
foreach (InputRequirement requirement in overAllRequirements)
{
if (!requirement.IsSatisfiedBy(new ProcessInput(input)))
return false;
}
return true;
}
internal int NumberOfRequiedData(InputRequirement input)
{
return !requirements.ContainsKey(input)
? 0
: requirements[input];
}
internal int MinInputCount
{
get
{
return requirements.Count;
}
}
IEnumerator<InputRequirement> IEnumerable<InputRequirement>.GetEnumerator()
{
return requirements.Keys.GetEnumerator();
}
public IEnumerator<KeyValuePair<InputRequirement, int>> GetEnumerator()
{
return requirements.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class InputRequirements
{
// predicate => quantity
private readonly Dictionary<InputRequirement, int> requirements = new Dictionary<InputRequirement, int>();
public Dictionary<InputRequirement, int> Requirements
{
get { return requirements; }
}
}
public abstract class InputRequirement
{
public abstract bool IsSatisfiedBy(ProcessInput input);
}
public class TrackRestrictionRequirement : InputRequirement, IEnumerable<IDataProcess>
{
private readonly List<IDataProcess> affectedProcesses = new List<IDataProcess>();
private RestrictionTypes restrictionType = RestrictionTypes.Forbid;
public enum RestrictionTypes
{
/// <summary>None of affected processes can be in data's track.</summary>
Forbid,
/// <summary>All affected processes must be in data's track.</summary>
Enforce
}
public List<IDataProcess> AffectedProcesses
{
get { return affectedProcesses; }
}
public RestrictionTypes RestrictionType
{
get { return restrictionType; }
set { restrictionType = value; }
}
public override bool IsSatisfiedBy(ProcessInput input)
{
switch (restrictionType)
{
case RestrictionTypes.Forbid:
return !input.DataContainer.Track.Exists(pc => affectedProcesses.Contains(pc.Process));
default://case RestrictionTypes.Enforce:
return !input.DataContainer.Track.Exists(pc => !affectedProcesses.Contains(pc.Process));
}
}
public void Add(IDataProcess process)
{
affectedProcesses.Add(process);
}
public IEnumerator<IDataProcess> GetEnumerator()
{
return affectedProcesses.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void AddRange(IEnumerable<IDataProcess> processes)
{
affectedProcesses.AddRange(processes);
}
}
public class SequenceRequirement : InputRequirement, IEnumerable<IDataProcess>
{
private readonly List<IDataProcess> previousProcesses = new List<IDataProcess>();
public SequenceRequirement(IEnumerable<IDataProcess> range)
{
previousProcesses.AddRange(range);
}
public void Add(IDataProcess process)
{
previousProcesses.Add(process);
}
public override bool IsSatisfiedBy(ProcessInput input)
{
return previousProcesses.Contains(input.Source);
}
public IEnumerator<IDataProcess> GetEnumerator()
{
return previousProcesses.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class MultipleRequirement : InputRequirement
{
private readonly List<InputRequirement> partRequirements = new List<InputRequirement>();
private Conjunctions conjunction = Conjunctions.And;
public enum Conjunctions
{
And, Or, Neither, Single
}
public List<InputRequirement> PartRequirements
{
get { return partRequirements; }
}
public Conjunctions Conjunction
{
get { return conjunction; }
set { conjunction = value; }
}
public override bool IsSatisfiedBy(ProcessInput input)
{
switch (conjunction)
{
case Conjunctions.Or:
foreach (InputRequirement partRequirement in PartRequirements)
if (partRequirement.IsSatisfiedBy(input))
return true;
return false;
case Conjunctions.Neither:
foreach (InputRequirement partRequirement in PartRequirements)
if (partRequirement.IsSatisfiedBy(input))
return false;
return true;
case Conjunctions.Single:
bool any = false;
foreach (InputRequirement partRequirement in PartRequirements)
if (partRequirement.IsSatisfiedBy(input))
{
if (any)
return false;
any = true;
}
return any;
default: // Conjunctions.And:
foreach (InputRequirement partRequirement in PartRequirements)
if (!partRequirement.IsSatisfiedBy(input))
return false;
return true;
}
}
}
public class PredicateRequirement : InputRequirement
{
private InputPredicate predicate;
public PredicateRequirement()
{
}
public PredicateRequirement(InputPredicate predicate)
{
this.predicate = predicate;
}
public override bool IsSatisfiedBy(ProcessInput inputSet)
{
return predicate(inputSet);
}
public InputPredicate Predicate
{
get { return predicate; }
set { predicate = value; }
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
My name is Jacek. Currently, I am a Java/kotlin developer. I like C# and Monthy Python's sense of humour.