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

camundala.dmn.DmnTesterConfigCreator.scala Maven / Gradle / Ivy

There is a newer version: 1.30.23
Show newest version
package camundala
package dmn

import camundala.domain.*
import camundala.bpmn.*
import pme123.camunda.dmn.tester.shared.*

import java.time.LocalDateTime
import scala.language.reflectiveCalls
import scala.reflect.ClassTag

trait DmnTesterConfigCreator extends DmnConfigWriter:

  // the path where the DMNs are
  protected def dmnBasePath: os.Path = starterConfig.dmnPaths.head
  // the path where the DMN Configs are
  protected def dmnConfigPath: os.Path = starterConfig.dmnConfigPaths.head
  // creating the Path to the DMN - by default the _dmnName_ is `decisionDmn.decisionDefinitionKey`.
  protected def defaultDmnPath(dmnName: String): os.Path = dmnBasePath / s"$dmnName.dmn"

  protected def createDmnConfigs(dmnTesterObjects: DmnTesterObject[?]*): Unit =
    dmnConfigs(dmnTesterObjects)
      .foreach(updateConfig(_, dmnConfigPath))
    println("Check it on http://localhost:8883")
  end createDmnConfigs

  given [In <: Product]: Conversion[DecisionDmn[In, ?], DmnTesterObject[In]] =
    decisionDmn =>
      DmnTesterObject(
        decisionDmn,
        defaultDmnPath(decisionDmn.decisionDefinitionKey)
      )

  private def dmnConfigs(
      dmnTesterObjects: Seq[DmnTesterObject[?]]
  ): Seq[DmnConfig] =
    dmnTesterObjects
      .filterNot(_._inTestMode)
      .map { dmnTO =>
        val dmn = dmnTO.dDmn
        val in: Product = dmn.in
        val inputs = toInputs(in, dmnTO)
        val variables = toVariables(in)
        DmnConfig(
          dmn.decisionDefinitionKey,
          TesterData(inputs, variables),
          dmnTO.dmnPath.relativeTo(projectBasePath).segments.toList,
          testUnit = dmnTO._testUnit,
          acceptMissingRules = dmnTO._acceptMissingRules
        )

      }

  private def toInputs[T <: Product](
      product: T,
      dmnTO: DmnTesterObject[?]
  ) =
    product.productElementNames
      .zip(product.productIterator)
      .collect {
        case (k, v) if !v.isInstanceOf[DmnVariable[?]] =>
          testValues(k, v, dmnTO.addTestValues)
      }
      .toList

  private def testValues[E: ClassTag](
      k: String,
      value: E,
      addTestValues: Map[String, List[TesterValue]]
  ): TesterInput =
    val unwrapValue = value match
      case d: LocalDateTime => d.toString
      case Some(v) => v
      case v => v
    val isNullable = value match
      case Some(_) => true
      case _ => false
    // noinspection ScalaUnnecessaryParentheses
    unwrapValue match
      case v: (Double | Int | Long | Short | String | Float) =>
        TesterInput(
          k,
          isNullable,
          addTestValues.getOrElse(k, List(TesterValue.fromAny(v)))
        )
      case _: Boolean =>
        TesterInput(
          k,
          isNullable,
          List(TesterValue.fromAny(true), toTesterValue(false))
        )
      case v: scala.reflect.Enum =>
        val e: { def values: Array[?] } =
          v.asInstanceOf[{ def values: Array[?] }]
        TesterInput(
          k,
          isNullable,
          addTestValues.getOrElse(k, e.values.map(v => toTesterValue(v)).toList)
        )
      case v =>
        throw new IllegalArgumentException(
          s"Not supported for DMN Input ($k -> $v)"
        )
    end match
  end testValues

  private def toVariables[T <: Product](
      product: T
  ) =
    product.productElementNames
      .zip(product.productIterator)
      .collect { case (k, v: DmnVariable[?]) =>
        val result: DmnValueType = v.value
        testValues(k, result, Map.empty)
      }
      .toList

  case class DmnTesterObject[In <: Product](
      dDmn: DecisionDmn[In, ?],
      dmnPath: os.Path,
      addTestValues: Map[String, List[TesterValue]] = Map.empty,
      _testUnit: Boolean = false,
      _acceptMissingRules: Boolean = false,
      _inTestMode: Boolean = false
  )

  private def toTesterValue(value: Any) =
    value match
      // enums not supported in DmnTester 2.13
      case e: scala.reflect.Enum => TesterValue.fromAny(e.toString)
      case v => TesterValue.fromAny(v)

  extension [In <: Product](dmnTO: DmnTesterObject[In])

    def dmnPath(path: os.Path): DmnTesterObject[In] =
      dmnTO.copy(dmnPath = path)

    def dmnPath(dmnName: String): DmnTesterObject[In] =
      dmnPath(defaultDmnPath(dmnName))

    def testUnit: DmnTesterObject[In] =
      dmnTO.copy(_testUnit = true)

    def inTestMode: DmnTesterObject[In] =
      dmnTO.copy(_inTestMode = true)

    def acceptMissingRules: DmnTesterObject[In] =
      dmnTO.copy(_acceptMissingRules = true)

    inline def testValues(
        inline key: In => DmnValueType | Option[DmnValueType],
        values: Any*
    ): DmnTesterObject[In] =
      val testerValues = values
        .map(v => toTesterValue(v.toString))
        .toList
      dmnTO.copy(addTestValues =
        dmnTO.addTestValues + (nameOfVariable(key) -> testerValues)
      )
    end testValues
  end extension
end DmnTesterConfigCreator




© 2015 - 2024 Weber Informatics LLC | Privacy Policy