【问题标题】:Drools rule validating objects within Scala Option typeDrools 规则验证 Scala 选项类型中的对象
【发布时间】:2015-02-09 16:52:00
【问题描述】:

(强制性新手免责声明)

我正在尝试编写一个规则,只要(scala)列表中的对象匹配条件就会触发。这里的问题是列表实际上是一个 Option(List[TypeA])... (另外,我意识到将列表存储在工作内存中并不是最佳做法,但鉴于这种情况我不能这样做)

我使用的案例类具有以下结构:

TypeA {
    arg1 : Option[List[TypeB]]
}

TypeB {
    value : String
}

我写过类似这样的规则:

when
    $a : TypeA($l : arg1)
    $b : TypeB() from $l.get()
then
    System.out.println($b)

我已经在没有“.get()”的情况下进行了尝试,只是为了获取 Some() 类型的对象。

使用“.get()”,我设法返回了 Option 的内容,但它似乎与预期的类型(List[TypeB])不匹配。相反,返回值的类型似乎是 scala.collection.immutable.$colon$colon

对问题所在有什么想法吗?以及是否有任何适当的方法来处理 Drools 中的选项?

【问题讨论】:

  • 又是你! @laune 没有,我警告过你将 Scala 与 Drools 一起使用。没有经过 Drools 人官方验证这两个工具是否兼容。
  • 是的,我又来了 ;) 收到警告,但我正在使用 Scala 对象(暂时别无选择)并使用 Java 方法与它们进行交互...这更像是一个概念证明在此刻。到目前为止,我已经成功地在 Java 中很好地使用了 Scala 对象,只是这个小烦恼让我暂时退缩了……想法?
  • List 是一些对象 property 并没有什么坏处。这是一个“按原样”使用的列表(或任何其他集合或地图),这是一个不好的设计。
  • Option 包装您的清单有多重要?您是否尝试过查看您返回的类型?我很想知道返回的类型。你能做到吗?
  • 不幸的是,案例类不是我自己的,但它是我必须使用的(无法更改它们)。我已经使用 .get() 进行了尝试,但我得到的只是 scala.collection.immutable.$colon$colon 类型的东西......我认为它是一个带有头部和尾部的通用列表。调查您的答案: mo ​​中的 javaconverters ... 似乎非常有用!谢谢

标签: list scala drools scala-option


【解决方案1】:

由于您正在做大量的 Java 和 Scala 互操作,我建议您让自己非常熟悉 Scala 的 javaconverters 功能。这个方便的实用程序集合允许您将 Scala 集合转换为 Java 集合,反之亦然。

在您的情况下,我认为您需要从 Java 集合转换为 Scala 集合。请尝试以下操作:

import scala.collection.JavaConverters._

val myScalaList = $b.asScala.toList

文档中的示例:

import scala.collection.JavaConverters._

val sl = new scala.collection.mutable.ListBuffer[Int]
val jl : java.util.List[Int] = sl.asJava
val sl2 : scala.collection.mutable.Buffer[Int] = jl.asScala
assert(sl eq sl2)

您遇到的另一个问题是可变和不可变数据结构。 Java 中的标准列表结构是可变的,但默认情况下 Scala 会为您提供不可变列表,除非您明确指出您想要一个可变列表。因此,在两个世界之间进行天真的转换时会出现一些阻抗不匹配。

正如我在之前的文章中提到的,您可以通过为需要推送到 Drools 的实体创建 Java 类来避免很多问题。在基于 Scala 的项目中混合 Java 类和 Scala 类不是问题。

另一种方法是在 Scala 案例类中创建一个函数,该函数使用 asJava 方法将 Scala 集合转换为 Java 集合并返回它。每当您需要引用该 scala 集合时,在您的 DRL 文件中调用此方法,以便获得 Java 集合。

理想情况下,如果 JBoss Drools 愿意,他们需要增强他们当前的编译器以更好地处理 Scala 类型,或者制作一个不会破坏 Scala 类型的专用 Drools Scala 编译器。

【讨论】:

  • 运气不好。问题是我一开始就无法进入列表。我尝试在规则的 RHS 上调用$l.get().asJava() / asScala(),但不断收到与严格模式相关的错误:[Error: unable to resolve method using strict-mode: java.lang.Object.asScala()](自 6.1 KieSessions 以来我还没有找到解决方案)。我已经在不是列表的 Option 参数上尝试了.get(),并且 Drools 似乎返回了 Scala 案例类的对象,但是我再一次无法深入研究它的参数(即我会得到一个 TypeB 但得到错误读取 typeBObj.value)。
  • 您是否导入了这些方法,即import scala.collection.JavaConverters._
  • 是的,在 drl 文件中同时导入了 scala.collections.JavaConverters.* 和 scala.collections.JavaConversions.*
  • 试试这个技巧:在您的 Scala 案例类中创建一个函数,该函数使用 asJava 方法将 Scala 集合转换为 Java 集合并返回它。每当您需要引用该 scala 集合时,在您的 DRL 文件中调用此方法,以便获得 Java 集合。
  • 哈哈。更新了答案。让我们continue this discussion in chat.
【解决方案2】:

我唯一能想到的尝试:

when
    $a : TypeA($l : arg)
    $b : TypeB() from (ArrayList)$l.get() // or some other Java *-List
then
    System.out.println($b)

值得再试一次:

when
    $a : TypeA($l : arg)
    $b : TypeB() from $l.get()asJava()*-List
then
    System.out.println($b)

【讨论】:

  • 还有什么 - 这里只有 Java。如果您知道演员表的更好目标类,请使用它。
  • @laune,OP 还存在可变性和不变性的问题。从帖子看来,Scala 列表是不可变的。但是,如您所知,ArrayList 是可变的。从 Java 中获得与 Scala 的数据结构的一对一映射至少可以说是很棘手。
  • 谢谢@laune。也试过了,但它返回一个空列表,然后在 LHS 中根本不匹配。
  • 可以写$l.get().asJava()吗?这应该返回一个可变的 Java 列表(如果我正确理解了 I.K.)。
  • 虽然不在 drl 文件中。我正在调用一个返回 $l.get.asJava 的 scala 方法。就像您在另一个问题@laune 中提到的 Java 包装器一样
猜你喜欢
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 2021-12-20
  • 2020-09-15
  • 1970-01-01
  • 2020-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多