流口水会检查列表中的一个属性是否存在于其他列表中

问题描述

我遵循以下结构:

public class Proposal {
   private final List<Product> products; 
   private final List<Customer> customers;
}

public class Customer {
   private String id;
   private String country;
}

public class Product {
  private String customerId;
  private String country;
  private String type; 
}

要求是: 不要检查产品类型是“ A”还是“ B”,以及ID为21的客户。 对于其他任何产品,请检查customerId是否与id匹配,或者将客户所在国家/地区设置为null,并将产品上的国家/地区设置为“美国”

基于此,我准备了一条规则,但该规则不起作用:

//rule body
Proposal($products: products,$customers: customers)

$productstochecks : Product(customerId != "21") && type not in ("A","B") from $products

//first condition to check if there is any applicable case:
exist(Product(customerId != "21") && type not in ("A","B") from $products) and

(
  // check if there is a customer who can use this product
  forall (
    Product($customerId: customerId,$country: country) from $productstochecks
    Customer(id == $customerId || (country == null &&  $country == "US"))

  )
)

谢谢您的帮助或建议

解决方法

您的$productsToChecks声明中存在语法错误:

$productsToChecks : Product(customerId != "21") && type not in ("A","B") from $products

您要检查的两个属性都必须位于Product( ... )部分内,如下所示:

$productsToChecks: Product( customerId != "21",type not in ("A","B")) from $products

您也会在规则的其他部分重复此错误。


所以您的要求是:

不要检查产品类型是“ A”还是“ B”以及ID为ID的客户:21.对于其他产品,请检查customerId是否与ID相匹配,或者是否将客户所在国家/地区设置为null,将客户所在国家/地区设置为产品设置为“美国”

我们可以将其提炼为以下伪代码:

  • 何时
    • 产品不是:(类型= A或类型= B)且customerId = 21
    • (产品customerId ==客户ID)或(客户国家/地区== null和产品国家/地区==美国)
  • 然后做点事情

鉴于第二部分的“或”,这是两个规则。

我们需要做的第一部分是找到我们关注的产品子集。您可以通过多种方式执行此操作-collectaccumulate是立即想到的两个。假设您的问题的要求是完整的,那么collect在这里(更简单)更合适。

Proposal($products: products,$customers: customers)

$productSubset: List() from collect( Product( customerId != 21,"B") ) from $products)

现在,您可以使用该产品子集(其中不包括您需要忽略的产品)来匹配您的其他条件。正如我提到的,由于这些条件是“或”运算,因此它们应该是两个不同的规则。

rule "Product customerId matches Customer id"
when
  Proposal($products: products,$customers: customers)
  $productSubset: List() 
                  from collect( Product( customerId != 21,"B") ) from $products)

  Customer( $id: id != null ) from $customers
  $product: Product( customerId == $id ) from $productSubset
then
  // do something with $product
end

rule "US Product and no Customer Country"
when
  Proposal($products: products,"B") ) from $products)

  Customer( country == null ) from $customers
  $product: Product( country == "US" ) from $productSubset
then
  // do something with $product
end

要减少重复的代码,可以将通用条件放入单个“父”规则中,然后使用extends关键字创建两个具有不同条件的子规则。

我以这样的方式设计了这些规则,即假设您想对符合您条件的每种产品采取一些措施。基于此假设,右侧将为与每个规则的条件匹配的每个产品触发(还要注意,由于这两个规则不是互斥的,因此,如果customerId与相匹配,则产品可能会触发两次。国家/地区要求得到满足。)

但是,如果结果所需的只是符合条件的所有产品的列表,则可以再次使用函数来获取该产品列表。在这种情况下,accumulate函数比collect更合适:

rule "Get list of products for customer"
when
  Proposal($products: products,"B") ) from $products)

  Customer( $id: id != null,$country: country ) from $customers

  $product: Product( customerId == $id ) from $productSubset

  $customerProducts: List() from accumulate(
                       $p: Product((customerId == $id) || ($country == null && country == "US")) from $products,collectList($p)
                     )
then
  // do something with $customerProducts
end

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...