Problem

  • Reduce number of exchange items a Linkable component exposes through its interface

Proposal


    interface IFilter
    {
        string ShortName();
        string Description();
        bool Exclude(IExchangeItem item);
    }

    // Optional Extension

    interface IFilterable
    {
        int SuggestedFilterCount { get; }
        IFilter FilterSugestion(int index);
    }
  • 3rd parties could also provide library of useful filters
  • OmiEd could then make these filters available to the user via the GUI

Examples


        static List<IInputExchangeItem> FilteredExchangeItems(ILinkableComponent iLC)
        {
            List<IInputExchangeItem> items = new List<IInputExchangeItem>();

            if (iLC is IFilterable)
            {
                IFilterable iFilterable = (IFilterable)iLC;

                List<IFilter> activeFilters = new List<IFilter>();

                // Make all sugestions active, would be GUI controlled, 
                // and could include 3rd part supplied filters as well
                for (int n = 0; n < iFilterable.SuggestedFilterCount; ++n)
                    activeFilters.Add(iFilterable.FilterSugestion(n));

                for (int n = 0; n < iLC.InputExchangeItemCount; ++n)
                {
                    foreach (IFilter f in activeFilters)
                    {
                        if (f.Exclude(iLC.GetInputExchangeItem(n)))
                            continue;
                        items.Add(iLC.GetInputExchangeItem(n));
                    }
                }
            }
            else
            {
                for (int n = 0; n < iLC.InputExchangeItemCount; ++n)
                    items.Add(iLC.GetInputExchangeItem(n));
            }

            return items;
        }

    class LinkableComponent : ILinkableComponent, IFilterable
    {
        #region ILinkableComponent Members
        #endregion

        #region IPublisher Members
        #endregion

        #region IFilterable Members

        public int SuggestedFilterCount
        {
            get { return 1; }
        }

        public IFilter FilterSugestion(int index)
        {
            switch (index)
            {
                case 0:
                    return new FilterQuantity("Flow");
            }

            throw new Exception("Out of range");
        }

        #endregion
    }

    class FilterIdRegExp : IFilter
    {
        Regex _reg; 

        FilterIdRegExp(string reg)
        {
            _reg = new Regex(reg);
        }

        string ShortName()
        {
            return string.Format("Filter on \"{0}\"", _reg);
        }
        string Description()
        {
            return string.Format("Filter to match ElementSet Id against Regular Expression {0}", _reg);
        }

        bool Exclude(IExchangItem item)
        {
            return !_reg.Match(item.ElementSet().ID());
        }
    }

    class FilterQuantity : IFilter
    {
        string _quantity;

        FilterQuantity(string quantity)
        {
            _quantity = quantity;
        }

        string ShortName()
        {
            return string.Format("Filter on \"{0}\"", _quantity);
        }
        string Description()
        {
            return string.Format("Filter to match Quantity Id against \"{0}\"", _quantity);
        }

        bool Exclude(IExchangItem item)
        {
            return item.Quantity.ID() != _quantity;
        }
    }

    class FilterRegion : IFilter
    {
        List<IRegion> _regions;

        FilterRegion(List<IRegion> regions)
        {
            _regions = regions;
        }

        string ShortName()
        {
            return "Filter on regions";
        }
        string Description()
        {
            return "Filter on regions";
        }

        bool Exclude(IExchangItem item)
        {
            foreach (IRegion region in _regions)
                if (region.Contains(item.ElementSet()))
                    return false;

            return true;
        }
    }

1 Comment

  1. Unknown User (don)

    Very good idea! I have a few additional suggestions, comments:

    • Exclude() method seems to be overkill - someone will need to call this method may times for all existing exchange items.
    • I seems more logical to merge IFilterable into ILinkableComponent since it is the only place where collections of exchange items are used.
    • Check how Hibernate uses Criteria, Criterion: Hibernate Criteria, http://david.givoni.com/blog/?p=9
    • Not sure if there is need to return filters from component. Just CreateExchangeItemFilter() maybe more helpful. Gui will use this method to create filter and to filter exchange items based on user-provided criteria.

    See example below. Advantage is that IFilter implementation may cache collection of exchange items which should be returned it criteria will not change which may be very good for performance.

    // how to use (tests)
    class FilterTest
    {
       void FilterExchangeItemsByQuantity()
       {
          IQuantity waterLevelQuantity = new Quantity("water level", new Unit("m"));
          IComponent component = CreateComponent();
          
          // create filter in order to get filtered list of exchange items.
          IFilter filter = component.CreateExchangeItemFilter();
    
          // add quantity-based criterion to filter, user may develop his own criteria
          ICriterion quantityCriterion = new QuantityCriterion(waterLevelQuantity);
          filter.AddCriterion(quantityCriterion);
    
          // get filtered exchange items
          IList<IExchangeItem> filteredExchangeItems = filter.ExchangeItems;
       }
    }
    
    
    // implementation
    interface ILinkableComponent
    {
       IList<IExchangeItem> ExchangeItems { get; }
    
       IFilter CreateExchangeItemFilter(); 
    }
    
    interface IFilter
    {
       IList<IExchangeItem> ExchangeItems { get; } // returns filtered exchange items
    
       AddCriterion(ICriterion criterion);
    }
    
    interface ICriterion
    {
       bool IsValid(IExchangeItem);
    }
    
    class QuantityCriterion: ICriterion
    {
      QuantityCriterion(IQuantity quantity) { ... }
    
      bool IsValid(IExchangeItem item) { ... }
    }