为什么'from'关键字会向后迭代?

时间:2011-01-20 20:20:40

标签: jboss drools

我在工作内存中有一个ArrayList,我在when子句中使用'from'语句进行迭代。但是,该规则在数组中向后迭代。有没有办法控制这种行为?

列表创建:

List<Map<String,String>> list = new ArrayList<Map<String,String>>();
Map<String,String> m1 = ...
Map<String,String> m2 = ...
list.add(m1);
list.add(m2);
ImportItem item = new ImportItem(list);  //model object. Constructor arg returned by getInput()
StatelessKnowledgeSession session = knowledgeBase.newStatelessKnowledgeSession();
session.insert(item);
session.fireAllRules();

Drools规则:

rule "My Rule"
dialect "java"
when
    item : ImportItem(ignore == false)  //model object that holds the input
    map  : Map() from item.getInput()  // == the ArrayList from above
then
    System.out.println(map);
end

可生产

<output of m2>
<output of m1>

2 个答案:

答案 0 :(得分:3)

迭代不会倒退,因为您可以看到是否将审核日志附加到会话中。默认情况下,规则的执行遵循LIFO订单(如果您未使用任何其他冲突解决策略)。

我的建议是不要尝试将对象封装在数据结构中。如果要读取文件的行并且需要按顺序处理这些行,只需使用类来表示行并将行直接插入到会话中。为了保证执行顺序,您可以使用行号作为显着性的参数。

例如:

rule "Process lines in order"
   // salience executes from higher number to lowest number, so using the 
   // negative value you will executem them from the first to the last
   salience (- $lineNumber )
when
   $line : Line( $lineNumber : lineNumber )
then
   // do something with $line
end

显然,你可以使用“from”方法使用相同的技巧,但是引擎在工作内存中匹配事实的效率要高于迭代对象集合的效率。

希望它有所帮助。 埃德森

答案 1 :(得分:0)

您应该始终尝试编写规则,以便订单不计算在内。但是,如果您确实需要按特定顺序触发规则,或者在这种情况下,请按特定顺序从列表中获取事实。当您更新到较新版本的引擎时,请确保规则引擎内部的任何更改都不会破坏您的规则。

你不能相信“来自”,即使它以相反的方式进行迭代。

此解决方案存在一个问题。如果更新ImportItem并需要再次遍历输入,则需要撤消与其相关的MyIterator。

declare MyIterator
    index:int
    lastIndex:int
    importItem:ImportItem
end 

rule "Insert ImportItem iterator"
    when
        item : ImportItem()
        not MyIterator( importItem == item )
    then
        MyIterator myIterator = new MyIterator();
        myIterator.setImportItem( item );
        myIterator.setIndex( 0 );
        myIterator.setLastIndex( item.getInput().size() ); 
        insert( myIterator );
end

rule "My Rule"
    when
        myIterator :MyIterator( index < lastIndex )
        item : ImportItem(  this == myIterator.importItem, 
                            ignore == false )
        map  : Map() from item.getInput().get( myIterator.getIndex() )  
    then
        System.out.println(map);

        myIterator.setIndex( myIterator.getIndex() + 1 );
        update( myIterator );
end