Click here to Skip to main content
15,896,445 members
Articles / Programming Languages / C#

Search Keywords - Relationship between Pipes-and-Filters and Decorator design patterns

Rate me:
Please Sign up or sign in to vote.
4.90/5 (21 votes)
20 Feb 2006CPOL12 min read 65.7K   699   65  
An article on the implementation of both Pipes-and-Filters architectural design pattern and Decorator pattern.
using System;
using System.Text;
using System.Collections.Generic;
using System.IO;

namespace DecoratorImpl
{
    public interface IComponent<T>
    {
        IEnumerable<T> Words { get; }
        bool Process();
    }


    public abstract class SearchDecorator<T> : IComponent<T> where T: new()
    {
        protected IComponent<T> _ancestor;

        public SearchDecorator(IComponent<T> ancestor)
        {
            _ancestor = ancestor;
        }

        public virtual bool Process()
        {
            return _ancestor.Process();
        }
        public virtual IEnumerable<T> Words
        {
            get
            {
                return _ancestor.Words;
            }
        }
    }

    public class FileLoader : IComponent<Item> 
    {
        private string _path;
        private IEnumerable<Item> _words;

        public FileLoader(string path)
        {
            _path = path;
        }
        public bool Process()
        {
            try
            {
                if (File.Exists(_path))
                {
                    string buffer;
                    // Create an instance of StreamReader to read from a file.
                    // The using statement also closes the StreamReader.
                    using (StreamReader sr = new StreamReader(_path))
                    {
                        buffer = sr.ReadToEnd();
                    }

                    buffer = buffer.Replace("\r\n", " ");
                    Tokens Tokenizer = new Tokens(buffer, new char[] { ' ', ';', ',' });
                    //foreach (string Token in Tokenizer)
                    //{
                    //    if (Token == string.Empty) continue;

                    //    System.Diagnostics.Debug.Write(Token);
                    //    //output.Write(new Item(Token));

                    //}
                    _words = CreateEnumerator(Tokenizer);

                    return true;
                }
                else
                    throw new Exception("File could not be read");
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.Write(ex.Message);
            }

            return false;
        }

        IEnumerable<Item> CreateEnumerator(Tokens Tokenizer)
        {
            foreach (string Token in Tokenizer)
            {
                if (Token == string.Empty) continue;

                System.Diagnostics.Debug.Write(Token);
                yield return new Item(Token);
            }
        }

        public IEnumerable<Item> Words
        {
            get
            {
                return this._words;
            }
        }

    }

    public class StartWithSearch : SearchDecorator<Item>
    {
        private string _keyword;
        private IEnumerable<Item> _words;


        public StartWithSearch(IComponent<Item> ancestor, string keyword)
            : base(ancestor)
        {
            _keyword = keyword;
            _ancestor = ancestor;
        }
        public override bool Process()
        {
            _ancestor.Process();

            System.Diagnostics.Debug.Write(_keyword);
            _words = CreateEnumerator();
            return true;
        }

        IEnumerable<Item> CreateEnumerator()
        {
            foreach (Item Token in _ancestor.Words)
            {
                if (Token.Text == string.Empty) continue;
                if (Token.Text.StartsWith(_keyword))
                {
                    System.Diagnostics.Debug.Write(Token.Text);
                    yield return Token;
                }
            }
        }
        
        public override IEnumerable<Item> Words
        {
            get
            {
                return _words;
            }
        }
    }


    public class WordLengthSearch : SearchDecorator<Item>
    {
        private int _length;
        private IEnumerable<Item> _words;


        public WordLengthSearch(IComponent<Item> ancestor, int length)
            : base(ancestor)
        {
            _length = length;
            _ancestor = ancestor;
        }
        public override bool Process()
        {
            _ancestor.Process();
            _words = CreateEnumerator();
            return true;
        }

        IEnumerable<Item> CreateEnumerator()
        {
            foreach (Item Token in _ancestor.Words)
            {
                if (Token.Text == string.Empty) continue;
                if (Token.Text.Length <= _length)
                {
                    System.Diagnostics.Debug.Write(Token.Text);
                    yield return Token;
                }
            }
        }

        public override IEnumerable<Item> Words
        {
            get
            {
                return _words;
            }
        }
    }

    public class PalindromeSearch : SearchDecorator<Item>
    {
         private IEnumerable<Item> _words;
        public PalindromeSearch(IComponent<Item> ancestor)
            : base(ancestor)
        {
            _ancestor = ancestor;
        }
        public override bool Process()
        {
            _ancestor.Process();
            _words = CreateEnumerator();
            return true;
        }

        IEnumerable<Item> CreateEnumerator()
        {
            foreach (Item Token in _ancestor.Words)
            {
                if (Token.Text == string.Empty) continue;
                int length = Token.Text.Length;
                if (length < 2) yield return Token;
                else
                {
                    int half = length / 2;
                    bool flag = true;
                    for (int i = 0; i < half; ++i)
                        if (Token.Text[i] != Token.Text[length - 1 - i])
                        {
                            flag = false;
                            break;
                        }
                    if (flag)
                        yield return Token;
                }
            }
        }

        public override IEnumerable<Item> Words
        {
            get
            {
                return _words;
            }
        }
    }

    public class Output : SearchDecorator<Item>
    {
         public Output(IComponent<Item> ancestor)
            : base(ancestor)
        {
            _ancestor = ancestor;
        }
        public override bool Process()
        {
            _ancestor.Process();

            string str = string.Empty;
            foreach (Item Token in _ancestor.Words)
            {
                str += Token.Text + System.Environment.NewLine;
            }
            System.Windows.Forms.MessageBox.Show(str);
            return true;
        }
    }

    #region Item Class

    public class Item
    {
        private string _text = null;
        public string Text
        {
            get { return _text; }
            set { _text = value; }
        }
        public Item()
        {
            _text = string.Empty;
        }
        public Item(string t)
        {
            _text = t;
        }
    }

    #endregion

    class EntryPoint
    {
        public static void Invoke()
        {
			//********** DYNAMIC BEHAVOIUR *************

            IComponent<Item> S = new FileLoader("a.log");
            S = new StartWithSearch(S, "ma");
            S = new WordLengthSearch(S, 5);
            S = new PalindromeSearch(S);
            S = new Output(S);
            
            S.Process();
		}
    }
}

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
Architect
Pakistan Pakistan
Basharat Hussain currently works as Solution Architect for the company TEO (http://www.teo-intl.com) in Islamabad, Pakistan.

Blog: My Blog Link

Comments and Discussions