Click here to Skip to main content
15,894,539 members
Articles / Programming Languages / C#

Data-controlled Processes Application Design

Rate me:
Please Sign up or sign in to vote.
4.65/5 (7 votes)
23 Nov 2009CPOL10 min read 30.3K   376   34  
A ready-to-use process manager provided
using System;
using System.Collections.Generic;

namespace DataDriven
{
    public class InputSet
    {
        private readonly List<DataContainer> objects;

        protected InputSet() 
        {
            objects = new List<DataContainer>();
        }

        internal InputSet(int capacity)
        {
            objects = new List<DataContainer>(capacity);
        }

        internal List<DataContainer> Objects
        {
            get { return objects; }
        }

        internal void AddInput(DataContainer dataContainer)
        {
            Objects.Add(dataContainer);
        }
        internal void Clear()
        {
            Objects.Clear();
        }

        public ProcessInput<T>[] All<T>()
        {
            return Objects.FindAll(inp => inp.Data is T)
                .ConvertAll(inp => new ProcessInput<T>(inp)).ToArray();
        }
        public T[] AllData<T>()
        {
            return Objects.FindAll(inp => inp.Data is T)
                .ConvertAll(inp => (T)inp.Data).ToArray();
        }

        public IEnumerable<ProcessInput> All()
        {
            foreach (DataContainer o in Objects)
            {
                yield return new ProcessInput(o);
            }
        }
        internal IEnumerable<DataContainer> AllData()
        {
            foreach (DataContainer o in Objects)
            {
                yield return o;
            }
        }

        internal DataContainer FindContainer(object data)
        {
            return Objects.Find(inp => inp.Data == data);
        }
        /// <summary>Adds input if needed by requirement and 
        /// returns true if all requirements are satisfied.</summary>
        internal bool WouldNeed(DataContainer newInput, ProcessInputRequirements requirements)
        {

            IEnumerable<InputRequirement> requirement = requirements.GetRequirementFor(newInput);
            var containers = new LinkedList<DataContainer>(Objects);

            if (requirement != null)
                foreach (InputRequirement inputRequirement in requirement)
                {
                    int count = 0;
                    for (var node = containers.First; node != null; node = node.Next)
                    {
                        if (inputRequirement.IsSatisfiedBy(new ProcessInput(node.Value)))
                        {
                            containers.Remove(node);
                            count++;
                        }
                    }
                    int matches = count;
                    if (matches < requirements.NumberOfRequiedData(inputRequirement))
                        return true;
                }
            return false;
        }
        
        public ProcessInput<T> Single<T>()
        {
            var tInputs = new List<ProcessInput<T>>(All<T>());
            if (tInputs.Count == 0)
                throw new InvalidOperationException("There is no input of type T.");
            return tInputs[0];
        }
        public T SingleData<T>()
        {
            var tInputs = All<T>();
            if (tInputs.Length == 0)
                throw new InvalidOperationException("There is no input of type T.");
            return tInputs[0].Data;
        }
    }
    public class ProcessInput
    {
        internal readonly DataContainer DataContainer;

        internal ProcessInput(DataContainer dataContainer)
        {
            DataContainer = dataContainer;
        }
        /// <summary>
        /// Gets the latest process which worked on data.
        /// </summary>
        public IDataProcess Source
        {
            get 
            {
                return DataContainer.Source != null 
                    ? DataContainer.Source.Process 
                    : null;
            }
        }

        public object Data
        {
            get { return DataContainer.Data; }
        }
        /// <summary>
        /// Returns true if the data was processed by a given process.
        /// </summary>
        public bool HasVisited(IDataProcess process)
        {
            return DataContainer.Track.Exists(pc => pc.Process == process);
        }
        /// <summary>
        /// Gets all former processes which operated on this data so far.
        /// </summary>
        public IDataProcess[] GetTrack()
        {
            IDataProcess[] arr;
            lock (DataContainer.Track)
            {
                arr = new IDataProcess[DataContainer.Track.Count - 1]; // exclude the current process
                for (int i = 0; i < DataContainer.Track.Count - 1; i++)
                {
                    arr[i] = DataContainer.Track[i].Process;
                }
            }
            return arr;
        }
        /// <summary>
        /// Gets number of processes which used this input data.
        /// </summary>
        public int FormerProcessCount
        {
            get
            {
                return DataContainer.Track.Count - 1;
            }
        }
    }    
    public class ProcessInput<T> : ProcessInput
    {

        internal ProcessInput(DataContainer dataContainer) : base(dataContainer)
        {
            if (!(dataContainer.Data is T))
                throw new ArgumentException("Type parameter does not correspond with a type of data.");
        }

        public new T Data
        {
            get { return (T)DataContainer.Data; }
        }
    }

    //public class OutputSet : InputSet, IEnumerable
    //{
    //    private readonly ProcessContainer source;
    //    private readonly InputSet processInput;

    //    internal OutputSet() : this(null, null)
    //    {
    //    }

    //    internal OutputSet(ProcessContainer source, InputSet processInput)
    //    {
    //        this.source = source;
    //        this.processInput = processInput;
    //    }

    //    public void Add(object obj, SendDataParams param)
    //    {
    //        DataContainer container = processInput.Objects.Find(dc => dc.Data == obj);
    //        if (container != null)
    //        {
    //            container.Track.Add(source);
    //            Add(container);
    //        }
    //        else
    //            Objects.Add(new DataContainer
    //                        {
    //                            Data = obj,
    //                            SendParams = param,
    //                            Source = source,
    //                        });
    //    }
    //    public static implicit operator OutputSet(object[] arr)
    //    {
    //        var set = new OutputSet();
    //        set.AddRange(arr);
    //        return set;
    //    }
    //    public void AddRange(IEnumerable objects)
    //    {
    //        foreach (object obj in objects)
    //            Add(obj, new SendDataParams());
    //    }
    //    public void Add(object obj)
    //    {
    //        Add(obj, new SendDataParams());
    //    }

    //    public IEnumerator GetEnumerator()
    //    {
    //        return Objects.ConvertAll(dc => dc.Data).GetEnumerator();
    //    }
    //}

}

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Poland Poland
My name is Jacek. Currently, I am a Java/kotlin developer. I like C# and Monthy Python's sense of humour.

Comments and Discussions