コード例 #1
0
 private static BasicFilterBase Clone(this BasicFilter criteria)
 {
     return(new BasicFilter
     {
         Field = criteria.Field,
         Operator = criteria.Operator,
         Value = criteria.Value,
         Value2 = criteria.Value2,
         Values = criteria.Values
     });
 }
コード例 #2
0
        private BaseCriteria Convert(BasicFilter filter)
        {
            if (filter == null)
            {
                throw new ArgumentNullException("criteria");
            }

            if (!filter.IsValid)
            {
                throw new ArgumentOutOfRangeException("InvalidFilterCriteria", filter.ToJson());
            }

            if (_processCriteria != null)
            {
                var processed = _processCriteria(filter);
                if (!Object.ReferenceEquals(processed, null))
                {
                    if (processed.IsEmpty)
                    {
                        throw new ArgumentOutOfRangeException("EmptyFilterLine", filter.ToJson());
                    }

                    return(processed);
                }
            }

            string fieldName = filter.Field;

            Field field = null;

            if (_row != null)
            {
                field = _row.FindField(fieldName);
            }

            // if filter fields list is specified, the fieldname must exist in this list, otherwise
            // it may be an hacking attempt, as user tries to filter a field that he is not
            // represented with
            IFilterField filterField = null;

            if (filterFields != null)
            {
                filterField = filterFields.ByNameOrTextual(fieldName);
                if (filterField == null &&
                    (field == null || field.Flags.HasFlag(FieldFlags.DenyFiltering)))
                {
                    throw new ArgumentOutOfRangeException("UnknownFilterField", fieldName);
                }
            }

            //var type = GetFilterFieldType(field, fieldName);
            var fieldExpr = GetFieldExpression(field, fieldName);

            if (fieldExpr == null)
            {
                // field is not found anywhere, don't allow unknown fields as it may cause a script injection
                // attack or other types of security threats!
                throw new ArgumentOutOfRangeException("UnknownFilterField", filter.ToJson());
            }

            bool isInteger = (filterField != null && (filterField.Handler == "Integer")) ||
                             (filterField == null && field != null && (field is Int16Field || field is Int32Field || field is Int64Field));

            bool isDecimal = (filterField != null && (filterField.Handler == "Decimal")) ||
                             (filterField == null && field != null && (field is DoubleField || field is DecimalField));

            bool isNumeric = isInteger || isDecimal;

            bool isDateTime =
                (filterField != null && (filterField.Handler == "Date")) ||
                (filterField == null && field != null &&
                 (field is DateTimeField));

            var op = filter.Operator;

            switch (op)
            {
            case FilterOp.True:
                return(new Criteria(fieldExpr) == 1);

            case FilterOp.False:
                return(new Criteria(fieldExpr) == 0);

            case FilterOp.IsNull:
                return(new Criteria(fieldExpr).IsNull());

            case FilterOp.IsNotNull:
                return(new Criteria(fieldExpr).IsNotNull());

            case FilterOp.Like:
                return(new Criteria(fieldExpr).Like(filter.Value));

            case FilterOp.NotLike:
                return(new Criteria(fieldExpr).NotLike(filter.Value));

            case FilterOp.Contains:
                return(new Criteria(fieldExpr).Contains(filter.Value));

            case FilterOp.NotContains:
                return(new Criteria(fieldExpr).NotContains(filter.Value));

            case FilterOp.StartsWith:
                return(new Criteria(fieldExpr).StartsWith(filter.Value));

            case FilterOp.EndsWith:
                return(new Criteria(fieldExpr).EndsWith(filter.Value));

            case FilterOp.IN:
            case FilterOp.NotIN:
            {
                var values = new List <object>();
                foreach (var s in filter.Values)
                {
                    if (isDecimal)
                    {
                        values.Add(ParseDoubleValue(s));
                    }
                    else if (isInteger)
                    {
                        values.Add(ParseIntegerValue(field, s));
                    }
                    else
                    {
                        values.Add(s);
                    }
                }

                if (values.Count == 0)
                {
                    throw new ArgumentOutOfRangeException("InvalidFilterLine", filter.ToJson());
                }

                if (op == FilterOp.IN)
                {
                    return(new Criteria(fieldExpr).In(values.ToArray()));
                }
                else
                {
                    return(new Criteria(fieldExpr).NotIn(values.ToArray()));
                }
            }
            }

            // parse value1 and value2
            string value1Text = filter.Value.TrimToEmpty();
            string value2Text = filter.Value2.TrimToEmpty();

            if ((op == FilterOp.BW || op == FilterOp.NotBW))
            {
                if (value1Text.IsNullOrEmpty() || value2Text.IsNullOrEmpty())
                {
                    throw new ArgumentOutOfRangeException("InvalidFilterLine", filter.ToJson());
                }

                if (isInteger)
                {
                    return(new Criteria(fieldExpr) >= ParseIntegerValue(field, value1Text) &
                           new Criteria(fieldExpr) <= ParseIntegerValue(field, value2Text));
                }
                else if (isDecimal)
                {
                    return(new Criteria(fieldExpr) >= ParseDoubleValue(value1Text) &
                           new Criteria(fieldExpr) <= ParseDoubleValue(value2Text));
                }
                else if (isDateTime)
                {
                    var d1 = ParseDateTimeValue(value1Text);
                    var d2 = ParseDateTimeValue(value2Text);

                    if (d1.Date == d1 && d2.Date == d2)
                    {
                        if (op == FilterOp.BW)
                        {
                            return(new Criteria(fieldExpr) >= d1.Date & new Criteria(fieldExpr) < d2.Date.AddDays(1));
                        }
                        else
                        {
                            return(~(new Criteria(fieldExpr) < d1.Date | new Criteria(fieldExpr) >= d2.Date.AddDays(1)));
                        }
                    }
                    else
                    {
                        if (op == FilterOp.BW)
                        {
                            return(new Criteria(fieldExpr) >= d1 & new Criteria(fieldExpr) <= d2);
                        }
                        else
                        {
                            return(~((new Criteria(fieldExpr) < d1 | new Criteria(fieldExpr) > d2)));
                        }
                    }
                }
                else
                {
                    if (op == FilterOp.BW)
                    {
                        return(new Criteria(fieldExpr) >= value1Text & new Criteria(fieldExpr) <= value2Text);
                    }
                    else
                    {
                        return(~((new Criteria(fieldExpr) < value2Text | new Criteria(fieldExpr) > value2Text)));
                    }
                }
            }

            var result = new Criteria(fieldExpr);

            if (isInteger)
            {
                var i = ParseIntegerValue(field, value1Text);
                if (op == FilterOp.EQ)
                {
                    return(result == i);
                }
                else if (op == FilterOp.NE)
                {
                    return(result != i);
                }
                else if (op == FilterOp.GT)
                {
                    return(result > i);
                }
                else if (op == FilterOp.GE)
                {
                    return(result >= i);
                }
                else if (op == FilterOp.LT)
                {
                    return(result < i);
                }
                else if (op == FilterOp.LE)
                {
                    return(result <= i);
                }
            }
            else if (isDecimal)
            {
                var o = ParseIntegerValue(field, value1Text);
                if (op == FilterOp.EQ)
                {
                    return(result == o);
                }
                else if (op == FilterOp.NE)
                {
                    return(result != o);
                }
                else if (op == FilterOp.GT)
                {
                    return(result > o);
                }
                else if (op == FilterOp.GE)
                {
                    return(result >= o);
                }
                else if (op == FilterOp.LT)
                {
                    return(result < o);
                }
                else if (op == FilterOp.LE)
                {
                    return(result <= o);
                }
            }
            else if (isDateTime)
            {
                var d = ParseDateTimeValue(value1Text);
                if (d.Date == d)
                {
                    if (op == FilterOp.EQ)
                    {
                        return(result >= d & result < d.AddDays(1));
                    }
                    else if (op == FilterOp.NE)
                    {
                        return(~(result < d | result >= d.AddDays(1)));
                    }
                    else if (op == FilterOp.GT)
                    {
                        return(result >= d.AddDays(1));
                    }
                    else if (op == FilterOp.GE)
                    {
                        return(result >= d);
                    }
                    else if (op == FilterOp.LT)
                    {
                        return(result < d);
                    }
                    else if (op == FilterOp.LE)
                    {
                        return(result < d.AddDays(1));
                    }
                }
                else
                {
                    if (op == FilterOp.EQ)
                    {
                        return(result == d);
                    }
                    else if (op == FilterOp.NE)
                    {
                        return(result != d);
                    }
                    else if (op == FilterOp.GT)
                    {
                        return(result > d);
                    }
                    else if (op == FilterOp.GE)
                    {
                        return(result >= d);
                    }
                    else if (op == FilterOp.LT)
                    {
                        return(result < d);
                    }
                    else if (op == FilterOp.LE)
                    {
                        return(result <= d);
                    }
                }
            }
            else
            {
                if (op == FilterOp.EQ)
                {
                    return(result == value1Text);
                }
                else if (op == FilterOp.NE)
                {
                    return(result != value1Text);
                }
                else if (op == FilterOp.GT)
                {
                    return(result > value1Text);
                }
                else if (op == FilterOp.GE)
                {
                    return(result >= value1Text);
                }
                else if (op == FilterOp.LT)
                {
                    return(result < value1Text);
                }
                else if (op == FilterOp.LE)
                {
                    return(result <= value1Text);
                }
            }

            throw new InvalidOperationException();
        }
コード例 #3
0
        public static bool IsSame(this BasicFilterBase filter, BasicFilterBase other)
        {
            if (filter == null)
            {
                return(other == null);
            }

            var g = filter as BasicFilterGroup;

            if (g != null)
            {
                var go = other as BasicFilterGroup;
                if (go == null)
                {
                    return(false);
                }

                if (g.Nodes.Count != go.Nodes.Count)
                {
                    return(false);
                }

                for (var i = 0; i < g.Nodes.Count; i++)
                {
                    if (!IsSame(g.Nodes[i], go.Nodes[i]))
                    {
                        return(false);
                    }
                }
            }
            else
            {
                BasicFilter c  = (BasicFilter)filter;
                BasicFilter co = other as BasicFilter;
                if (co == null)
                {
                    return(false);
                }

                if (c.Field != co.Field)
                {
                    return(false);
                }

                if (c.Operator != co.Operator)
                {
                    return(false);
                }

                if (c.Value != co.Value)
                {
                    return(false);
                }

                if (c.Value2 != co.Value2)
                {
                    return(false);
                }

                if ((c.Values == null) != (co.Values == null))
                {
                    return(false);
                }

                if (c.Values != null)
                {
                    if (c.Values.Length != co.Values.Length)
                    {
                        return(false);
                    }

                    for (var i = 0; i < c.Values.Length; i++)
                    {
                        if (c.Values[i] != co.Values[i])
                        {
                            return(false);
                        }
                    }
                }
            }

            return(true);
        }
コード例 #4
0
        public static BasicFilterBase ToBasicFilter(this IList <FilterLine> lines)
        {
            if (lines == null)
            {
                throw new ArgumentNullException("lines");
            }

            if (lines.Count == 0)
            {
                return(null);
            }

            bool inParens = false;

            // http://en.wikipedia.org/wiki/Shunting_yard_algorithm
            // http://en.wikipedia.org/wiki/Reverse_Polish_Notation

            List <BasicFilter> filters   = new List <BasicFilter>(lines.Count);
            List <int>         rpnOutput = new List <int>(lines.Count * 2); // will contain negative or indexes of items
            Stack <int>        rpnStack  = new Stack <int>(lines.Count * 2);

            int intLeftParen = -1;
            int intAnd       = -2;
            int intOr        = -3;
            int index        = 0;

            foreach (FilterLine line in lines)
            {
                if (inParens &&
                    (line.RightParen || line.LeftParen))
                {
                    while (true)
                    {
                        var token = rpnStack.Pop();
                        if (token == intLeftParen)
                        {
                            break;
                        }
                        rpnOutput.Add(token);
                    }
                    inParens = false;
                }

                if (index > 0)
                {
                    var token = line.OR ? intOr : intAnd;
                    while (true)
                    {
                        if (rpnStack.Count == 0)
                        {
                            break;
                        }
                        var topToken = rpnStack.Peek();
                        if (topToken < intLeftParen &&
                            token <= topToken)
                        {
                            rpnOutput.Add(rpnStack.Pop());
                        }
                        else
                        {
                            break;
                        }
                    }

                    rpnStack.Push(token);
                }

                if (line.LeftParen)
                {
                    rpnStack.Push(intLeftParen);
                }

                rpnOutput.Add(index);

                index++;
            }

            if (inParens)
            {
                while (true)
                {
                    var token = rpnStack.Pop();
                    if (token == intLeftParen)
                    {
                        break;
                    }
                    rpnOutput.Add(token);
                }
            }

            while (rpnStack.Count > 0)
            {
                var token = rpnStack.Pop();
                if (token == intLeftParen)
                {
                    throw new InvalidOperationException("mismatched leftParen in RPN stack!");
                }
                rpnOutput.Add(token);
            }

            var evaluationStack = new Stack <BasicFilterBase>();

            foreach (var input in rpnOutput)
            {
                if (input >= 0)
                {
                    BasicFilter item = new BasicFilter();
                    var         line = lines[input];
                    item.Field    = line.Field;
                    item.Operator = line.Op;
                    item.Value    = line.Value;
                    item.Values   = line.Values;

                    evaluationStack.Push(item);
                }
                else
                {
                    if (evaluationStack.Count < 2)
                    {
                        throw new InvalidOperationException("RPN evaluation stack has less than two items!");
                    }

                    LogicalOp op = input == intAnd ? LogicalOp.And : LogicalOp.Or;

                    var             right  = evaluationStack.Pop();
                    var             left   = evaluationStack.Pop();
                    BasicFilterBase result = left.Merge(op, right);
                    evaluationStack.Push(result);
                }
            }

            if (evaluationStack.Count > 1)
            {
                throw new InvalidOperationException("RPN evaluation stack has more than one item!");
            }

            return(evaluationStack.Pop());
        }