summaryrefslogtreecommitdiff
path: root/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm
diff options
context:
space:
mode:
Diffstat (limited to 'platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm')
-rw-r--r--platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm212
1 files changed, 153 insertions, 59 deletions
diff --git a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm
index 19c264aa40..58b37fae0e 100644
--- a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm
+++ b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm
@@ -7,95 +7,189 @@
- (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: {
- 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;
+ mbgl::style::EqualsFilter eqFilter;
+ eqFilter.key = self.mgl_keyPath.UTF8String;
+ eqFilter.value = self.mgl_constantValue;
+
+ // Convert == nil to NotHasFilter.
+ if (eqFilter.value.is<mbgl::NullValue>()) {
+ mbgl::style::NotHasFilter notHasFilter;
+ notHasFilter.key = eqFilter.key;
+ return notHasFilter;
}
+
+ return eqFilter;
}
case NSNotEqualToPredicateOperatorType: {
- 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;
+ mbgl::style::NotEqualsFilter neFilter;
+ neFilter.key = self.mgl_keyPath.UTF8String;
+ neFilter.value = self.mgl_constantValue;
+
+ // Convert != nil to HasFilter.
+ if (neFilter.value.is<mbgl::NullValue>()) {
+ mbgl::style::HasFilter hasFilter;
+ hasFilter.key = neFilter.key;
+ return hasFilter;
}
+
+ return neFilter;
}
case NSGreaterThanPredicateOperatorType: {
- auto filter = mbgl::style::GreaterThanFilter();
- filter.key = self.leftExpression.keyPath.UTF8String;
- filter.value = self.rightExpression.mgl_filterValue;
- return filter;
+ 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: {
- auto filter = mbgl::style::GreaterThanEqualsFilter();
- filter.key = self.leftExpression.keyPath.UTF8String;
- filter.value = self.rightExpression.mgl_filterValue;
- return filter;
+ 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: {
- auto filter = mbgl::style::LessThanFilter();
- filter.key = self.leftExpression.keyPath.UTF8String;
- filter.value = self.rightExpression.mgl_filterValue;
- return filter;
+ 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: {
- auto filter = mbgl::style::LessThanEqualsFilter();
- filter.key = self.leftExpression.keyPath.UTF8String;
- filter.value = self.rightExpression.mgl_filterValue;
- return filter;
+ 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: {
- auto filter = mbgl::style::InFilter();
- filter.key = self.leftExpression.keyPath.UTF8String;
- filter.values = self.rightExpression.mgl_filterValues;
- return filter;
+ 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."];
+ }
+ mbgl::style::InFilter inFilter;
+ inFilter.key = leftExpression.keyPath.UTF8String;
+ inFilter.values = rightExpression.mgl_aggregateMBGLValue;
+ return inFilter;
}
case NSContainsPredicateOperatorType: {
- auto filter = mbgl::style::InFilter();
- filter.key = [self.rightExpression.constantValue UTF8String];
- filter.values = self.leftExpression.mgl_filterValues;
- return filter;
+ 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."];
+ }
+ mbgl::style::InFilter inFilter;
+ inFilter.key = rightExpression.keyPath.UTF8String;
+ inFilter.values = leftExpression.mgl_aggregateMBGLValue;
+ return inFilter;
}
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;
+ 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:@"Unsupported operator type"
+ [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;
+ NSExpressionType leftType = leftExpression.expressionType;
+ NSExpressionType rightType = rightExpression.expressionType;
+ if (leftType == NSKeyPathExpressionType && rightType == NSConstantValueExpressionType) {
+ return leftExpression.keyPath;
+ } else if (leftType == NSConstantValueExpressionType && rightType == NSKeyPathExpressionType) {
+ return rightExpression.keyPath;
+ }
+
+ [NSException raise:NSInvalidArgumentException
+ format:@"Comparison predicate must compare an attribute (as a key path) to a constant or vice versa."];
+ return nil;
+}
+
+- (mbgl::Value)mgl_constantValue {
+ NSExpression *leftExpression = self.leftExpression;
+ NSExpression *rightExpression = self.rightExpression;
+ NSExpressionType leftType = leftExpression.expressionType;
+ NSExpressionType rightType = rightExpression.expressionType;
+ mbgl::Value value;
+ if (leftType == NSKeyPathExpressionType && rightType == NSConstantValueExpressionType) {
+ value = rightExpression.mgl_constantMBGLValue;
+ } else if (leftType == NSConstantValueExpressionType && rightType == NSKeyPathExpressionType) {
+ value = leftExpression.mgl_constantMBGLValue;
+ } else {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Comparison predicate must compare an attribute (as a key path) to a constant or vice versa."];
+ }
+ return value;
+}
+
@end