drools mvel for each element in a map

大城市里の小女人 提交于 2019-12-24 01:53:02

问题


One of the no-nos in drools includes manually iterating over collections in the consequence (then clause). I need to write a drool which is effectively iterating over a map while doing something for each key value pair in that map. In other words, I need to duplicate the behavior of a for-each loop in drools without actually writing a for-each loop.

Now, I realize I could just write a for-each loop in the consequence. I want to keep my code as close to drools-standard as possible. I have included a more concrete example below.

I have a map of strings and colors.

Map<String, Color> colorMap

For every color in the map, I want to check a different collection to find the exact code for that color.

Map<Color, ColorCode> colorCodes

A Java dialect approach would be something like the following:

for (Map.Entry<String, Color> entry : colorMap.entrySet())
{
    ColorCode code = colorCodes.get(entry.getValue());

    thenconsequence.do(code);
}

How would something similar be done using the drools dialect?

Update: The more I think about this problem, the more I am concerned I shouldn't be doing this sort of map lookup/iterating in the context of drools. The right way of doing it may instead be to insert fact object representations of these collections into the working memory. For example, I might wrap each color in a colorFact which has the Color wrapped up in and a field indicating the color name. Same with the codes. I could then write a drool along the lines of:

when
Color(name=="blue", $c:color)
ColorCode(name == "blue", $code:colorCode)
then 
  $code.printCode();
end

If this is the best way to go about it, I'm concerned about the sheer number of facts I am going to have to add. I already have thousands. This will create tens of thousands more. I'm not worried about memory. Rather, I'm worried about the time required to iterate through all these collections and adding their elements to working memory. Can anyone comment on if this is the best way to do this, or if a better way exists?


回答1:


Although this can be done using a simple set of Java statements, here's how to do it in a single rule, with the least (I think) amount of overhead for insertion etc:

rule "matchcolorcode"
when
    $cm: ColorMap()
    Map.Entry( $key: key, $color: value ) from $cm.entrySet()
    $ccm: ColorCodeMap( $ccm.containsKey($key) )
then
    System.out.println( $key + ": " + $color + ", " + $ccm.get($key) );
end

The facts are simple wrappers for generic instantiations of HashMap, e.g.:

class ColorMap extends HashMap<String,Color> {}


来源:https://stackoverflow.com/questions/22547374/drools-mvel-for-each-element-in-a-map

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!