diff options
author | Fabian Guerra Soto <fabian.guerra@mapbox.com> | 2018-04-16 16:51:59 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-16 16:51:59 -0400 |
commit | 62dd097328c1776cd62208baf6e46b1cd4154a52 (patch) | |
tree | f8b383ca94cade4af4a6ab5bb79113a8199fc1a7 /platform/darwin/src | |
parent | fe4348eec34a3a9c23f7a0af2ccfa4eff28416ea (diff) | |
download | qtlocation-mapboxgl-62dd097328c1776cd62208baf6e46b1cd4154a52.tar.gz |
[ios, macos] NSPredicate expression filters. (#11587)
* [ios, macos] Add NSAndPredicateType predicate expression filter.
* [ios, macos] Add type to NSPredicate expressions.
* [ios, macos] Add Expression filter support.
* [ios, macos] Update NSPredicate expression based tests.
* [ios, macos] Refactor ExpressionFilters.
* [ios, macos] Add symmetric test to ExpressionFilters.
* [ios, macos] Update NSPredicate test to ExpressionFilters.
* [ios, macos] Re-introduce Filter tests.
* [ios, macos] Remove typed NSComparisonPredicate's comparable values.
* [ios, macos] Update style layers predicate tests.
* [ios, macos] Remove unused predicate conversion code.
* [ios, macos] Update documentation exaple's test.
* [ios, macos] Update Predicate and Expressions guide..
* [ios, macos] Remove mgl_ prefix from variable expressions.
* [ios, macos] Update predicates and expressions documentation.
* [ios, macos] Update changelogs.
Diffstat (limited to 'platform/darwin/src')
-rw-r--r-- | platform/darwin/src/MGLVectorStyleLayer.h | 2 | ||||
-rw-r--r-- | platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm | 223 | ||||
-rw-r--r-- | platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm | 60 | ||||
-rw-r--r-- | platform/darwin/src/NSExpression+MGLAdditions.mm | 2 | ||||
-rw-r--r-- | platform/darwin/src/NSPredicate+MGLAdditions.mm | 29 |
5 files changed, 20 insertions, 296 deletions
diff --git a/platform/darwin/src/MGLVectorStyleLayer.h b/platform/darwin/src/MGLVectorStyleLayer.h index b3c8fc2433..d9431215a1 100644 --- a/platform/darwin/src/MGLVectorStyleLayer.h +++ b/platform/darwin/src/MGLVectorStyleLayer.h @@ -47,7 +47,7 @@ MGL_EXPORT ```swift let layer = MGLLineStyleLayer(identifier: "contour", source: terrain) layer.sourceLayerIdentifier = "contours" - layer.predicate = NSPredicate(format: "(index == 5 || index == 10) && ele >= 1500.0") + layer.predicate = NSPredicate(format: "(index == 5 || index == 10) && CAST(ele, 'NSNumber') >= 1500.0") mapView.style?.addLayer(layer) ``` */ diff --git a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm index c39e987d85..380215ff32 100644 --- a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm +++ b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm @@ -1,231 +1,12 @@ #import "NSComparisonPredicate+MGLAdditions.h" +#import "MGLStyleValue_Private.h" + #import "NSPredicate+MGLAdditions.h" #import "NSExpression+MGLPrivateAdditions.h" @implementation NSComparisonPredicate (MGLAdditions) -- (mbgl::style::Filter)mgl_filter { - NSExpression *leftExpression = self.leftExpression; - NSExpression *rightExpression = self.rightExpression; - NSExpressionType leftType = leftExpression.expressionType; - NSExpressionType rightType = rightExpression.expressionType; - BOOL isReversed = ((leftType == NSConstantValueExpressionType || leftType == NSAggregateExpressionType) - && rightType == NSKeyPathExpressionType); - switch (self.predicateOperatorType) { - case NSEqualToPredicateOperatorType: { - mbgl::style::EqualsFilter eqFilter; - eqFilter.key = self.mgl_keyPath.UTF8String; - eqFilter.value = self.mgl_constantValue; - - // Convert $type == to TypeEqualsFilter. - if (eqFilter.key == "$type") { - mbgl::style::TypeEqualsFilter typeEqFilter; - typeEqFilter.value = self.mgl_featureType; - return typeEqFilter; - } - - // Convert $id == to IdentifierEqualsFilter. - if (eqFilter.key == "$id") { - // Convert $id == nil to NotHasIdentifierFilter. - if (eqFilter.value.is<mbgl::NullValue>()) { - return mbgl::style::NotHasIdentifierFilter(); - } - - mbgl::style::IdentifierEqualsFilter idEqFilter; - idEqFilter.value = self.mgl_featureIdentifier; - return idEqFilter; - } - - // Convert == nil to NotHasFilter. - if (eqFilter.value.is<mbgl::NullValue>()) { - mbgl::style::NotHasFilter notHasFilter; - notHasFilter.key = eqFilter.key; - return notHasFilter; - } - - return eqFilter; - } - case NSNotEqualToPredicateOperatorType: { - mbgl::style::NotEqualsFilter neFilter; - neFilter.key = self.mgl_keyPath.UTF8String; - neFilter.value = self.mgl_constantValue; - - // Convert $type != to TypeNotEqualsFilter. - if (neFilter.key == "$type") { - mbgl::style::TypeNotEqualsFilter typeNeFilter; - typeNeFilter.value = self.mgl_featureType; - return typeNeFilter; - } - - // Convert $id != to IdentifierNotEqualsFilter. - if (neFilter.key == "$id") { - // Convert $id != nil to HasIdentifierFilter. - if (neFilter.value.is<mbgl::NullValue>()) { - return mbgl::style::HasIdentifierFilter(); - } - - mbgl::style::IdentifierNotEqualsFilter idNeFilter; - idNeFilter.value = self.mgl_featureIdentifier; - return idNeFilter; - } - - // Convert != nil to HasFilter. - if (neFilter.value.is<mbgl::NullValue>()) { - mbgl::style::HasFilter hasFilter; - hasFilter.key = neFilter.key; - return hasFilter; - } - - return neFilter; - } - case NSGreaterThanPredicateOperatorType: { - if (isReversed) { - mbgl::style::LessThanFilter ltFilter; - ltFilter.key = self.mgl_keyPath.UTF8String; - ltFilter.value = self.mgl_constantValue; - return ltFilter; - } else { - mbgl::style::GreaterThanFilter gtFilter; - gtFilter.key = self.mgl_keyPath.UTF8String; - gtFilter.value = self.mgl_constantValue; - return gtFilter; - } - } - case NSGreaterThanOrEqualToPredicateOperatorType: { - if (isReversed) { - mbgl::style::LessThanEqualsFilter lteFilter; - lteFilter.key = self.mgl_keyPath.UTF8String; - lteFilter.value = self.mgl_constantValue; - return lteFilter; - } else { - mbgl::style::GreaterThanEqualsFilter gteFilter; - gteFilter.key = self.mgl_keyPath.UTF8String; - gteFilter.value = self.mgl_constantValue; - return gteFilter; - } - } - case NSLessThanPredicateOperatorType: { - if (isReversed) { - mbgl::style::GreaterThanFilter gtFilter; - gtFilter.key = self.mgl_keyPath.UTF8String; - gtFilter.value = self.mgl_constantValue; - return gtFilter; - } else { - mbgl::style::LessThanFilter ltFilter; - ltFilter.key = self.mgl_keyPath.UTF8String; - ltFilter.value = self.mgl_constantValue; - return ltFilter; - } - } - case NSLessThanOrEqualToPredicateOperatorType: { - if (isReversed) { - mbgl::style::GreaterThanEqualsFilter gteFilter; - gteFilter.key = self.mgl_keyPath.UTF8String; - gteFilter.value = self.mgl_constantValue; - return gteFilter; - } else { - mbgl::style::LessThanEqualsFilter lteFilter; - lteFilter.key = self.mgl_keyPath.UTF8String; - lteFilter.value = self.mgl_constantValue; - return lteFilter; - } - } - case NSInPredicateOperatorType: { - if (isReversed) { - if (leftType == NSConstantValueExpressionType && [leftExpression.constantValue isKindOfClass:[NSString class]]) { - [NSException raise:NSInvalidArgumentException - format:@"CONTAINS not supported for string comparison."]; - } - [NSException raise:NSInvalidArgumentException - format:@"Predicate cannot compare values IN attribute."]; - } - - // Convert $type IN to TypeInFilter. - if ([leftExpression.keyPath isEqualToString:@"$type"]) { - mbgl::style::TypeInFilter typeInFilter; - typeInFilter.values = rightExpression.mgl_aggregateFeatureType; - return typeInFilter; - } - - // Convert $id IN to IdentifierInFilter. - if ([leftExpression.keyPath isEqualToString:@"$id"]) { - mbgl::style::IdentifierInFilter idInFilter; - idInFilter.values = rightExpression.mgl_aggregateFeatureIdentifier; - return idInFilter; - } - - mbgl::style::InFilter inFilter; - inFilter.key = leftExpression.keyPath.UTF8String; - inFilter.values = rightExpression.mgl_aggregateMBGLValue; - return inFilter; - } - case NSContainsPredicateOperatorType: { - if (!isReversed) { - if (rightType == NSConstantValueExpressionType && [rightExpression.constantValue isKindOfClass:[NSString class]]) { - [NSException raise:NSInvalidArgumentException - format:@"IN not supported for string comparison."]; - } - [NSException raise:NSInvalidArgumentException - format:@"Predicate cannot compare attribute CONTAINS values."]; - } - - // Convert CONTAINS $type to TypeInFilter. - if ([rightExpression.keyPath isEqualToString:@"$type"]) { - mbgl::style::TypeInFilter typeInFilter; - typeInFilter.values = leftExpression.mgl_aggregateFeatureType; - return typeInFilter; - } - - // Convert CONTAINS $id to IdentifierInFilter. - if ([rightExpression.keyPath isEqualToString:@"$id"]) { - mbgl::style::IdentifierInFilter idInFilter; - idInFilter.values = leftExpression.mgl_aggregateFeatureIdentifier; - return idInFilter; - } - - mbgl::style::InFilter inFilter; - inFilter.key = rightExpression.keyPath.UTF8String; - inFilter.values = leftExpression.mgl_aggregateMBGLValue; - return inFilter; - } - case NSBetweenPredicateOperatorType: { - if (isReversed) { - [NSException raise:NSInvalidArgumentException - format:@"Predicate cannot compare bounds BETWEEN attribute."]; - } - if (![rightExpression.constantValue isKindOfClass:[NSArray class]]) { - [NSException raise:NSInvalidArgumentException - format:@"Right side of BETWEEN predicate must be an array."]; // not NSSet - } - auto values = rightExpression.mgl_aggregateMBGLValue; - if (values.size() != 2) { - [NSException raise:NSInvalidArgumentException - format:@"Right side of BETWEEN predicate must have two items."]; - } - mbgl::style::AllFilter allFilter; - mbgl::style::GreaterThanEqualsFilter gteFilter; - gteFilter.key = leftExpression.keyPath.UTF8String; - gteFilter.value = values[0]; - allFilter.filters.push_back(gteFilter); - mbgl::style::LessThanEqualsFilter lteFilter; - lteFilter.key = leftExpression.keyPath.UTF8String; - lteFilter.value = values[1]; - allFilter.filters.push_back(lteFilter); - return allFilter; - } - case NSMatchesPredicateOperatorType: - case NSLikePredicateOperatorType: - case NSBeginsWithPredicateOperatorType: - case NSEndsWithPredicateOperatorType: - case NSCustomSelectorPredicateOperatorType: - [NSException raise:NSInvalidArgumentException - format:@"NSPredicateOperatorType:%lu is not supported.", (unsigned long)self.predicateOperatorType]; - } - - return {}; -} - - (NSString *)mgl_keyPath { NSExpression *leftExpression = self.leftExpression; NSExpression *rightExpression = self.rightExpression; diff --git a/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm b/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm index 19568b8033..5a98b763ea 100644 --- a/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm +++ b/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm @@ -1,8 +1,12 @@ #import "NSCompoundPredicate+MGLAdditions.h" +#import "MGLStyleValue_Private.h" + #import "NSPredicate+MGLAdditions.h" #import "NSExpression+MGLPrivateAdditions.h" +#include <mbgl/style/conversion/property_value.hpp> + @implementation NSCompoundPredicate (MGLAdditions) - (std::vector<mbgl::style::Filter>)mgl_subfilters @@ -14,62 +18,6 @@ return filters; } -- (mbgl::style::Filter)mgl_filter -{ - switch (self.compoundPredicateType) { - case NSNotPredicateType: { - NSAssert(self.subpredicates.count <= 1, @"NOT predicate cannot have multiple subpredicates."); - NSPredicate *subpredicate = self.subpredicates.firstObject; - mbgl::style::Filter subfilter = subpredicate.mgl_filter; - - // Convert NOT(!= nil) to NotHasFilter. - if (subfilter.is<mbgl::style::HasFilter>()) { - auto hasFilter = subfilter.get<mbgl::style::HasFilter>(); - return mbgl::style::NotHasFilter { .key = hasFilter.key }; - } - - // Convert NOT(== nil) to HasFilter. - if (subfilter.is<mbgl::style::NotHasFilter>()) { - auto hasFilter = subfilter.get<mbgl::style::NotHasFilter>(); - return mbgl::style::HasFilter { .key = hasFilter.key }; - } - - // Convert NOT(IN) or NOT(CONTAINS) to NotInFilter. - if (subfilter.is<mbgl::style::InFilter>()) { - auto inFilter = subfilter.get<mbgl::style::InFilter>(); - mbgl::style::NotInFilter notInFilter; - notInFilter.key = inFilter.key; - notInFilter.values = inFilter.values; - return notInFilter; - } - - // Convert NOT(), NOT(AND), NOT(NOT), NOT(==), etc. into NoneFilter. - mbgl::style::NoneFilter noneFilter; - if (subfilter.is<mbgl::style::AnyFilter>()) { - // Flatten NOT(OR). - noneFilter.filters = subfilter.get<mbgl::style::AnyFilter>().filters; - } else if (subpredicate) { - noneFilter.filters = { subfilter }; - } - return noneFilter; - } - case NSAndPredicateType: { - mbgl::style::AllFilter filter; - filter.filters = self.mgl_subfilters; - return filter; - } - case NSOrPredicateType: { - mbgl::style::AnyFilter filter; - filter.filters = self.mgl_subfilters; - return filter; - } - } - - [NSException raise:@"Compound predicate type not handled" - format:@""]; - return {}; -} - @end @implementation NSCompoundPredicate (MGLExpressionAdditions) diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm index 3c42b80a13..c175868dae 100644 --- a/platform/darwin/src/NSExpression+MGLAdditions.mm +++ b/platform/darwin/src/NSExpression+MGLAdditions.mm @@ -562,7 +562,7 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) { argumentObjects = [argumentObjects subarrayWithRange:NSMakeRange(1, argumentObjects.count - 1)]; NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(argumentObjects); return [NSExpression expressionForFunction:operand selectorName:@"mgl_numberWithFallbackValues:" arguments:subexpressions]; - } else if ([op isEqualToString:@"to-string"]) { + } else if ([op isEqualToString:@"to-string"] || [op isEqualToString:@"string"]) { NSExpression *operand = [NSExpression expressionWithMGLJSONObject:argumentObjects.firstObject]; return [NSExpression expressionWithFormat:@"CAST(%@, 'NSString')", operand]; } else if ([op isEqualToString:@"get"]) { diff --git a/platform/darwin/src/NSPredicate+MGLAdditions.mm b/platform/darwin/src/NSPredicate+MGLAdditions.mm index ed48c794aa..bbd324bb63 100644 --- a/platform/darwin/src/NSPredicate+MGLAdditions.mm +++ b/platform/darwin/src/NSPredicate+MGLAdditions.mm @@ -3,6 +3,8 @@ #import "MGLValueEvaluator.h" #import "MGLStyleValue_Private.h" +#include <mbgl/style/conversion/filter.hpp> + class FilterEvaluator { public: @@ -206,25 +208,18 @@ public: - (mbgl::style::Filter)mgl_filter { - if ([self isEqual:[NSPredicate predicateWithValue:YES]]) - { - return mbgl::style::AllFilter(); - } - - if ([self isEqual:[NSPredicate predicateWithValue:NO]]) - { - return mbgl::style::AnyFilter(); - } - - if ([self.predicateFormat hasPrefix:@"BLOCKPREDICATE("]) - { + mbgl::style::conversion::Error valueError; + NSArray *jsonObject = self.mgl_jsonExpressionObject; + auto value = mbgl::style::conversion::convert<mbgl::style::Filter>(mbgl::style::conversion::makeConvertible(jsonObject), valueError); + + if (!value) { [NSException raise:NSInvalidArgumentException - format:@"Block-based predicates are not supported."]; + format:@"Invalid filter value: %@", @(valueError.message.c_str())]; + return {}; } - - [NSException raise:NSInvalidArgumentException - format:@"Unrecognized predicate type."]; - return {}; + mbgl::style::Filter filter = std::move(*value); + + return filter; } + (instancetype)mgl_predicateWithFilter:(mbgl::style::Filter)filter |