mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 04:57:03 +00:00
CPExpression +expressionForConditional:trueExpression:falseExpression:
Conditional Expression : an expression using different expressions for evaluation, depending of a predicate result. Support for predicate parsing: ```TERNARY(predicate, trueExpression, falseExpression)``` With init, equal, evaluation, parsing tests.
This commit is contained in:
@@ -29,3 +29,4 @@
|
||||
@import "_CPSetExpression.j"
|
||||
@import "_CPSubqueryExpression.j"
|
||||
@import "_CPBlockExpression.j"
|
||||
@import "_CPConditionalExpression.j"
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* _CPConditionalExpression.j
|
||||
*
|
||||
* Created by cacaodev.
|
||||
* Copyright 2015.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
@import "_CPPredicate.j"
|
||||
@import "_CPExpression.j"
|
||||
|
||||
@implementation _CPConditionalExpression : CPExpression
|
||||
{
|
||||
CPPredicate _predicate;
|
||||
CPExpression _trueExpression;
|
||||
CPExpression _falseExpression;
|
||||
}
|
||||
|
||||
- (id)initWithPredicate:(CPPredicate)aPredicate trueExpression:(CPExpression)trueExpression falseExpression:(CPExpression)falseExpression
|
||||
{
|
||||
self = [super initWithExpressionType:CPConditionalExpressionType];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_predicate = aPredicate;
|
||||
_trueExpression = trueExpression;
|
||||
_falseExpression = falseExpression;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
if (self === object)
|
||||
return YES;
|
||||
|
||||
if (object === nil || object.isa !== self.isa || ![[object predicate] isEqual:_predicate] || ![[object trueExpression] isEqual:_trueExpression] || ![[object falseExpression] isEqual:_falseExpression])
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (CPPredicate)predicate
|
||||
{
|
||||
return _predicate;
|
||||
}
|
||||
|
||||
- (CPExpression)trueExpression
|
||||
{
|
||||
return _trueExpression;
|
||||
}
|
||||
|
||||
- (CPExpression)falseExpression
|
||||
{
|
||||
return _falseExpression;
|
||||
}
|
||||
|
||||
- (id)expressionValueWithObject:(id)object context:(CPDictionary)context
|
||||
{
|
||||
var eval = [_predicate evaluateWithObject:object substitutionVariables:context];
|
||||
var exp = eval ? _trueExpression : _falseExpression;
|
||||
|
||||
return [exp expressionValueWithObject:object context:context];
|
||||
}
|
||||
|
||||
- (CPString)description
|
||||
{
|
||||
return [CPString stringWithFormat:@"TERNARY(%@,%@,%@)", [_predicate predicateFormat], [_trueExpression description], [_falseExpression description]];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -69,6 +69,10 @@ CPMinusSetExpressionType = 9;
|
||||
An expression that returns the result of evaluating a block.
|
||||
*/
|
||||
CPBlockExpressionType = 10;
|
||||
/*!
|
||||
An expression that returns an expression that depends on the evaluation of a predicate.
|
||||
*/
|
||||
CPConditionalExpressionType = 11;
|
||||
|
||||
/*!
|
||||
@ingroup foundation
|
||||
@@ -284,6 +288,11 @@ A dictionary that the expression can use to store temporary state for one predic
|
||||
return [[_CPBlockExpression alloc] initWithBlock:aBlock arguments:args];
|
||||
}
|
||||
|
||||
+ (CPExpression)expressionForConditional:(CPPredicate)aPredicate trueExpression:(CPExpression)trueExpression falseExpression:(CPExpression)falseExpression
|
||||
{
|
||||
return [[_CPConditionalExpression alloc] initWithPredicate:aPredicate trueExpression:trueExpression falseExpression:falseExpression];
|
||||
}
|
||||
|
||||
// Getting Information About an Expression
|
||||
/*!
|
||||
Returns the expression type for the receiver.
|
||||
|
||||
@@ -751,11 +751,35 @@
|
||||
subpredicate = [self parsePredicate];
|
||||
|
||||
if (![self scanString:@")" intoString:NULL])
|
||||
CPRaiseParseError(self, @"expression");
|
||||
CPRaiseParseError(self, @"predicate");
|
||||
|
||||
return [[_CPSubqueryExpression alloc] initWithExpression:collection usingIteratorExpression:variableExpression predicate:subpredicate];
|
||||
}
|
||||
|
||||
if ([self scanString:@"TERNARY" intoString:NULL])
|
||||
{
|
||||
if (![self scanString:@"(" intoString:NULL])
|
||||
CPRaiseParseError(self, @"expression");
|
||||
|
||||
var predicate,
|
||||
trueExpression,
|
||||
falseExpression;
|
||||
|
||||
predicate = [self parsePredicate];
|
||||
if (![self scanString:@"," intoString:NULL])
|
||||
CPRaiseParseError(self, @"predicate");
|
||||
|
||||
trueExpression = [self parseExpression];
|
||||
if (![self scanString:@"," intoString:NULL])
|
||||
CPRaiseParseError(self, @"expression");
|
||||
|
||||
falseExpression = [self parseExpression];
|
||||
if (![self scanString:@")" intoString:NULL])
|
||||
CPRaiseParseError(self, @"expression");
|
||||
|
||||
return [CPExpression expressionForConditional:predicate trueExpression:trueExpression falseExpression:falseExpression];
|
||||
}
|
||||
|
||||
if ([self scanString:@"FUNCTION" intoString:NULL])
|
||||
{
|
||||
if (![self scanString:@"(" intoString:NULL])
|
||||
|
||||
@@ -86,6 +86,10 @@
|
||||
} arguments:nil];
|
||||
|
||||
[self assertNotNull:expression_block message:"Block Expression should not be nil"];
|
||||
|
||||
var expression_conditional = [CPExpression expressionForConditional:[CPPredicate predicateWithValue:YES] trueExpression:expression_minusset falseExpression:expression_block];
|
||||
|
||||
[self assertNotNull:expression_conditional message:"Conditional Expression should not be nil"];
|
||||
}
|
||||
|
||||
- (void)testSetExpressionEvaluation
|
||||
@@ -167,6 +171,14 @@
|
||||
[self assertTrue:([eval isEqual:"OBJA-B"]) message:"'" + [expression description] + "' result is "+ eval + "but should be " + "OBJA-B"];
|
||||
}
|
||||
|
||||
- (void)testConditionalExpressionEvaluation
|
||||
{
|
||||
var expression = [CPExpression expressionForConditional:[CPPredicate predicateWithFormat:"SELF = $variable"] trueExpression:[CPExpression expressionForConstantValue:"TRUE_EXP"] falseExpression:[CPExpression expressionForConstantValue:"FALSE_EXP"]];
|
||||
|
||||
var eval = [expression expressionValueWithObject:"OBJ" context:@{"variable":"OBJ"}];
|
||||
[self assertTrue:([eval isEqual:"TRUE_EXP"]) message:"'" + [expression description] + "' result is "+ eval + "but should be " + "TRUE_EXP"];
|
||||
}
|
||||
|
||||
- (void)testOptions
|
||||
{
|
||||
var pred = [[CPComparisonPredicate alloc] initWithLeftExpression:[CPExpression expressionForConstantValue:@"àa"] rightExpression:[CPExpression expressionForConstantValue:@"aà"] modifier:CPDirectPredicateModifier type:CPLikePredicateOperatorType options:3];
|
||||
@@ -401,6 +413,9 @@
|
||||
predicate = [CPPredicate predicateWithFormat:@"a UNION {'b'} = {'a','b'}"];
|
||||
var left = [[predicate leftExpression] expressionValueWithObject:object context:nil];
|
||||
[self assertTrue:[left isEqualToSet:result] message:"Expression eval " + left + " should be " + result];
|
||||
|
||||
predicate = [CPPredicate predicateWithFormat:@"TERNARY(Record1.Children[SIZE] = 1, 'Single', Record1.Name) = 'John'"];
|
||||
[self assertTrue:[predicate evaluateWithObject:dict] message:"Predicate " + predicate + " should evaluate to TRUE"];
|
||||
}
|
||||
|
||||
- (void)testExpressionAndPredicateIsEqual
|
||||
@@ -459,6 +474,10 @@
|
||||
pred1 = [CPPredicate predicateWithFormat:@"a = 'a' AND b = 'b'"];
|
||||
pred2 = [CPPredicate predicateWithFormat:@"a = 'a' AND b = 'b'"];
|
||||
[self assert:pred1 equals:pred2];
|
||||
|
||||
pred1 = [CPPredicate predicateWithFormat:@"TERNARY(Record1.Children[FIRST] BEGINSWITH Record1.Name, 'SAME', 'DIFFERENT') = 'DIFFERENT'"];
|
||||
pred2 = [CPPredicate predicateWithFormat:@"TERNARY(Record1.Children[FIRST] BEGINSWITH Record1.Name, 'SAME', 'DIFFERENT') = 'DIFFERENT'"];
|
||||
[self assert:pred1 equals:pred2];
|
||||
}
|
||||
|
||||
- (void)testExpressionAndPredicateIsNotEqualToNil
|
||||
@@ -510,6 +529,10 @@
|
||||
|
||||
[self assert:pred1 notEqual:nil];
|
||||
|
||||
pred1 = [CPPredicate predicateWithFormat:@"TERNARY(Record1.Children[FIRST] BEGINSWITH Record1.Name, 'SAME', 'DIFFERENT') = 'DIFFERENT'"];
|
||||
|
||||
[self assert:pred1 notEqual:nil];
|
||||
|
||||
pred1 = [CPPredicate predicateWithFormat:@"$x CONTAINS 'a'"];
|
||||
|
||||
[self assert:pred1 notEqual:nil];
|
||||
|
||||
Reference in New Issue
Block a user