Drools - extract value inside a map and assign - error : unable to resolve method using strict-mode

Drools - extract value inside a map and assign - error : unable to resolve method using strict-mode

感谢@roddy 对我的查询的回答

复制粘贴之前的内容以设置上下文: 这是我的数据结构:

public class Premium{

    private Map<String,Map<String,String>> valuesMap = new HashMap<String,Map<String,String>>();
    
    public Map<String, Map<String, String>> getValuesMap() {
       return valuesMap;
    }
}

将出现在此 'valuesMap' 中的示例值:

Map<String,String> m1= new HashMap<String,String>();
m1.put("death","100");
m1.put("income","50");

valuesMap.put("Male",m1);
valuesMap.put("Female",m2);
....

感谢@Roddy,现在我可以提取嵌入在 'valuesMap' 中的地图 'm1' 用于“男性”

rule "rule#7 testing me 001 "
when
    // below line extracts 'valuesMap' from Premium object
    $pr:Premium($masterMap:valuesMap) 
    // now have a handle to the embedded map for 'Male'
    Map( $male: this["Male"] ) from $masterMap
    
    // defining an object in which I want to populate the value from map obtained for male
    $rulesResponse:RulesResponse();
then   
    System.out.println("rule#7 map " + $map);
    // this is where in below code it is failing 
    $rulesResponse.abc = $innerMap.get("income");
end

当我尝试根据键 'income' 从映射中提取字符串并将其分配给 'RulesResponse' 对象时,它失败了:

[Error: unable to resolve method using strict-mode: java.lang.Object.get(java.lang.String)]
[Near : {... nse.abc = $innerMap.get("income"); ....}]

响应对象是一个简单的 POJO,属性为 getter 和 setter:abc

public class RulesResponse {
private String abc = "";

public String getAbc() {
    return abc;
}

public void setAbc(String abc) {
    this.abc = abc;
}

如果我尝试分配一个硬编码值 - 它会起作用,并且还会在规则执行后反映出来

// this works
$rulesResponse.abc = "hard coded value";

当您 this["Male"] 离开地图时,它是一个对象,而不是任何类型。这基本上是由于类型擦除——Map<String, ?>.

你可以通过Map( $income: this["income"]) from $male得到“收入”。当然,现在 $income 也将是一个对象,因此您需要再次转换它。可以像右侧的 (String)$income 或左侧的 $incomeStr: String() from $income 一样简单。

rule "Example"
when
    $pr: Premium( $masterMap: valuesMap != null ) 
    Map( $male: this["Male"] != null ) from $masterMap
    Map( $income: this["income"] != null ) from $male

    $rulesResponse: RulesResponse()
then
    $rulesResponse.abc = (String)$income; // cast as necessary
end

由于类型擦除,我们失去了嵌套的类型身份——你有一个 Map<String, ?>,实际上变成了 Map<String, Object>


强烈建议使用结构正确的 POJO 而不是 Map 作为规则输入。即使您的实际代码使用这些嵌套映射(糟糕的做法!),您也应该在调用规则之前利用转换——您的规则不仅会更简单、更容易使用,而且它们的性能也会更高.

即使将内部映射转换为对象也会使事情变得更容易:

class GenderValues {
  String death;
  String income;
}

class Premium {
  Map<String, GenderValues> valuesByGender;
}

最佳做法是完全省略地图。