private NSCompoundPredicate FindMatches(string searchString)
        {
            /*
             * Each searchString creates an OR predicate for: name, yearIntroduced, introPrice.
             * Example if searchItems contains "Gladiolus 51.99 2001":
             * - name CONTAINS[c] "gladiolus"
             * - name CONTAINS[c] "gladiolus", yearIntroduced ==[c] 2001, introPrice ==[c] 51.99
             * - name CONTAINS[c] "ginger", yearIntroduced ==[c] 2007, introPrice ==[c] 49.98
             */
            var searchItemsPredicate = new List <NSPredicate>();

            /*
             * Below we use NSExpression represent expressions in our predicates.
             * NSPredicate is made up of smaller, atomic parts:
             * two NSExpressions (a left-hand value and a right-hand value).
             */

            // Name field matching.
            var titleExpression        = NSExpression.FromKeyPath(ExpressionKeys.Title);
            var searchStringExpression = NSExpression.FromConstant(new NSString(searchString));

            var titleSearchComparisonPredicate = new NSComparisonPredicate(titleExpression,
                                                                           searchStringExpression,
                                                                           NSComparisonPredicateModifier.Direct,
                                                                           NSPredicateOperatorType.Contains,
                                                                           NSComparisonPredicateOptions.CaseInsensitive | NSComparisonPredicateOptions.DiacriticInsensitive);

            searchItemsPredicate.Add(titleSearchComparisonPredicate);

            var numberFormatter = new NSNumberFormatter
            {
                NumberStyle       = NSNumberFormatterStyle.None,
                FormatterBehavior = NSNumberFormatterBehavior.Default
            };

            // The `searchString` may fail to convert to a number.
            var targetNumber = numberFormatter.NumberFromString(searchString);

            if (targetNumber != null)
            {
                // Use `targetNumberExpression` in both the following predicates.
                var targetNumberExpression = NSExpression.FromConstant(targetNumber);

                // The `yearIntroduced` field matching.
                var yearIntroducedExpression = NSExpression.FromKeyPath(ExpressionKeys.YearIntroduced);
                var yearIntroducedPredicate  = new NSComparisonPredicate(yearIntroducedExpression,
                                                                         targetNumberExpression,
                                                                         NSComparisonPredicateModifier.Direct,
                                                                         NSPredicateOperatorType.EqualTo,
                                                                         NSComparisonPredicateOptions.CaseInsensitive | NSComparisonPredicateOptions.DiacriticInsensitive);

                searchItemsPredicate.Add(yearIntroducedPredicate);

                // The `price` field matching.
                var priceExpression = NSExpression.FromKeyPath(ExpressionKeys.IntroPrice);
                var finalPredicate  = new NSComparisonPredicate(priceExpression,
                                                                targetNumberExpression,
                                                                NSComparisonPredicateModifier.Direct,
                                                                NSPredicateOperatorType.EqualTo,
                                                                NSComparisonPredicateOptions.CaseInsensitive | NSComparisonPredicateOptions.DiacriticInsensitive);

                searchItemsPredicate.Add(finalPredicate);
            }

            return(NSCompoundPredicate.CreateOrPredicate(searchItemsPredicate.ToArray()));
        }
Exemple #2
0
        static NSPredicate ToPredicate(NSObject @object)
        {
            if (@object == NSNumber.FromBoolean(true))
            {
                return(NSPredicate.FromValue(true));
            }

            if (@object == NSNumber.FromBoolean(false))
            {
                return(NSPredicate.FromValue(false));
            }

            if (@object is NSArray == false)
            {
                return(null);
            }

            var array   = (NSArray)@object;
            var objects = SubArray(array);
            var op      = objects[0].ToString();

            if (MGLPredicateOperatorTypesByJSONOperator.TryGetValue(op, out var operatorType))
            {
                NSComparisonPredicateOptions options = 0;

                if (objects.Count > 3)
                {
                    var collatorExpression = SubArray((NSArray)objects[3]);

                    if (collatorExpression.Count != 2)
                    {
                        return(null);
                    }

                    var collator = (NSDictionary)collatorExpression[1];

                    if (false == collator.ContainsKey((NSString)"locale"))
                    {
                        if (collator.ValueForKey((NSString)"case-sensitive") == NSNumber.FromBoolean(false))
                        {
                            options |= NSComparisonPredicateOptions.CaseInsensitive;
                        }

                        if (collator.ValueForKey((NSString)"diacritic-sensitive") == NSNumber.FromBoolean(false))
                        {
                            options |= NSComparisonPredicateOptions.DiacriticInsensitive;
                        }
                    }
                }

                var subexpressions = ToSubexpressions(SubArray(objects, 1));

                return(new NSComparisonPredicate(
                           subexpressions[0],
                           subexpressions[1],
                           NSComparisonPredicateModifier.Direct,
                           operatorType,
                           options
                           ));
            }

            switch (op)
            {
            case "!": {
                var subpredicates = ToSubpredicates(SubArray(objects, 1));
                if (subpredicates.Count > 1)
                {
                    var predicate = NSCompoundPredicate.CreateOrPredicate(subpredicates.ToArray());

                    return(NSCompoundPredicate.CreateNotPredicate(predicate));
                }

                return(NSPredicate.FromValue(true));
            }

            case "all": {
                var subpredicates = ToSubpredicates(SubArray(objects, 1));

                if (subpredicates.Count == 2)
                {
                    if (subpredicates[0] is NSComparisonPredicate leftCondition &&
                        subpredicates[1] is NSComparisonPredicate rightCondition
                        )
                    {
                        NSExpression[] limits = null;
                        NSExpression   leftConditionExpression = null;

                        if (leftCondition.PredicateOperatorType == NSPredicateOperatorType.GreaterThanOrEqualTo &&
                            rightCondition.PredicateOperatorType == NSPredicateOperatorType.LessThanOrEqualTo
                            )
                        {
                            limits = new NSExpression[]
                            {
                                leftCondition.RightExpression,
                                rightCondition.RightExpression
                            };
                            leftConditionExpression = leftCondition.LeftExpression;
                        }
                        else if (leftCondition.PredicateOperatorType == NSPredicateOperatorType.LessThanOrEqualTo &&
                                 rightCondition.PredicateOperatorType ==
                                 NSPredicateOperatorType.LessThanOrEqualTo
                                 )
                        {
                            limits = new NSExpression[]
                            {
                                leftCondition.LeftExpression,
                                rightCondition.RightExpression
                            };
                            leftConditionExpression = leftCondition.RightExpression;
                        }
                        else if (leftCondition.PredicateOperatorType == NSPredicateOperatorType.LessThanOrEqualTo &&
                                 rightCondition.PredicateOperatorType ==
                                 NSPredicateOperatorType.GreaterThanOrEqualTo
                                 )
                        {
                            limits = new NSExpression[]
                            {
                                leftCondition.LeftExpression,
                                rightCondition.LeftExpression
                            };
                            leftConditionExpression = leftCondition.RightExpression;
                        }
                        else if (leftCondition.PredicateOperatorType == NSPredicateOperatorType.GreaterThanOrEqualTo &&
                                 rightCondition.PredicateOperatorType ==
                                 NSPredicateOperatorType.GreaterThanOrEqualTo
                                 )
                        {
                            limits = new NSExpression[]
                            {
                                leftCondition.RightExpression,
                                rightCondition.LeftExpression
                            };
                            leftConditionExpression = leftCondition.LeftExpression;
                        }

                        if (limits != null && leftConditionExpression != null)
                        {
                            return(NSPredicate.FromFormat("%@ BETWEEN %@", leftConditionExpression,
                                                          NSExpression.FromAggregate(limits)));
                        }
                    }
                }

                return(new NSCompoundPredicate(NSCompoundPredicateType.And, subpredicates.ToArray()));
            }

            case "any": {
                var subpredicates = ToSubpredicates(SubArray(objects, 1));

                return(new NSCompoundPredicate(NSCompoundPredicateType.Or, subpredicates.ToArray()));
            }

            default: {
                var expression = ToExpression(array);

                return(new NSComparisonPredicate(
                           expression,
                           NSExpression.FromConstant(NSNumber.FromBoolean(true)),
                           NSComparisonPredicateModifier.Direct,
                           NSPredicateOperatorType.EqualTo,
                           0
                           ));
            }
            }
        }