예제 #1
0
        /// <summary>
        /// Gets the generated arguments
        /// </summary>
        /// <returns>The list of arguments</returns>
        public static IEnumerable <ApiField> GetArguments()
        {
            if (FilterType.Fields.Count > 2)
            {
                yield return
                    (FilterType.CreateField(
                         "filter",
                         EnFieldFlags.CanBeUsedInInput | EnFieldFlags.Queryable | EnFieldFlags.IsTypeArgument));
            }

            if (SortType.Values.Any())
            {
                const EnFieldFlags SortFlags =
                    EnFieldFlags.CanBeUsedInInput | EnFieldFlags.Queryable | EnFieldFlags.IsTypeArgument
                    | EnFieldFlags.IsArray;
                yield return(ApiField.Object("sort", SortType.TypeName, SortFlags));
            }

            if (NodeMetaData.KeyProperty != null)
            {
                var keyMetadata = TypeMetadata.GenerateTypeMetadata(
                    NodeMetaData.KeyProperty.PropertyType,
                    NodeMetaData.KeyProperty.GetCustomAttribute <PublishToApiAttribute>());
                if (keyMetadata.ScalarType != EnScalarType.None)
                {
                    yield return
                        (ApiField.Scalar(
                             "id",
                             keyMetadata.ScalarType,
                             EnFieldFlags.CanBeUsedInInput | EnFieldFlags.Queryable | EnFieldFlags.IsTypeArgument));
                }
            }

            yield return
                (ApiField.Scalar(
                     "limit",
                     EnScalarType.Integer,
                     EnFieldFlags.CanBeUsedInInput | EnFieldFlags.Queryable | EnFieldFlags.IsTypeArgument));

            yield return
                (ApiField.Scalar(
                     "offset",
                     EnScalarType.Integer,
                     EnFieldFlags.CanBeUsedInInput | EnFieldFlags.Queryable | EnFieldFlags.IsTypeArgument));
        }
예제 #2
0
        /// <summary>
        /// Performs final type initialization
        /// </summary>
        private static void InitializeType()
        {
            if (isInitialized)
            {
                return;
            }

            lock (LockObject)
            {
                if (isInitialized)
                {
                    return;
                }

                isInitialized = true;

                var nodeType       = ObjectResolver <T> .GeneratedType;
                var realFields     = ObjectResolver <T> .DeclaredFields;
                var sortableFields = nodeType.Fields.Where(f => f.Flags.HasFlag(EnFieldFlags.IsSortable));
                foreach (var sortableField in sortableFields)
                {
                    SortingConditions[$"{sortableField.Name}_asc"] =
                        new SortingCondition(realFields[sortableField.Name].Name, SortingCondition.EnDirection.Asc);
                    SortingConditions[$"{sortableField.Name}_desc"] =
                        new SortingCondition(realFields[sortableField.Name].Name, SortingCondition.EnDirection.Desc);
                }

                SortType.Values.AddRange(SortingConditions.Keys);

                FilterChecks["OR"] = prop =>
                {
                    var subFilters = prop.Value as JArray;
                    if (subFilters == null)
                    {
                        return(Expression.Constant(true));
                    }

                    Expression or = Expression.Constant(false);
                    or = subFilters.Children()
                         .OfType <JObject>()
                         .Aggregate(or, (current, subFilter) => Expression.Or(current, CreateFilterPart(subFilter)));

                    return(or);
                };

                FilterType.Fields.Add(
                    FilterType.CreateField(
                        "OR",
                        description: "Combine filter conditions with logic \"OR\"",
                        flags: EnFieldFlags.Queryable | EnFieldFlags.CanBeUsedInInput));

                FilterChecks["AND"] = prop =>
                {
                    var subFilters = prop.Value as JArray;
                    if (subFilters == null)
                    {
                        return(Expression.Constant(true));
                    }

                    Expression and = Expression.Constant(true);
                    and = subFilters.Children()
                          .OfType <JObject>()
                          .Aggregate(
                        and,
                        (current, subFilter) => Expression.And(current, CreateFilterPart(subFilter)));

                    return(and);
                };

                FilterType.Fields.Add(
                    FilterType.CreateField(
                        "AND",
                        description: "Combine filter conditions with logic \"AND\"",
                        flags: EnFieldFlags.Queryable | EnFieldFlags.CanBeUsedInInput));

                var filterableFields = nodeType.Fields.Where(f => f.Flags.HasFlag(EnFieldFlags.IsFilterable));

                var stringContains   = typeof(string).GetMethod("Contains");
                var stringStartsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
                var stringEndsWith   = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
                var stringToLower    = typeof(string).GetMethod("ToLower", new Type[0]);

                foreach (var filterableField in filterableFields)
                {
                    var property = realFields[filterableField.Name] as PropertyInfo;
                    if (property == null)
                    {
                        continue;
                    }

                    var propertyExpression = Expression.Property(FilterSourceParameter, property);

                    Func <JProperty, Expression> createConstant =
                        prop => Expression.Constant(prop.Value.ToObject(property.PropertyType), property.PropertyType);

                    AddFilterExpression(
                        filterableField.Name,
                        prop => Expression.Equal(propertyExpression, createConstant(prop)),
                        filterableField,
                        "{0} exactly equals to the parameter");
                    AddFilterExpression(
                        $"{filterableField.Name}_not",
                        prop => Expression.NotEqual(propertyExpression, createConstant(prop)),
                        filterableField,
                        "{0} not equals to the parameter");

                    switch (filterableField.ScalarType)
                    {
                    case EnScalarType.Float:
                    case EnScalarType.Decimal:
                    case EnScalarType.Integer:
                    case EnScalarType.DateTime:
                        AddFilterExpression(
                            $"{filterableField.Name}_lt",
                            prop => Expression.LessThan(propertyExpression, createConstant(prop)),
                            filterableField,
                            "{0} is less then the parameter");
                        AddFilterExpression(
                            $"{filterableField.Name}_lte",
                            prop => Expression.LessThanOrEqual(propertyExpression, createConstant(prop)),
                            filterableField,
                            "{0} is less then or equal to the parameter");
                        AddFilterExpression(
                            $"{filterableField.Name}_gt",
                            prop => Expression.GreaterThan(propertyExpression, createConstant(prop)),
                            filterableField,
                            "{0} is greater then the parameter");
                        AddFilterExpression(
                            $"{filterableField.Name}_gte",
                            prop => Expression.GreaterThanOrEqual(propertyExpression, createConstant(prop)),
                            filterableField,
                            "{0} is greater then or equal to the parameter");
                        break;

                    case EnScalarType.String:
                        var propertyToLower = Expression.Call(propertyExpression, stringToLower);
                        AddFilterExpression(
                            $"{filterableField.Name}_in",
                            prop => Expression.Call(createConstant(prop), stringContains, propertyExpression),
                            filterableField,
                            "{0} is a substring of the parameter");
                        AddFilterExpression(
                            $"{filterableField.Name}_not_in",
                            prop =>
                            Expression.Not(
                                Expression.Call(createConstant(prop), stringContains, propertyExpression)),
                            filterableField,
                            "{0} is not a substring of the parameter");
                        AddFilterExpression(
                            $"{filterableField.Name}_contains",
                            prop => Expression.Call(propertyExpression, stringContains, createConstant(prop)),
                            filterableField,
                            "{0} contains the parameter as substring");
                        AddFilterExpression(
                            $"{filterableField.Name}_not_contains",
                            prop =>
                            Expression.Not(
                                Expression.Call(propertyExpression, stringContains, createConstant(prop))),
                            filterableField,
                            "{0} doesn't contain the parameter as substring");
                        AddFilterExpression(
                            $"{filterableField.Name}_starts_with",
                            prop => Expression.Call(propertyExpression, stringStartsWith, createConstant(prop)),
                            filterableField,
                            "{0} starts with the parameter value");
                        AddFilterExpression(
                            $"{filterableField.Name}_not_starts_with",
                            prop =>
                            Expression.Not(
                                Expression.Call(propertyExpression, stringStartsWith, createConstant(prop))),
                            filterableField,
                            "{0} doesn't start with the parameter value");
                        AddFilterExpression(
                            $"{filterableField.Name}_ends_with",
                            prop => Expression.Call(propertyExpression, stringEndsWith, createConstant(prop)),
                            filterableField,
                            "{0} ends with the parameter value");
                        AddFilterExpression(
                            $"{filterableField.Name}_not_ends_with",
                            prop =>
                            Expression.Not(
                                Expression.Call(propertyExpression, stringEndsWith, createConstant(prop))),
                            filterableField,
                            "{0} doesn't end with the parameter value");

                        AddFilterExpression(
                            $"{filterableField.Name}_l",
                            prop => Expression.Equal(propertyToLower, createConstant(prop)),
                            filterableField,
                            "{0} lowercased equals the parameter");

                        AddFilterExpression(
                            $"{filterableField.Name}_l_not",
                            prop => Expression.NotEqual(propertyToLower, createConstant(prop)),
                            filterableField,
                            "{0} lowercased doesn't equal the parameter");

                        AddFilterExpression(
                            $"{filterableField.Name}_l_in",
                            prop => Expression.Call(createConstant(prop), stringContains, propertyToLower),
                            filterableField,
                            "{0} lowercased is a substring of the parameter");
                        AddFilterExpression(
                            $"{filterableField.Name}_l_not_in",
                            prop =>
                            Expression.Not(
                                Expression.Call(createConstant(prop), stringContains, propertyToLower)),
                            filterableField,
                            "{0} lowercased is not a substring of the parameter");
                        AddFilterExpression(
                            $"{filterableField.Name}_l_contains",
                            prop => Expression.Call(propertyToLower, stringContains, createConstant(prop)),
                            filterableField,
                            "{0} lowercased contains the parameter as substring");
                        AddFilterExpression(
                            $"{filterableField.Name}_l_not_contains",
                            prop =>
                            Expression.Not(
                                Expression.Call(propertyToLower, stringContains, createConstant(prop))),
                            filterableField,
                            "{0} lowercased doesn't contain the parameter as substring");
                        AddFilterExpression(
                            $"{filterableField.Name}_l_starts_with",
                            prop => Expression.Call(propertyToLower, stringStartsWith, createConstant(prop)),
                            filterableField,
                            "{0} lowercased starts with the parameter value");
                        AddFilterExpression(
                            $"{filterableField.Name}_l_not_starts_with",
                            prop =>
                            Expression.Not(
                                Expression.Call(propertyToLower, stringStartsWith, createConstant(prop))),
                            filterableField,
                            "{0} lowercased doesn't start with the parameter value");
                        AddFilterExpression(
                            $"{filterableField.Name}_l_ends_with",
                            prop => Expression.Call(propertyToLower, stringEndsWith, createConstant(prop)),
                            filterableField,
                            "{0} lowercased ends with the parameter value");
                        AddFilterExpression(
                            $"{filterableField.Name}_l_not_ends_with",
                            prop =>
                            Expression.Not(
                                Expression.Call(propertyToLower, stringEndsWith, createConstant(prop))),
                            filterableField,
                            "{0} lowercased doesn't end with the parameter value");
                        break;
                    }
                }
            }
        }