diff options
author | Jesse Bounds <jesse@rebounds.net> | 2016-09-21 09:12:59 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-09-21 09:12:59 -0700 |
commit | 1165a408fbee37a0892b07b5c35e1a36d7aa0063 (patch) | |
tree | 5ee4aa50d79ba712cf744af44255cb3490c92513 | |
parent | 6fe621bbef43e6b73a53ca25a9df3d349cd84929 (diff) | |
download | qtlocation-mapboxgl-1165a408fbee37a0892b07b5c35e1a36d7aa0063.tar.gz |
[ios, macos] Add more predicate operator to mbgl filter translations
Adds several new translations to prevent data loss.
-rw-r--r-- | platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm | 54 | ||||
-rw-r--r-- | platform/darwin/src/NSPredicate+MGLAdditions.mm | 22 | ||||
-rw-r--r-- | platform/darwin/test/MGLFilterTests.mm | 57 |
3 files changed, 113 insertions, 20 deletions
diff --git a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm index ced6a1ac47..19c264aa40 100644 --- a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm +++ b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm @@ -9,16 +9,34 @@ { switch (self.predicateOperatorType) { case NSEqualToPredicateOperatorType: { - auto filter = mbgl::style::EqualsFilter(); - filter.key = self.leftExpression.keyPath.UTF8String; - filter.value = self.rightExpression.mgl_filterValue; - return filter; + if (self.rightExpression.constantValue) + { + auto filter = mbgl::style::EqualsFilter(); + filter.key = self.leftExpression.keyPath.UTF8String; + filter.value = self.rightExpression.mgl_filterValue; + return filter; + } + else + { + auto filter = mbgl::style::NotHasFilter(); + filter.key = self.leftExpression.keyPath.UTF8String; + return filter; + } } case NSNotEqualToPredicateOperatorType: { - auto filter = mbgl::style::NotEqualsFilter(); - filter.key = self.leftExpression.keyPath.UTF8String; - filter.value = self.rightExpression.mgl_filterValue; - return filter; + if (self.rightExpression.constantValue) + { + auto filter = mbgl::style::NotEqualsFilter(); + filter.key = self.leftExpression.keyPath.UTF8String; + filter.value = self.rightExpression.mgl_filterValue; + return filter; + } + else + { + auto filter = mbgl::style::HasFilter(); + filter.key = self.leftExpression.keyPath.UTF8String; + return filter; + } } case NSGreaterThanPredicateOperatorType: { auto filter = mbgl::style::GreaterThanFilter(); @@ -50,13 +68,29 @@ filter.values = self.rightExpression.mgl_filterValues; return filter; } + case NSContainsPredicateOperatorType: { + auto filter = mbgl::style::InFilter(); + filter.key = [self.rightExpression.constantValue UTF8String]; + filter.values = self.leftExpression.mgl_filterValues; + return filter; + } + case NSBetweenPredicateOperatorType: { + auto filter = mbgl::style::AllFilter(); + auto gteFilter = mbgl::style::GreaterThanEqualsFilter(); + gteFilter.key = self.leftExpression.keyPath.UTF8String; + gteFilter.value = self.rightExpression.mgl_filterValues[0]; + filter.filters.push_back(gteFilter); + auto lteFilter = mbgl::style::LessThanEqualsFilter(); + lteFilter.key = self.leftExpression.keyPath.UTF8String; + lteFilter.value = self.rightExpression.mgl_filterValues[1]; + filter.filters.push_back(lteFilter); + return filter; + } case NSMatchesPredicateOperatorType: case NSLikePredicateOperatorType: case NSBeginsWithPredicateOperatorType: case NSEndsWithPredicateOperatorType: case NSCustomSelectorPredicateOperatorType: - case NSContainsPredicateOperatorType: - case NSBetweenPredicateOperatorType: [NSException raise:@"Unsupported operator type" format:@"NSPredicateOperatorType:%lu is not supported.", (unsigned long)self.predicateOperatorType]; } diff --git a/platform/darwin/src/NSPredicate+MGLAdditions.mm b/platform/darwin/src/NSPredicate+MGLAdditions.mm index 9c3f9c888c..64ad277e4d 100644 --- a/platform/darwin/src/NSPredicate+MGLAdditions.mm +++ b/platform/darwin/src/NSPredicate+MGLAdditions.mm @@ -76,15 +76,11 @@ public: } NSPredicate* operator()(mbgl::style::HasFilter filter) { - [NSException raise:@"Unsupported filter type" - format:@"Cannot convert mbgl::style::HasFilter to NSPredicate"]; - return nil; + return [NSPredicate predicateWithFormat:@"%K != nil", @(filter.key.c_str())]; } NSPredicate* operator()(mbgl::style::NotHasFilter filter) { - [NSException raise:@"Unsupported filter type" - format:@"Cannot convert mbgl::style::NotHasFilter to NSPredicate"]; - return nil; + return [NSPredicate predicateWithFormat:@"%K == nil", @(filter.key.c_str())]; } }; @@ -93,8 +89,20 @@ public: - (mbgl::style::Filter)mgl_filter { + if ([self isEqual:[NSPredicate predicateWithValue:YES]]) + { + auto filter = mbgl::style::AllFilter(); + return filter; + } + + if ([self isEqual:[NSPredicate predicateWithValue:NO]]) + { + auto filter = mbgl::style::AnyFilter(); + return filter; + } + [NSException raise:@"Not supported" - format:@"NSPredicate doesn't implement ’-mgl_filter’. Try with NSComparisonPredicate or NSCompoundPredicate instead."]; + format:@"Try with NSComparisonPredicate or NSCompoundPredicate instead."]; return {}; } diff --git a/platform/darwin/test/MGLFilterTests.mm b/platform/darwin/test/MGLFilterTests.mm index 513963ab7e..6fbe5f0157 100644 --- a/platform/darwin/test/MGLFilterTests.mm +++ b/platform/darwin/test/MGLFilterTests.mm @@ -3,6 +3,7 @@ #import "NSPredicate+MGLAdditions.h" #import "MGLValueEvaluator.h" + @interface MGLFilterTests : MGLStyleLayerTests { MGLGeoJSONSource *source; MGLLineStyleLayer *layer; @@ -42,8 +43,11 @@ NSPredicate *typePredicate = [NSPredicate predicateWithFormat:@"%K == %@", @"$type", @"Feature"]; NSPredicate *idPredicate = [NSPredicate predicateWithFormat:@"%K == %@", @"$id", @"1234123"]; NSPredicate *specialCharsPredicate = [NSPredicate predicateWithFormat:@"%K == %@", @"ty-’pè", @"sŒm-ethįng"]; - NSPredicate *booleanPredicate = [NSPredicate predicateWithFormat:@"%K != %@", @"cluster", [NSNumber numberWithBool:YES]]; - return @[equalPredicate, + NSPredicate *booleanPredicate = [NSPredicate predicateWithFormat:@"cluster != YES"]; + NSPredicate *nilEqualsPredicate = [NSPredicate predicateWithFormat:@"type == %@", nil]; + NSPredicate *nilNotEqualsPredicate = [NSPredicate predicateWithFormat:@"type != %@", nil]; + return @[ + equalPredicate, notEqualPredicate, greaterThanPredicate, greaterThanOrEqualToPredicate, @@ -55,7 +59,10 @@ typePredicate, idPredicate, specialCharsPredicate, - booleanPredicate]; + booleanPredicate, + nilEqualsPredicate, + nilNotEqualsPredicate + ]; } - (void)testAllPredicates @@ -67,6 +74,50 @@ [self.mapView.style addLayer:layer]; } +- (void)testContainsPredicate +{ + // core does not have a "contains" filter but we can achieve the equivalent by creating an `mbgl::style::InFilter` + // and searching the value for the key + NSPredicate *expectedPredicate = [NSPredicate predicateWithFormat:@"park IN %@", @[@"park", @"neighbourhood"]]; + NSPredicate *containsPredicate = [NSPredicate predicateWithFormat:@"%@ CONTAINS %@", @[@"park", @"neighbourhood"], @"park"]; + + layer.predicate = containsPredicate; + XCTAssertEqualObjects(layer.predicate, expectedPredicate); + [self.mapView.style addLayer:layer]; +} + +- (void)testBetweenPredicate +{ + // core does not have a "between" filter but we can achieve the equivalent by creating a set of greater than or equal / less than or equal + // filters for the lower and upper bounds (inclusive) + NSPredicate *expectedPredicate = [NSCompoundPredicate predicateWithFormat:@"%K >= 2 AND %K <= 3", @"stroke-width", @"stroke-width"]; + NSPredicate *betweenPredicate = [NSPredicate predicateWithFormat:@"%K BETWEEN %@", @"stroke-width", @[@2.0, @3.0]]; + + layer.predicate = betweenPredicate; + XCTAssertEqualObjects(layer.predicate, expectedPredicate); + [self.mapView.style addLayer:layer]; +} + +- (void)testTruePredicate +{ + // This comes out of the class cluster as an NSTruePredicate and it is equal to `[NSPredicate predicateWithValue:YES]` + NSPredicate *truePredicate = [NSPredicate predicateWithFormat:@"TRUEPREDICATE"]; + + layer.predicate = truePredicate; + XCTAssertEqualObjects(layer.predicate.description, truePredicate.description); + [self.mapView.style addLayer:layer]; +} + +- (void)testFalsePredicate +{ + // This comes out of the class cluster as an NSFalsePredicate and it is equal to `[NSPredicate predicateWithValue:NO]` + NSPredicate *falsePredicate = [NSPredicate predicateWithFormat:@"FALSEPREDICATE"]; + + layer.predicate = falsePredicate; + XCTAssertEqualObjects(layer.predicate.description, falsePredicate.description); + [self.mapView.style addLayer:layer]; +} + - (void)testIntermittentEncoding { NSPredicate *specialCharsPredicate = [NSPredicate predicateWithFormat:@"%K == %@", @"ty-’pè", @"sŒm-ethįng"]; |