Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[ios, macos] Special-case $id, $type in predicates
Browse files Browse the repository at this point in the history
  • Loading branch information
1ec5 committed Feb 9, 2017
1 parent e4d6b1b commit 82de8b0
Show file tree
Hide file tree
Showing 8 changed files with 347 additions and 4 deletions.
95 changes: 93 additions & 2 deletions platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@

@implementation NSComparisonPredicate (MGLAdditions)

- (mbgl::style::Filter)mgl_filter
{
- (mbgl::style::Filter)mgl_filter {
NSExpression *leftExpression = self.leftExpression;
NSExpression *rightExpression = self.rightExpression;
NSExpressionType leftType = leftExpression.expressionType;
Expand All @@ -18,6 +17,20 @@ @implementation NSComparisonPredicate (MGLAdditions)
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") {
mbgl::style::IdentifierEqualsFilter idEqFilter;
idEqFilter.value = self.mgl_featureIdentifier;
return idEqFilter;
}

// Convert == nil to NotHasFilter.
if (eqFilter.value.is<mbgl::NullValue>()) {
Expand All @@ -32,6 +45,20 @@ @implementation NSComparisonPredicate (MGLAdditions)
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") {
mbgl::style::IdentifierNotEqualsFilter idNeFilter;
idNeFilter.value = self.mgl_featureIdentifier;
return idNeFilter;
}

// Convert != nil to HasFilter.
if (neFilter.value.is<mbgl::NullValue>()) {
Expand Down Expand Up @@ -103,6 +130,21 @@ @implementation NSComparisonPredicate (MGLAdditions)
[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;
Expand All @@ -117,6 +159,21 @@ @implementation NSComparisonPredicate (MGLAdditions)
[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;
Expand Down Expand Up @@ -192,4 +249,38 @@ - (NSString *)mgl_keyPath {
return value;
}

- (mbgl::FeatureType)mgl_featureType {
NSExpression *leftExpression = self.leftExpression;
NSExpression *rightExpression = self.rightExpression;
NSExpressionType leftType = leftExpression.expressionType;
NSExpressionType rightType = rightExpression.expressionType;
mbgl::FeatureType type;
if (leftType == NSKeyPathExpressionType && rightType == NSConstantValueExpressionType) {
type = rightExpression.mgl_featureType;
} else if (leftType == NSConstantValueExpressionType && rightType == NSKeyPathExpressionType) {
type = leftExpression.mgl_featureType;
} else {
[NSException raise:NSInvalidArgumentException
format:@"Comparison predicate must compare an attribute (as a key path) to a constant or vice versa."];
}
return type;
}

- (mbgl::FeatureIdentifier)mgl_featureIdentifier {
NSExpression *leftExpression = self.leftExpression;
NSExpression *rightExpression = self.rightExpression;
NSExpressionType leftType = leftExpression.expressionType;
NSExpressionType rightType = rightExpression.expressionType;
mbgl::FeatureIdentifier identifier;
if (leftType == NSKeyPathExpressionType && rightType == NSConstantValueExpressionType) {
identifier = rightExpression.mgl_featureIdentifier;
} else if (leftType == NSConstantValueExpressionType && rightType == NSKeyPathExpressionType) {
identifier = leftExpression.mgl_featureIdentifier;
} else {
[NSException raise:NSInvalidArgumentException
format:@"Comparison predicate must compare an attribute (as a key path) to a constant or vice versa."];
}
return identifier;
}

@end
3 changes: 3 additions & 0 deletions platform/darwin/src/NSExpression+MGLAdditions.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ NS_ASSUME_NONNULL_BEGIN

@property (nonatomic, readonly) mbgl::Value mgl_constantMBGLValue;
@property (nonatomic, readonly) std::vector<mbgl::Value> mgl_aggregateMBGLValue;
@property (nonatomic, readonly) mbgl::FeatureType mgl_featureType;
@property (nonatomic, readonly) std::vector<mbgl::FeatureType> mgl_aggregateFeatureType;
@property (nonatomic, readonly) mbgl::FeatureIdentifier mgl_featureIdentifier;
@property (nonatomic, readonly) std::vector<mbgl::FeatureIdentifier> mgl_aggregateFeatureIdentifier;

@end

Expand Down
61 changes: 61 additions & 0 deletions platform/darwin/src/NSExpression+MGLAdditions.mm
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,67 @@ @implementation NSExpression (MGLAdditions)
return {};
}

- (std::vector<mbgl::FeatureType>)mgl_aggregateFeatureType {
if ([self.constantValue isKindOfClass:[NSArray class]] || [self.constantValue isKindOfClass:[NSSet class]]) {
std::vector<mbgl::FeatureType> convertedValues;
for (id value in self.constantValue) {
NSExpression *expression = value;
if (![expression isKindOfClass:[NSExpression class]]) {
expression = [NSExpression expressionForConstantValue:expression];
}
convertedValues.push_back(expression.mgl_featureType);
}
return convertedValues;
}
[NSException raise:NSInvalidArgumentException
format:@"Constant value expression must contain an array or set."];
return {};
}

- (mbgl::FeatureType)mgl_featureType {
id value = self.constantValue;
if ([value isKindOfClass:NSString.class]) {
if ([value isEqualToString:@"Point"]) {
return mbgl::FeatureType::Point;
}
if ([value isEqualToString:@"LineString"]) {
return mbgl::FeatureType::LineString;
}
if ([value isEqualToString:@"Polygon"]) {
return mbgl::FeatureType::Polygon;
}
} else if ([value isKindOfClass:NSNumber.class]) {
switch ([value integerValue]) {
case 1:
return mbgl::FeatureType::Point;
case 2:
return mbgl::FeatureType::LineString;
case 3:
return mbgl::FeatureType::Polygon;
default:
break;
}
}
return mbgl::FeatureType::Unknown;
}

- (std::vector<mbgl::FeatureIdentifier>)mgl_aggregateFeatureIdentifier {
if ([self.constantValue isKindOfClass:[NSArray class]] || [self.constantValue isKindOfClass:[NSSet class]]) {
std::vector<mbgl::FeatureIdentifier> convertedValues;
for (id value in self.constantValue) {
NSExpression *expression = value;
if (![expression isKindOfClass:[NSExpression class]]) {
expression = [NSExpression expressionForConstantValue:expression];
}
convertedValues.push_back(expression.mgl_featureIdentifier);
}
return convertedValues;
}
[NSException raise:NSInvalidArgumentException
format:@"Constant value expression must contain an array or set."];
return {};
}

- (mbgl::FeatureIdentifier)mgl_featureIdentifier {
mbgl::Value mbglValue = self.mgl_constantMBGLValue;

Expand Down
63 changes: 61 additions & 2 deletions platform/darwin/src/NSPredicate+MGLAdditions.mm
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,41 @@
return predicates;
}

NSExpression *getValues(std::vector<mbgl::Value> values) {
template <typename MBGLType>
NSExpression *getValues(std::vector<MBGLType> values) {
NSMutableArray *array = [NSMutableArray arrayWithCapacity:values.size()];
for (auto value : values) {
id constantValue = mbgl::Value::visit(value, ValueEvaluator());
id constantValue = MBGLType::visit(value, ValueEvaluator());
[array addObject:[NSExpression expressionForConstantValue:constantValue]];
}
return [NSExpression expressionForAggregate:array];
}

NSString *getFeatureTypeString(mbgl::FeatureType type) {
switch (type) {
case mbgl::FeatureType::Point:
return @"Point";

case mbgl::FeatureType::LineString:
return @"LineString";

case mbgl::FeatureType::Polygon:
return @"Polygon";

default:
NSCAssert(NO, @"Unrecognized feature type %hhu", type);
return nil;
}
}

NSExpression *getFeatureTypeStrings(std::vector<mbgl::FeatureType> values) {
NSMutableArray *array = [NSMutableArray arrayWithCapacity:values.size()];
for (auto value : values) {
id typeString = getFeatureTypeString(value);
[array addObject:[NSExpression expressionForConstantValue:typeString]];
}
return [NSExpression expressionForAggregate:array];
}

NSPredicate *operator()(mbgl::style::NullFilter filter) {
return nil;
Expand Down Expand Up @@ -57,6 +84,38 @@
NSPredicate *operator()(mbgl::style::NotInFilter filter) {
return [NSPredicate predicateWithFormat:@"NOT %K IN %@", @(filter.key.c_str()), getValues(filter.values)];
}

NSPredicate *operator()(mbgl::style::TypeEqualsFilter filter) {
return [NSPredicate predicateWithFormat:@"%K == %@", @"$type", getFeatureTypeString(filter.value)];
}

NSPredicate *operator()(mbgl::style::TypeNotEqualsFilter filter) {
return [NSPredicate predicateWithFormat:@"%K != %@", @"$type", getFeatureTypeString(filter.value)];
}

NSPredicate *operator()(mbgl::style::TypeInFilter filter) {
return [NSPredicate predicateWithFormat:@"%K IN %@", @"$type", getFeatureTypeStrings(filter.values)];
}

NSPredicate *operator()(mbgl::style::TypeNotInFilter filter) {
return [NSPredicate predicateWithFormat:@"NOT %K IN %@", @"$type", getFeatureTypeStrings(filter.values)];
}

NSPredicate *operator()(mbgl::style::IdentifierEqualsFilter filter) {
return [NSPredicate predicateWithFormat:@"%K == %@", @"$id", mbgl::FeatureIdentifier::visit(filter.value, ValueEvaluator())];
}

NSPredicate *operator()(mbgl::style::IdentifierNotEqualsFilter filter) {
return [NSPredicate predicateWithFormat:@"%K != %@", @"$id", mbgl::FeatureIdentifier::visit(filter.value, ValueEvaluator())];
}

NSPredicate *operator()(mbgl::style::IdentifierInFilter filter) {
return [NSPredicate predicateWithFormat:@"%K IN %@", @"$id", getValues(filter.values)];
}

NSPredicate *operator()(mbgl::style::IdentifierNotInFilter filter) {
return [NSPredicate predicateWithFormat:@"NOT %K IN %@", @"$id", getValues(filter.values)];
}

NSPredicate *operator()(mbgl::style::AnyFilter filter) {
NSArray *subpredicates = getPredicates(filter.filters);
Expand Down
19 changes: 19 additions & 0 deletions platform/darwin/test/MGLExpressionTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -212,4 +212,23 @@ - (void)testExpressionConversionNull
XCTAssertTrue(convertedValue.is<mbgl::NullValue>());
}

#pragma mark - Feature type tests

- (void)testFeatureType {
XCTAssertEqual([NSExpression expressionWithFormat:@"'Point'"].mgl_featureType, mbgl::FeatureType::Point);
XCTAssertEqual([NSExpression expressionWithFormat:@"'LineString'"].mgl_featureType, mbgl::FeatureType::LineString);
XCTAssertEqual([NSExpression expressionWithFormat:@"'Polygon'"].mgl_featureType, mbgl::FeatureType::Polygon);
XCTAssertEqual([NSExpression expressionWithFormat:@"'Unknown'"].mgl_featureType, mbgl::FeatureType::Unknown);
XCTAssertEqual([NSExpression expressionWithFormat:@"''"].mgl_featureType, mbgl::FeatureType::Unknown);

XCTAssertEqual([NSExpression expressionWithFormat:@"1"].mgl_featureType, mbgl::FeatureType::Point);
XCTAssertEqual([NSExpression expressionWithFormat:@"2"].mgl_featureType, mbgl::FeatureType::LineString);
XCTAssertEqual([NSExpression expressionWithFormat:@"3"].mgl_featureType, mbgl::FeatureType::Polygon);
XCTAssertEqual([NSExpression expressionWithFormat:@"0"].mgl_featureType, mbgl::FeatureType::Unknown);
XCTAssertEqual([NSExpression expressionWithFormat:@"-1"].mgl_featureType, mbgl::FeatureType::Unknown);
XCTAssertEqual([NSExpression expressionWithFormat:@"4"].mgl_featureType, mbgl::FeatureType::Unknown);

XCTAssertEqual([NSExpression expressionWithFormat:@"nil"].mgl_featureType, mbgl::FeatureType::Unknown);
}

@end
Loading

0 comments on commit 82de8b0

Please sign in to comment.