我在工作内存中有一个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>
答案 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