Skip to content

Commit

Permalink
refactor: Extract equals comparison
Browse files Browse the repository at this point in the history
Move the equals comparison in a separate class to be reusable.
  • Loading branch information
saig0 committed Aug 30, 2024
1 parent 9c3ed24 commit f5c5017
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -519,58 +519,11 @@ class FeelInterpreter {
withValues(
x,
y,
{
case (ValNull, _) => f(c(ValNull, y.toOption.getOrElse(ValNull)))
case (_, ValNull) => f(c(x.toOption.getOrElse(ValNull), ValNull))
case (ValNumber(x), ValNumber(y)) => f(c(x, y))
case (ValBoolean(x), ValBoolean(y)) => f(c(x, y))
case (ValString(x), ValString(y)) => f(c(x, y))
case (ValDate(x), ValDate(y)) => f(c(x, y))
case (ValLocalTime(x), ValLocalTime(y)) => f(c(x, y))
case (ValTime(x), ValTime(y)) => f(c(x, y))
case (ValLocalDateTime(x), ValLocalDateTime(y)) => f(c(x, y))
case (ValDateTime(x), ValDateTime(y)) => f(c(x, y))
case (ValYearMonthDuration(x), ValYearMonthDuration(y)) => f(c(x, y))
case (ValDayTimeDuration(x), ValDayTimeDuration(y)) => f(c(x, y))
case (ValList(x), ValList(y)) =>
if (x.size != y.size) {
f(false)

} else {
val isEqual = x.zip(y).foldRight(true) { case ((x, y), listIsEqual) =>
listIsEqual && {
checkEquality(x, y, c, f) match {
case ValBoolean(itemIsEqual) => itemIsEqual
case _ => false
}
}
}
f(isEqual)
}
case (ValContext(x), ValContext(y)) =>
val xVars = x.variableProvider.getVariables
val yVars = y.variableProvider.getVariables

if (xVars.keys != yVars.keys) {
f(false)

} else {
val isEqual = xVars.keys.foldRight(true) { case (key, contextIsEqual) =>
contextIsEqual && {
val xVal = context.valueMapper.toVal(xVars(key))
val yVal = context.valueMapper.toVal(yVars(key))

checkEquality(xVal, yVal, c, f) match {
case ValBoolean(entryIsEqual) => entryIsEqual
case _ => false
}
}
}
f(isEqual)
}
case _ =>
{ (x, y) =>
new ValComparator(context.valueMapper).compare(x, y).toOption.getOrElse {
error(EvaluationFailureType.NOT_COMPARABLE, s"Can't compare '$x' with '$y'")
ValNull
}
}
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. Camunda licenses this file to you under the Apache License,
* Version 2.0; you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.camunda.feel.impl.interpreter

import org.camunda.feel.context.Context
import org.camunda.feel.syntaxtree._
import org.camunda.feel.valuemapper.ValueMapper

class ValComparator(private val valueMapper: ValueMapper) {

def compare(x: Val, y: Val): Val = (x, y) match {
// both values are null
case (ValNull, _) => ValBoolean(ValNull == y.toOption.getOrElse(ValNull))
case (_, ValNull) => ValBoolean(x.toOption.getOrElse(ValNull) == ValNull)
// compare values of the same type
case (ValNumber(x), ValNumber(y)) => ValBoolean(x == y)
case (ValBoolean(x), ValBoolean(y)) => ValBoolean(x == y)
case (ValString(x), ValString(y)) => ValBoolean(x == y)
case (ValDate(x), ValDate(y)) => ValBoolean(x == y)
case (ValLocalTime(x), ValLocalTime(y)) => ValBoolean(x == y)
case (ValTime(x), ValTime(y)) => ValBoolean(x == y)
case (ValLocalDateTime(x), ValLocalDateTime(y)) => ValBoolean(x == y)
case (ValDateTime(x), ValDateTime(y)) => ValBoolean(x == y)
case (ValYearMonthDuration(x), ValYearMonthDuration(y)) => ValBoolean(x == y)
case (ValDayTimeDuration(x), ValDayTimeDuration(y)) => ValBoolean(x == y)
case (ValList(x), ValList(y)) => compare(x, y)
case (ValContext(x), ValContext(y)) => compare(x, y)
// values have a different type
case _ => ValError(s"Can't compare '$x' with '$y'")
}

private def compare(x: List[Val], y: List[Val]): ValBoolean = {
if (x.size != y.size) {
ValBoolean(false)

} else {
val itemsAreEqual = x.zip(y).foldRight(true) { case ((x, y), listIsEqual) =>
listIsEqual && {
compare(x, y) match {
case ValBoolean(itemIsEqual) => itemIsEqual
case _ => false
}
}
}
ValBoolean(itemsAreEqual)
}
}

private def compare(x: Context, y: Context): ValBoolean = {
val xVars = x.variableProvider.getVariables
val yVars = y.variableProvider.getVariables

if (xVars.keys != yVars.keys) {
ValBoolean(false)

} else {
val itemsAreEqual = xVars.keys.foldRight(true) { case (key, contextIsEqual) =>
contextIsEqual && {
val xVal = valueMapper.toVal(xVars(key))
val yVal = valueMapper.toVal(yVars(key))

compare(xVal, yVal) match {
case ValBoolean(entryIsEqual) => entryIsEqual
case _ => false
}
}
}
ValBoolean(itemsAreEqual)
}
}

}

0 comments on commit f5c5017

Please sign in to comment.