Skip to content

Commit

Permalink
Filter list with custom function (#417)
Browse files Browse the repository at this point in the history
* test(engine): verify list filter with function

* verify that a list can be filtered with a built-in and custom function
* verify that the custom function is invoked with the expected elements

* fix(engine): filter list with function

* a list can be filtered using a boolean function
* currently, the function is invoked once to determine if it is a number (for index access) or a boolean value (or something else)
* since the function is invoked without the list item, the invocation can fail if the "item" variable is passed in as a parameter
  • Loading branch information
saig0 committed Apr 25, 2022
1 parent 8552b02 commit 11f0947
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -253,21 +253,23 @@ class FeelInterpreter {
case Filter(list, filter) =>
withList(
eval(list),
l =>
l => {
val evalFilterWithItem =
(item: Val) => eval(filter)(filterContext(item))

filter match {
case ConstNumber(index) => filterList(l.items, index)
case ArithmeticNegation(ConstNumber(index)) =>
filterList(l.items, -index)
case comparison: Comparison =>
filterList(l.items,
item => eval(comparison)(filterContext(item)))
case _: Comparison | _: FunctionInvocation |
_: QualifiedFunctionInvocation =>
filterList(l.items, evalFilterWithItem)
case _ =>
eval(filter) match {
case ValNumber(index) => filterList(l.items, index)
case _ =>
filterList(l.items,
item => eval(filter)(filterContext(item)))
case _ => filterList(l.items, evalFilterWithItem)
}
}
}
)
case IterationContext(start, end) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import org.camunda.feel.syntaxtree._
import org.scalatest.matchers.should.Matchers
import org.scalatest.flatspec.AnyFlatSpec

import scala.collection.mutable.ListBuffer

/**
* @author Philipp Ossler
*/
Expand Down Expand Up @@ -97,7 +99,7 @@ class InterpreterListExpressionTest
)))
}

it should "be filtered via boolean expression" in {
it should "be filtered via comparison" in {

eval("[1,2,3,4][item > 2]") should be(
ValList(List(ValNumber(3), ValNumber(4))))
Expand All @@ -121,6 +123,39 @@ class InterpreterListExpressionTest
eval("[1,2,3,4][i]", Map("i" -> -2)) should be(ValNumber(3))
}

it should "be filtered via boolean expression" in {
eval("[1,2,3,4][odd(item)]") should be(
ValList(List(ValNumber(1), ValNumber(3))))

eval("[1,2,3,4][even(item)]") should be(
ValList(List(ValNumber(2), ValNumber(4))))
}

it should "be filtered via custom function" in {
val functionInvocations: ListBuffer[Val] = ListBuffer.empty

val result = eval(
expression = "[1,2,3,4][f(item)]",
variables = Map(),
functions = Map("f" -> ValFunction(
params = List("x"),
invoke = {
case List(x) =>
functionInvocations += x
ValBoolean(x == ValNumber(3))
}
)))

result should be(ValList(List(ValNumber(3))))

functionInvocations should be(List(
ValNumber(1),
ValNumber(2),
ValNumber(3),
ValNumber(4))
)
}

it should "be filtered multiple times (from literal)" in {
eval("[[1]][1][1]") should be(ValNumber(1))
eval("[[[1]]][1][1][1]") should be(ValNumber(1))
Expand Down

0 comments on commit 11f0947

Please sign in to comment.