Dynamic Filter By Using Intercepting Filter Pattern

Introduction

Interpreter Pattern comes under Behavioral Pattern. The purpose of this pattern is to process user input expressions and build an Abstract Syntax Tree. It is used when some context needs to be interpreted.

Problem Statement

A user has a set of collections and he/she wants to search some particular object from that collection. The user can search based on - First Name, Last name, Phone, or Email.

 
The user can search with different conditions as mentioned below.
  • Search by First Name and Last Name
  • Search by only First Name
  • Search by the First name of Email
  • Search by Either first name or Email
  • Search by only Phone Number
  • Search by Phone First Name, Last Name and Phone Number
  • Search By Either Phone Number or Email.
Solution

Intercepting Filter can be used to solve the above problem statement defined by the user.
 
Class diagram of the above Problem Statement's solution.
 
 
 
Code Explanation
 
Model Class of Person.
  1. public class Person  
  2. {  
  3.   
  4.     public String FirstName { getset; }  
  5.     public String LastName { getset; }  
  6.     public String Phone { getset; }  
  7.     public String Email { getset; }  
  8. }  
Search Criteria Interface.
  1. public interface ICriteria  
  2.    {  
  3.             List<Person> MeetCriteria(List<Person> persons);  
  4.    }  
Search Criteria based on the First Name.
  1. public class CriteriaFirstName : ICriteria  
  2.    {  
  3.        private string searchCriteria;  
  4.        public CriteriaFirstName(string searchCriteria)  
  5.        {  
  6.            this.searchCriteria = searchCriteria;  
  7.        }  
  8.        public List<Person> MeetCriteria(List<Person> persons)  
  9.        {  
  10.            List<Person> personsData = new List<Person>();  
  11.            foreach (var item in persons)  
  12.            {  
  13.                if (item.FirstName.ToUpper().Equals(searchCriteria.ToUpper()))  
  14.                {  
  15.                    personsData.Add(item);  
  16.                }  
  17.            }  
  18.   
  19.            return personsData;  
  20.        }  
  21.    }  
Search Criterial based on the Last Name.
  1. public class CriteriaLastName : ICriteria  
  2.         {  
  3.             private string searchCriteria;  
  4.             public CriteriaLastName(string searchCriteria)  
  5.             {  
  6.                 this.searchCriteria = searchCriteria;  
  7.             }  
  8.   
  9.             public List<Person> MeetCriteria(List<Person> persons)  
  10.             {  
  11.                 List<Person> personsData = new List<Person>();  
  12.                 foreach (var item in persons)  
  13.                 {  
  14.                     if (item.LastName.ToUpper().Equals(searchCriteria.ToUpper()))  
  15.                     {  
  16.                         personsData.Add(item);  
  17.                     }  
  18.                 }  
  19.   
  20.                 return personsData;  
  21.             }  
  22.         }  
Search Criteria based on the Phone.
  1. public class CriteriaPhone : ICriteria  
  2.  {  
  3.      private string searchCriteria;  
  4.      public CriteriaPhone(string searchCriteria)  
  5.      {  
  6.          this.searchCriteria = searchCriteria;  
  7.      }  
  8.   
  9.      public List<Person> MeetCriteria(List<Person> persons)  
  10.      {  
  11.          List<Person> personsData = new List<Person>();  
  12.          foreach (var item in persons)  
  13.          {  
  14.              if (item.Phone.ToUpper().Equals(searchCriteria.ToUpper()))  
  15.              {  
  16.                  personsData.Add(item);  
  17.              }  
  18.          }  
  19.   
  20.          return personsData;  
  21.      }  
  22.  }  
Search Criteria based on Email.
  1. public class CriteriaEmail : ICriteria  
  2. {  
  3.     private string searchCriteria;  
  4.     public CriteriaEmail(string searchCriteria)  
  5.     {  
  6.         this.searchCriteria = searchCriteria;  
  7.     }  
  8.     public List<Person> MeetCriteria(List<Person> persons)  
  9.     {  
  10.         List<Person> personsData = new List<Person>();  
  11.         foreach (var item in persons)  
  12.         {  
  13.             if (item.Email.ToUpper().Equals(searchCriteria.ToUpper()))  
  14.             {  
  15.                 personsData.Add(item);  
  16.             }  
  17.         }  
  18.   
  19.         return personsData;  
  20.     }  
  21. }  
Search Expression "AND".
  1. public class AndCriteria : ICriteria  
  2. {  
  3.     private ICriteria criteria;  
  4.     private ICriteria otherCriteria;  
  5.   
  6.     public AndCriteria(ICriteria criteria, ICriteria otherCriteria)  
  7.     {  
  8.         this.criteria = criteria;  
  9.         this.otherCriteria = otherCriteria;  
  10.     }  
  11.   
  12.     public List<Person> MeetCriteria(List<Person> persons)  
  13.     {  
  14.         List<Person> firstCriteriaPersons = criteria.MeetCriteria(persons);  
  15.         return otherCriteria.MeetCriteria(firstCriteriaPersons);  
  16.     }  
  17. }  
Search Expression "OR".
  1. public class OrCriteria : ICriteria  
  2.    {  
  3.        private ICriteria criteria;  
  4.        private ICriteria otherCriteria;  
  5.   
  6.        public OrCriteria(ICriteria criteria, ICriteria otherCriteria)  
  7.        {  
  8.            this.criteria = criteria;  
  9.            this.otherCriteria = otherCriteria;  
  10.        }  
  11.   
  12.        public List<Person> MeetCriteria(List<Person> persons)  
  13.        {  
  14.            List<Person> firstCriteriaItems = criteria.MeetCriteria(persons);  
  15.            List<Person> otherCriteriaItems = otherCriteria.MeetCriteria(persons);  
  16.   
  17.            foreach (var otherItems in otherCriteriaItems)  
  18.            {  
  19.                if (!firstCriteriaItems.Contains(otherItems))  
  20.                {  
  21.                    firstCriteriaItems.Add(otherItems);  
  22.                }  
  23.            }  
  24.   
  25.            return firstCriteriaItems;  
  26.        }  
  27.   
  28.    }  
Driver code for execution.
  1. class Program  
  2.     {  
  3.         static void Main(string[] args)  
  4.         {  
  5.             List<Person> persons = new List<Person>();  
  6.   
  7.             persons.Add(new Person { FirstName = "Robert", LastName = "kerry", Phone = "1234", Email = "[email protected]"});  
  8.             persons.Add(new Person { FirstName = "Robert", LastName = "Sam", Phone = "1234", Email = "[email protected]" });  
  9.             persons.Add(new Person { FirstName = "Jon", LastName = "Kam", Phone = "1234", Email = "[email protected]" });  
  10.   
  11.             Console.WriteLine("---Search by First and Last Name----");  
  12.             ICriteria firstName = new CriteriaFirstName("Robert");  
  13.             ICriteria lastName = new CriteriaLastName("Kerry");  
  14.             ICriteria fullName = new AndCriteria(firstName, lastName);  
  15.             var searchedData = fullName.MeetCriteria(persons);  
  16.   
  17.             //Search by First and last name (And criteria)  
  18.             foreach (var person in searchedData)  
  19.             {  
  20.                 Console.WriteLine(person.FirstName);  
  21.                 Console.WriteLine(person.LastName);  
  22.                 Console.WriteLine(person.Phone);  
  23.             }  
  24.   
  25.             //Search by first name and email. (And Criteria)  
  26.             firstName = new CriteriaFirstName("Robert");  
  27.             var email = new CriteriaEmail("[email protected]");  
  28.             fullName = new AndCriteria(firstName, email);  
  29.             searchedData = fullName.MeetCriteria(persons);  
  30.             foreach (var person in searchedData)  
  31.             {  
  32.                 Console.WriteLine(person.FirstName);  
  33.                 Console.WriteLine(person.LastName);  
  34.                 Console.WriteLine(person.Phone);  
  35.             }  
  36.   
  37.             Console.WriteLine("---Search by First Name Only----");  
  38.             firstName = new CriteriaFirstName("Robert");  
  39.             searchedData = firstName.MeetCriteria(persons);  
  40.             foreach (var person in searchedData)  
  41.             {  
  42.                 Console.WriteLine(person.FirstName);  
  43.                 Console.WriteLine(person.LastName);  
  44.                 Console.WriteLine(person.Phone);  
  45.             }  
  46.   
  47.             Console.WriteLine("---Search by First Name or email ----");  
  48.             //Search by first name . (or Criteria)  
  49.             firstName = new CriteriaFirstName("Robert");  
  50.             email = new CriteriaEmail("[email protected]");  
  51.             fullName = new OrCriteria(firstName, email);  
  52.             searchedData = fullName.MeetCriteria(persons);  
  53.             foreach (var person in searchedData)  
  54.             {  
  55.                 Console.WriteLine(person.FirstName);  
  56.                 Console.WriteLine(person.LastName);  
  57.                 Console.WriteLine(person.Phone);  
  58.             }  
  59.             
  60.             Console.ReadKey();  
  61.         }  
  62.     }  
Conclusion

Intercepting Filter Pattern creates dynamic filtering based on the search condition. It is very powerful design pattern for building the Interpreter. 
 
Also, find the attached code related to this problem statement.