All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.gatling.jsonpath.ComparisonOperator.scala Maven / Gradle / Ivy

There is a newer version: 3.13.3
Show newest version
/*
 * Copyright 2011-2024 GatlingCorp (https://gatling.io)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * 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 io.gatling.jsonpath

import com.fasterxml.jackson.core.JsonParser.NumberType
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.node.JsonNodeType._

/**
 * Originally contributed by Nicolas Rémond.
 */
sealed trait ComparisonOperator extends Product with Serializable {
  def apply(lhs: JsonNode, rhs: JsonNode): Boolean
}

// Comparison operators
sealed trait ComparisonWithOrderingOperator extends ComparisonOperator {
  protected def compare[T: Ordering](lhs: T, rhs: T): Boolean

  private def compareNumbers(lhs: JsonNode, rhs: JsonNode): Boolean =
    lhs.numberType match {
      case NumberType.INT =>
        rhs.numberType match {
          case NumberType.INT                       => compare(lhs.intValue, rhs.intValue)
          case NumberType.LONG                      => compare(lhs.longValue, rhs.longValue)
          case NumberType.DOUBLE | NumberType.FLOAT => compare(lhs.doubleValue, rhs.doubleValue)
          case NumberType.BIG_INTEGER               => compare(lhs.bigIntegerValue, rhs.bigIntegerValue)
          case NumberType.BIG_DECIMAL               => compare(lhs.decimalValue, rhs.decimalValue)
        }

      case NumberType.LONG =>
        rhs.numberType match {
          case NumberType.INT | NumberType.LONG     => compare(lhs.longValue, rhs.longValue)
          case NumberType.DOUBLE | NumberType.FLOAT => compare(lhs.doubleValue, rhs.doubleValue)
          case NumberType.BIG_INTEGER               => compare(lhs.bigIntegerValue, rhs.bigIntegerValue)
          case NumberType.BIG_DECIMAL               => compare(lhs.decimalValue, rhs.decimalValue)
        }

      case NumberType.FLOAT =>
        rhs.numberType match {
          case NumberType.INT | NumberType.LONG | NumberType.DOUBLE => compare(lhs.doubleValue, rhs.doubleValue)
          case NumberType.FLOAT                                     => compare(lhs.floatValue, rhs.floatValue)
          case NumberType.BIG_INTEGER | NumberType.BIG_DECIMAL      => compare(lhs.decimalValue, rhs.decimalValue)
        }

      case NumberType.DOUBLE =>
        rhs.numberType match {
          case NumberType.INT | NumberType.LONG | NumberType.DOUBLE | NumberType.FLOAT => compare(lhs.doubleValue, rhs.doubleValue)
          case NumberType.BIG_INTEGER | NumberType.BIG_DECIMAL                         => compare(lhs.decimalValue, rhs.decimalValue)
        }

      case NumberType.BIG_INTEGER =>
        rhs.numberType match {
          case NumberType.INT | NumberType.LONG | NumberType.BIG_INTEGER     => compare(lhs.bigIntegerValue, rhs.bigIntegerValue)
          case NumberType.DOUBLE | NumberType.FLOAT | NumberType.BIG_DECIMAL => compare(lhs.decimalValue, rhs.decimalValue)
        }

      case NumberType.BIG_DECIMAL => compare(lhs.decimalValue, rhs.decimalValue)

      case _ => false
    }

  def apply(lhs: JsonNode, rhs: JsonNode): Boolean =
    lhs.getNodeType match {
      case STRING  => rhs.getNodeType == STRING && compare(lhs.textValue, rhs.textValue)
      case BOOLEAN => rhs.getNodeType == BOOLEAN && compare(lhs.booleanValue, rhs.booleanValue)
      case NUMBER  => rhs.getNodeType == NUMBER && compareNumbers(lhs, rhs)
      case _       => false
    }
}

case object EqWithOrderingOperator extends ComparisonWithOrderingOperator {
  protected def compare[T: Ordering](lhs: T, rhs: T): Boolean = Ordering[T].equiv(lhs, rhs)
}

case object EqOperator extends ComparisonOperator {
  override def apply(lhs: JsonNode, rhs: JsonNode): Boolean =
    (lhs.getNodeType == NULL && rhs.getNodeType == NULL) || EqWithOrderingOperator(lhs, rhs)
}

case object NotEqOperator extends ComparisonOperator {
  override def apply(lhs: JsonNode, rhs: JsonNode): Boolean = !EqOperator(lhs, rhs)
}

case object LessOperator extends ComparisonWithOrderingOperator {
  override protected def compare[T: Ordering](lhs: T, rhs: T): Boolean = Ordering[T].lt(lhs, rhs)
}

case object GreaterOperator extends ComparisonWithOrderingOperator {
  override protected def compare[T: Ordering](lhs: T, rhs: T): Boolean = Ordering[T].gt(lhs, rhs)
}

case object LessOrEqOperator extends ComparisonWithOrderingOperator {
  override protected def compare[T: Ordering](lhs: T, rhs: T): Boolean = Ordering[T].lteq(lhs, rhs)
}

case object GreaterOrEqOperator extends ComparisonWithOrderingOperator {
  override protected def compare[T: Ordering](lhs: T, rhs: T): Boolean = Ordering[T].gteq(lhs, rhs)
}

// Binary boolean operators
sealed trait BinaryBooleanOperator extends Product with Serializable {
  def apply(lhs: Boolean, rhs: Boolean): Boolean
}

case object AndOperator extends BinaryBooleanOperator {
  override def apply(lhs: Boolean, rhs: Boolean): Boolean = lhs && rhs
}

case object OrOperator extends BinaryBooleanOperator {
  override def apply(lhs: Boolean, rhs: Boolean): Boolean = lhs || rhs
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy