From 5ab10f40243e049e370bf78439bc68f7b3019158 Mon Sep 17 00:00:00 2001 From: cacaodev Date: Sun, 27 Dec 2015 15:34:37 +0100 Subject: [PATCH] NEW: CPExpression +expressionForBlock:arguments: An expression that returns the result of evaluating a block. With tests. --- Foundation/CPPredicate/CPExpression.j | 1 + Foundation/CPPredicate/_CPBlockExpression.j | 83 +++++++++++++++++++++ Foundation/CPPredicate/_CPExpression.j | 25 +++++++ Tests/Foundation/CPPredicateTest.j | 20 +++++ 4 files changed, 129 insertions(+) create mode 100644 Foundation/CPPredicate/_CPBlockExpression.j diff --git a/Foundation/CPPredicate/CPExpression.j b/Foundation/CPPredicate/CPExpression.j index 06ed6b0ba..12ad45a74 100644 --- a/Foundation/CPPredicate/CPExpression.j +++ b/Foundation/CPPredicate/CPExpression.j @@ -28,3 +28,4 @@ @import "_CPAggregateExpression.j" @import "_CPSetExpression.j" @import "_CPSubqueryExpression.j" +@import "_CPBlockExpression.j" diff --git a/Foundation/CPPredicate/_CPBlockExpression.j b/Foundation/CPPredicate/_CPBlockExpression.j new file mode 100644 index 000000000..109d5d517 --- /dev/null +++ b/Foundation/CPPredicate/_CPBlockExpression.j @@ -0,0 +1,83 @@ +/* + * _CPBlockExpression.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 "_CPExpression.j" + +@implementation _CPBlockExpression : CPExpression +{ + Function _block; + CPArray _arguments; +} + +- (id)initWithBlock:(Function)aBlock arguments:(CPArray)arguments +{ + self = [super initWithExpressionType:CPBlockExpressionType]; + + if (self) + { + _block = aBlock; + _arguments = arguments; + } + + return self; +} + +- (BOOL)isEqual:(id)object +{ + if (self === object) + return YES; + + if (object === nil || object.isa !== self.isa || [object expressionBlock] !== _block || ![[object arguments] isEqual:_arguments]) + return NO; + + return YES; +} + +- (Function)expressionBlock +{ + return _block; +} + +- (CPArray)arguments +{ + return _arguments; +} + +- (id)expressionValueWithObject:(id)object context:(CPDictionary)context +{ + var args = []; + + if (_arguments !== nil) + { + args = _arguments.map(function(expression){ + return [expression expressionValueWithObject:object context:context]; + }); + } + + return _block(object, args, context); +} + +- (CPString)description +{ + return [CPString stringWithFormat:@"Block(0x%@)", [CPString stringWithHash:[self UID]]]; +} + +@end \ No newline at end of file diff --git a/Foundation/CPPredicate/_CPExpression.j b/Foundation/CPPredicate/_CPExpression.j index 5a9561cb7..02fb98801 100644 --- a/Foundation/CPPredicate/_CPExpression.j +++ b/Foundation/CPPredicate/_CPExpression.j @@ -65,6 +65,10 @@ CPIntersectSetExpressionType = 8; An expression that combines two nested expression results by set subtraction. */ CPMinusSetExpressionType = 9; +/*! + An expression that returns the result of evaluating a block. +*/ +CPBlockExpressionType = 10; /*! @ingroup foundation @@ -259,6 +263,27 @@ CPMinusSetExpressionType = 9; return [[_CPSubqueryExpression alloc] initWithExpression:expression usingIteratorVariable:variable predicate:predicate]; } +/*! + Returns Creates an NSExpression object that will use the Block for evaluating objects. + @param aBlock The Block is applied to the object to be evaluated. + +The Block takes three arguments and returns a value: + +evaluatedObject +The object to be evaluated. +expressions +An array of predicate expressions that evaluates to a collection. +context +A dictionary that the expression can use to store temporary state for one predicate evaluation. + +@discussion Note that context is mutable, and that it can only be accessed during the evaluation of the expression. +@param arguments An array containing NSExpression objects that will be used as parameters during the invocation of the block. +*/ ++ (CPExpression)expressionForBlock:(Function)aBlock arguments:(CPArray)args +{ + return [[_CPBlockExpression alloc] initWithBlock:aBlock arguments:args]; +} + // Getting Information About an Expression /*! Returns the expression type for the receiver. diff --git a/Tests/Foundation/CPPredicateTest.j b/Tests/Foundation/CPPredicateTest.j index f167d5513..2d6f8210a 100644 --- a/Tests/Foundation/CPPredicateTest.j +++ b/Tests/Foundation/CPPredicateTest.j @@ -79,6 +79,13 @@ var expression_minusset = [CPExpression expressionForMinusSet:set with:array]; [self assertNotNull:expression_minusset message:"MinusSet Expression should not be nil"]; + + var expression_block = [CPExpression expressionForBlock:function(obj, args, bindings) + { + return obj; + } arguments:nil]; + + [self assertNotNull:expression_block message:"Block Expression should not be nil"]; } - (void)testSetExpressionEvaluation @@ -147,6 +154,19 @@ [self assertTrue:([eval isEqual:expected]) message:"'" + [expression predicateFormat] + "' result is "+ eval + "but should be " + expected]; } +- (void)testBlockExpressionEvaluation +{ + var block = function(obj, args, bindings) + { + return [obj stringByAppendingString:[args componentsJoinedByString:"-"]]; + }; + + var expression = [CPExpression expressionForBlock:block arguments:[[CPExpression expressionForConstantValue:"A"], [CPExpression expressionForConstantValue:"B"]]]; + + var eval = [expression expressionValueWithObject:"OBJ" context:@{}]; + [self assertTrue:([eval isEqual:"OBJA-B"]) message:"'" + [expression description] + "' result is "+ eval + "but should be " + "OBJA-B"]; +} + - (void)testOptions { var pred = [[CPComparisonPredicate alloc] initWithLeftExpression:[CPExpression expressionForConstantValue:@"àa"] rightExpression:[CPExpression expressionForConstantValue:@"aà"] modifier:CPDirectPredicateModifier type:CPLikePredicateOperatorType options:3];