Example #1
0
        public void EnsureComparable(Type type, RsqlParser.ComparisonContext context)
        {
            type    = type ?? throw new ArgumentNullException(nameof(type));
            context = context ?? throw new ArgumentNullException(nameof(context));

            var effectiveType = type.FindNullableValueType() ?? type;

            if (!this.IsComparableType(effectiveType))
            {
                throw new InvalidComparatorException(context);
            }
        }
Example #2
0
        public virtual Expression <Func <T, bool> > BuildComparison <T>(
            string comparator,
            ParameterExpression parameter,
            RsqlParser.ComparisonContext context)
        {
            comparator = comparator ?? throw new ArgumentNullException(nameof(comparator));
            parameter  = parameter ?? throw new ArgumentNullException(nameof(parameter));
            context    = context ?? throw new ArgumentNullException(nameof(context));

            switch (comparator)
            {
            case "==":
            case "=eq=":
                return(this.EqualComparator <T>(parameter, context));

            case "!=":
            case "=neq=":
                return(this.NotEqualComparator <T>(parameter, context));

            case "<":
            case "=lt=":
                return(this.LessThanComparator <T>(parameter, context));

            case "<=":
            case "=le=":
                return(this.LessOrEqualComparator <T>(parameter, context));

            case ">":
            case "=gt=":
                return(this.GreaterThanComparator <T>(parameter, context));

            case ">=":
            case "=ge=":
                return(this.GreaterOrEqualComparator <T>(parameter, context));

            case "=is-null=":
            case "=nil=":
                return(this.IsNullComparator <T>(parameter, context));

            case "=in=":
                return(this.InComparator <T>(parameter, context));

            case "=out=":
            case "=nin=":
                return(this.NotInComparator <T>(parameter, context));

            default:
                throw new UnknownComparatorException(context);
            }
        }
Example #3
0
        private static object GetSingleValue(Type type, RsqlParser.ComparisonContext context)
        {
            type    = type ?? throw new ArgumentNullException(nameof(type));
            context = context ?? throw new ArgumentNullException(nameof(context));

            var value = context.arguments().value();

            if (value.Length > 1)
            {
                throw new TooManyArgumentsException(context);
            }

            return(ValueParser.GetValue(type, value.First()));
        }
Example #4
0
 public InvalidComparatorException(RsqlParser.ComparisonContext context, Exception?innerException = null)
     : base(context, $"Invalid comparator: {context.selector().GetText()}", innerException)
 {
 }
Example #5
0
        public override Expression <Func <T, bool> > VisitComparison(RsqlParser.ComparisonContext context)
        {
            var comparator = context.comparator().GetText().ToLowerInvariant();

            return(this._expressionHelper.BuildComparison <T>(comparator, this._parameter, context));
        }
Example #6
0
 /// <summary>
 /// Visit a parse tree produced by <see cref="RsqlParser.comparison"/>.
 /// <para>
 /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
 /// on <paramref name="context"/>.
 /// </para>
 /// </summary>
 /// <param name="context">The parse tree.</param>
 /// <return>The visitor result.</return>
 public virtual Result VisitComparison([NotNull] RsqlParser.ComparisonContext context)
 {
     return(VisitChildren(context));
 }
Example #7
0
 public UnknownComparatorException(RsqlParser.ComparisonContext context, Exception?innerException = null)
     : base(context, $"Unknown comparator: {context.comparator().GetText()}", innerException)
 {
 }
Example #8
0
 public TooManyArgumentsException(RsqlParser.ComparisonContext context, Exception?innerException = null)
     : base(context, $"Too many arguments: {context.selector().GetText()}", innerException)
 {
 }
Example #9
0
        public Expression <Func <T, bool> > NotInComparator <T>(ParameterExpression parameter, RsqlParser.ComparisonContext context)
        {
            parameter = parameter ?? throw new ArgumentNullException(nameof(parameter));
            context   = context ?? throw new ArgumentNullException(nameof(context));

            var expression = this.InComparator <T>(parameter, context);
            var body       = Expression.Not(expression.Body);

            return(Expression.Lambda <Func <T, bool> >(body, parameter));
        }
Example #10
0
        public Expression <Func <T, bool> > InComparator <T>(ParameterExpression parameter, RsqlParser.ComparisonContext context)
        {
            parameter = parameter ?? throw new ArgumentNullException(nameof(parameter));
            context   = context ?? throw new ArgumentNullException(nameof(context));

            var expressionPath = this._propertyAccessor.ParsePath(parameter, context.selector().GetText());

            this.EnsureEquatable(expressionPath.Type, context);

            var values             = ValueParser.GetValues(expressionPath.Type, context.arguments());
            var methodContainsInfo = ContainsHelper.GetOrRegistryContainsMethodInfo(expressionPath.Type);

            return(Expression.Lambda <Func <T, bool> >(
                       ComparisonBuilder.PathNotNull(
                           expressionPath,
                           Expression.Call(
                               Expression.Constant(methodContainsInfo.Convert(values)),
                               methodContainsInfo.ContainsMethod,
                               expressionPath.Expression)),
                       parameter));
        }
Example #11
0
        public Expression <Func <T, bool> > LikeComparator <T>(ParameterExpression parameter, RsqlParser.ComparisonContext context)
        {
            parameter = parameter ?? throw new ArgumentNullException(nameof(parameter));
            context   = context ?? throw new ArgumentNullException(nameof(context));

            var expressionPath = this._propertyAccessor.ParsePath(parameter, context.selector().GetText());

            if (expressionPath.Type != typeof(string))
            {
                throw new InvalidComparatorException(context);
            }

            var like = (string)ComparisonBuilder.GetSingleValue(expressionPath.Type, context);

            like = like.Replace(@"\*", ComparisonBuilder.EscapedLikePlaceholder);
            MethodInfo method;
            var        startsWild = like.StartsWith("*");
            var        endsWild   = like.EndsWith("*");

            if (!startsWild && endsWild)
            {
                method = ContainsHelper.StringStartsWithMethod;
            }
            else if (startsWild && !endsWild)
            {
                method = ContainsHelper.StringEndsWithMethod;
            }
            else
            {
                method = ContainsHelper.StringContainsMethod;
            }

            like = like.Replace("*", string.Empty).Replace(ComparisonBuilder.EscapedLikePlaceholder, "*");
            return(Expression.Lambda <Func <T, bool> >(
                       ComparisonBuilder.FullPathNotNull(
                           expressionPath,
                           Expression.Call(
                               expressionPath.Expression,
                               method,
                               Expression.Constant(like, expressionPath.Type))),
                       parameter));
        }
Example #12
0
        public Expression <Func <T, bool> > GreaterOrEqualComparator <T>(ParameterExpression parameter, RsqlParser.ComparisonContext context)
        {
            parameter = parameter ?? throw new ArgumentNullException(nameof(parameter));
            context   = context ?? throw new ArgumentNullException(nameof(context));

            var expressionPath = this._propertyAccessor.ParsePath(parameter, context.selector().GetText());

            this.EnsureComparable(expressionPath.Type, context);

            var value = ComparisonBuilder.GetSingleValue(expressionPath.Type, context);

            return(Expression.Lambda <Func <T, bool> >(
                       ComparisonBuilder.PathNotNull(
                           expressionPath,
                           Expression.GreaterThanOrEqual(
                               expressionPath.Expression,
                               Expression.Constant(value, expressionPath.Type))),
                       parameter));
        }
Example #13
0
        public Expression <Func <T, bool> > IsNullComparator <T>(ParameterExpression parameter, RsqlParser.ComparisonContext context)
        {
            parameter = parameter ?? throw new ArgumentNullException(nameof(parameter));
            context   = context ?? throw new ArgumentNullException(nameof(context));

            var expressionPath = this._propertyAccessor.ParsePath(parameter, context.selector().GetText());
            var value          = (bool)ComparisonBuilder.GetSingleValue(typeof(bool), context);

            var lastNullableExpression = expressionPath.ExpressionSteps.LastOrDefault(e => ComparisonBuilder.CanBeNull(e.Type));

            if (lastNullableExpression == null)
            {
                // Can never be null
                return(Expression.Lambda <Func <T, bool> >(Expression.Constant(!value), parameter));
            }

            var result = Expression.Lambda <Func <T, bool> >(
                ComparisonBuilder.PathCanBeNull(
                    expressionPath,
                    Expression.Equal(
                        lastNullableExpression,
                        Expression.Constant(null, typeof(object)))),
                parameter);

            if (value)
            {
                return(result);
            }

            var body = Expression.Not(result.Body);

            result = Expression.Lambda <Func <T, bool> >(body, parameter);
            return(result);
        }
Example #14
0
        public Expression <Func <T, bool> > EqualComparator <T>(ParameterExpression parameter, RsqlParser.ComparisonContext context)
        {
            parameter = parameter ?? throw new ArgumentNullException(nameof(parameter));
            context   = context ?? throw new ArgumentNullException(nameof(context));

            var expressionPath = this._propertyAccessor.ParsePath(parameter, context.selector().GetText());

            this.EnsureEquatable(expressionPath.Type, context);

            var value = ComparisonBuilder.GetSingleValue(expressionPath.Type, context);

            if (expressionPath.Type != typeof(string))
            {
                return(Expression.Lambda <Func <T, bool> >(
                           ComparisonBuilder.PathNotNull(
                               expressionPath,
                               Expression.Equal(
                                   expressionPath.Expression,
                                   Expression.Constant(value, expressionPath.Type)
                                   )),
                           parameter));
            }

            var escapedLike = ((string)value).Replace(@"\*", ComparisonBuilder.EscapedLikePlaceholder);

            if (escapedLike.Contains('*'))
            {
                return(this.LikeComparator <T>(parameter, context));
            }

            escapedLike = escapedLike.Replace(ComparisonBuilder.EscapedLikePlaceholder, "*");
            return(Expression.Lambda <Func <T, bool> >(
                       ComparisonBuilder.PathNotNull(
                           expressionPath,
                           Expression.Equal(
                               expressionPath.Expression,
                               Expression.Constant(escapedLike, expressionPath.Type))),
                       parameter));
        }