private def invoke()

in nlpcraft/src/main/scala/org/apache/nlpcraft/internal/impl/NCModelScanner.scala [163:297]


    private def invoke(cfg: NCModelConfig, mtd: Method, obj: AnyRef, args: scala.Array[AnyRef]): NCResult =
        val methodObj = if Modifier.isStatic(mtd.getModifiers) then null else obj
        var flag = mtd.canAccess(methodObj)
        lazy val z = s"mdlId=${cfg.getId}, callback=${method2Str(mtd)}"
        try
            if !flag then
                mtd.setAccessible(true)
                flag = true
            else
                flag = false
            mtd.invoke(methodObj, args: _*).asInstanceOf[NCResult]
        catch
            case e: InvocationTargetException =>
                e.getTargetException match
                    case cause: NCIntentSkip => throw cause
                    case cause: NCRejection => throw cause
                    case cause: NCException => throw cause
                    case cause: Throwable => E(s"Intent callback invocation error [$z]", cause)
            case e: Throwable => E(s"Unexpected intent callback invocation error [$z]", e)
        finally
            if flag then
                try mtd.setAccessible(false)
                catch case e: SecurityException => E(s"Access or security error in intent callback [$z]", e)

    /**
      *
      * @param cfg
      * @param field
      * @param obj
      */
    private def getFieldObject(cfg: NCModelConfig, field: Field, obj: AnyRef): AnyRef =
        lazy val fStr = field2Str(field)
        val fieldObj = if Modifier.isStatic(field.getModifiers) then null else obj
        var flag = field.canAccess(fieldObj)
        lazy val z = s"mdlId=${cfg.getId}, field=$fStr"
        val res =
            try
                if !flag then
                    field.setAccessible(true)
                    flag = true
                else
                    flag = false
                field.get(fieldObj)
            catch case e: Throwable => E(s"Unexpected field access error [$z]", e)
            finally
                if flag then
                    try field.setAccessible(false)
                    catch case e: SecurityException => E(s"Access or security error in field [$z]", e)

        if res == null then throw new NCException(s"Field value cannot be 'null' for [$z]")
        res

    /**
      *
      * @param mtd
      * @param argIdx
      */
    private def arg2Str(mtd: Method, argIdx: Int): String = s"#${argIdx + 2} of ${method2Str(mtd)}"

    /**
      * Gets its own methods including private and accessible from parents.
      *
      * @param o Object.
      * @return Methods.
      */
    private def getAllMethods(o: AnyRef): Set[Method] =
        val cls = o.getClass
        (cls.getDeclaredMethods ++ cls.getMethods).toSet

    /**
      * Gets its own fields including private and accessible from parents.
      *
      * @param o Object.
      * @return Fields.
      */
    private def getAllFields(o: AnyRef): Set[Field] =
        val cls = o.getClass
        (cls.getDeclaredFields ++ cls.getFields).toSet

    /**
      *
      * @param cfg
      * @param mtd
      * @param argClasses
      * @param paramGenTypes
      */
    private def checkTypes(cfg: NCModelConfig, mtd: Method, argClasses: Seq[Class[_]], paramGenTypes: Seq[Type]): Unit =
        require(argClasses.sizeIs == paramGenTypes.length)

        var warned = false

        argClasses.zip(paramGenTypes).zipWithIndex.foreach { case ((argClass, paramGenType), i) =>
            def mkArg(): String = arg2Str(mtd, i)

            lazy val z = s"mdlId=${cfg.getId}, type=${class2Str(argClass)}, arg=${mkArg()}"

            // Entity.
            if argClass == CLS_ENTITY then () // No-op.
            else if argClass.isArray then
                val compType = argClass.getComponentType
                if compType != CLS_ENTITY then
                    E(s"Unexpected array element type for $IT annotated argument [$z]")
                // Entities collection and optionals.
            else if COMP_CLS.contains(argClass) then
                paramGenType match
                    case pt: ParameterizedType =>
                        val actTypes = pt.getActualTypeArguments
                        val compTypes = if actTypes == null then Seq.empty else actTypes.toSeq
                        if compTypes.sizeIs != 1 then
                            E(s"Unexpected generic types count for $IT annotated argument [count=${compTypes.length}, $z]")
                        val compType = compTypes.head
                        compType match
                            case _: Class[_] =>
                                val genClass = compTypes.head.asInstanceOf[Class[_]]
                                if genClass != CLS_ENTITY then
                                    E(s"Unexpected generic type for $IT annotated argument [$z]")
                            case _: WildcardType =>
                                val wildcardType = compTypes.head.asInstanceOf[WildcardType]
                                val lowBounds = wildcardType.getLowerBounds
                                val upBounds = wildcardType.getUpperBounds
                                if lowBounds.nonEmpty || upBounds.size != 1 || upBounds(0) != CLS_ENTITY then
                                    E(s"Unexpected generic type for $IT annotated argument [$z]")
                            case _ => E(s"Unexpected generic type for $IT annotated argument [$z]")
                    case _ =>
                        if COMP_CLS.exists(_ == paramGenType) then
                            if !warned then
                                warned = true
                                logger.warn(s"Unable to detected and type-check method argument [${method2Str(mtd)}, $z]")
                            end if
                        else
                            E(s"Unexpected parameter type for $IT annotated argument [$z]")
            else
                // Other types.
                E(s"Unexpected parameter type for $IT annotated argument [$z]")
        }