Exemple #1
0
        private static IReadOnlyCollection <IFilter> And(IReadOnlyCollection <IFilter> left, IFilter right)
        {
            if (null == left)
            {
                throw new ArgumentNullException(nameof(left));
            }

            if (null == right)
            {
                throw new ArgumentNullException(nameof(right));
            }

            for (int index = 0; index < left.Count; index++)
            {
                IFilter leftFilter = left.ElementAt(index);
                FilterExpression.And(leftFilter, right);
            }
            return(left);
        }
Exemple #2
0
        private static void And(IFilter left, IFilter right)
        {
            if (null == left)
            {
                throw new ArgumentNullException(nameof(left));
            }

            if (null == right)
            {
                throw new ArgumentNullException(nameof(right));
            }

            if (null == left.AdditionalFilter)
            {
                left.AdditionalFilter = right;
            }
            else
            {
                FilterExpression.And(left.AdditionalFilter, right);
            }
        }
Exemple #3
0
        private static IReadOnlyCollection <IFilter> And(IFilter left, IReadOnlyCollection <IFilter> right)
        {
            List <IFilter> result   = new List <IFilter>();
            IFilter        template = new Filter(left);

            for (int index = 0; index < right.Count; index++)
            {
                IFilter rightFilter = right.ElementAt(index);
                IFilter leftFilter;
                if (0 == index)
                {
                    leftFilter = left;
                }
                else
                {
                    leftFilter = new Filter(template);
                    result.Add(leftFilter);
                }
                FilterExpression.And(leftFilter, rightFilter);
            }
            return(result);
        }
Exemple #4
0
        // Convert the doubly-linked list into a collection of IFilter objects.
        // There are three cases that may be encountered as the conversion proceeds through the linked list of clauses.
        // Those cases are documented by comments below.
        private IReadOnlyCollection <IFilter> Convert()
        {
            List <IFilter> result     = new List <IFilter>();
            IFilter        thisFilter = this.ToFilter();

            result.Add(thisFilter);
            FilterExpression current = this.next;

            while (current != null)
            {
                if (this.Level == current.Level)
                {
                    // The current clause has the same level number as the initial clause,
                    // such as
                    // b eq 2
                    // in the expression
                    // a eq 1 and b eq 2.
                    IFilter filter = current.ToFilter();
                    switch (current.Previous.logicalOperator)
                    {
                    case LogicalOperatorValue.and:
                        IFilter left = result.Last();
                        FilterExpression.And(left, filter);
                        break;

                    case LogicalOperatorValue.or:
                        result.Add(filter);
                        break;

                    default:
                        string notSupported = Enum.GetName(typeof(LogicalOperatorValue), this.logicalOperator);
                        throw new NotSupportedException(notSupported);
                    }
                    current = current.next;
                }
                else if (this.Level > current.Level)
                {
                    // The current clause has a lower level number than the initial clause,
                    // such as
                    // c eq 3
                    // in the expression
                    // (a eq 1 and b eq 2) or c eq 3.
                    IReadOnlyCollection <IFilter> superiors = current.Convert();
                    switch (current.Previous.logicalOperator)
                    {
                    case LogicalOperatorValue.and:
                        IFilter superior = superiors.First();
                        result = FilterExpression.And(result, superior).ToList();
                        IReadOnlyCollection <IFilter> remainder = superiors.Skip(1).ToArray();
                        result.AddRange(remainder);
                        break;

                    case LogicalOperatorValue.or:
                        result.AddRange(superiors);
                        break;

                    default:
                        string notSupported = Enum.GetName(typeof(LogicalOperatorValue), this.logicalOperator);
                        throw new NotSupportedException(notSupported);
                    }
                    break;
                }
                else
                {
                    // The current clause has a higher level number than the initial clause,
                    // such as
                    // b eq 2
                    // in the expression
                    // a eq 1 and (b eq 2 or c eq 3) and (d eq 4 or e eq 5)
                    //
                    // In this case, the linked list is edited,
                    // so that
                    // c eq 3
                    // has no next link,
                    // while the next link of
                    // a eq 1
                    // refers to
                    // d eq 4.
                    // Thereby,
                    // b eq 2 or c eq 3
                    // can be converted to filters and combined with the filter composed from
                    // a eq 1,
                    // after which conversion will continue with the conversion of
                    // d eq 4.
                    // It is the change in group number between
                    // c eq 3
                    // and
                    // d eq 4
                    // that identifies the end of current group,
                    // despite the two clauses having the same level number.
                    //
                    // It is because of the editing of the linked list that the public method,
                    // ToFilters(),
                    // makes a copy of the linked list before initiating conversion;
                    // so that,
                    // ToFilters()
                    // can be called on a FilterExpression any number of times,
                    // to yield the same output.
                    FilterExpression subordinate = current;
                    while (current != null && this.Level < current.Level && subordinate.Group == current.Group)
                    {
                        current = current.next;
                    }
                    if (current != null)
                    {
                        current.Previous.next     = null;
                        subordinate.Previous.next = current;
                    }
                    IReadOnlyCollection <IFilter> subordinates = subordinate.Convert();
                    switch (subordinate.Previous.logicalOperator)
                    {
                    case LogicalOperatorValue.and:
                        IFilter superior = result.Last();
                        IReadOnlyCollection <IFilter> merged = FilterExpression.And(superior, subordinates);
                        result.AddRange(merged);
                        break;

                    case LogicalOperatorValue.or:
                        result.AddRange(subordinates);
                        break;

                    default:
                        string notSupported = Enum.GetName(typeof(LogicalOperatorValue), this.logicalOperator);
                        throw new NotSupportedException(notSupported);
                    }
                }
            }
            return(result);
        }