我想在规则文件中将Calendar
附加到知识会话中。
目前,我是通过在Java文件中编写所需的代码来实现的:
ClassCalendar.java
:
package app1;
import org.kie.api.runtime.KieSession;
import org.kie.api.time.Calendar;
import org.quartz.impl.calendar.WeeklyCalendar;
public class ClassCalendar {
public static final void main(String[] args) {
try {
WeeklyCalendar weekDayCal = new WeeklyCalendar();
weekDayCal.setDaysExcluded(new boolean[] { false, false, false, false, false, false, false, false, false });
weekDayCal.setDayExcluded(java.util.Calendar.TUESDAY, true);
Calendar calendar = new CalendarWrapper(weekDayCal);
String ruleFilePath = "src/main/resources/rules/ruleFile1.drl";
KieSession kSession = KSessionUtil.buildKSession(ruleFilePath);
kSession.getCalendars().set("calendar", calendar);
kSession.insert(new String("hello"));
kSession.fireAllRules();
System.out.println("Bye");
} catch (Throwable t) {
t.printStackTrace();
}
}
}
CalendarWrapper.java
:
package app1;
import org.kie.api.time.Calendar;
import org.quartz.impl.calendar.WeeklyCalendar;
// A class to act as a converter from Quartz Calendar to Drools Calendar
public class CalendarWrapper implements Calendar {
private WeeklyCalendar cal;
public CalendarWrapper(WeeklyCalendar cal) {
this.cal = cal;
}
public boolean isTimeIncluded(long timestamp) {
return cal.isTimeIncluded(timestamp);
}
public static void main(String[] args) {
}
}
KSessionUtil.java
:
package app1;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.LinkedList;
import java.util.List;
import org.kie.api.KieBase;
import org.kie.api.KieBaseConfiguration;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.Message;
import org.kie.api.builder.Results;
import org.kie.api.conf.EqualityBehaviorOption;
import org.kie.api.conf.EventProcessingOption;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.KieSessionConfiguration;
import org.kie.api.runtime.conf.TimedRuleExectionOption;
import org.kie.api.runtime.rule.FactHandle;
public class KSessionUtil {
public static KieSession buildKSession(String ruleFilePath) {
List<String> ruleFilePathList = new LinkedList<String>();
ruleFilePathList.add(ruleFilePath);
return buildKSession(ruleFilePathList);
}
public static KieSession buildKSession(List<String> ruleFilePathList) {
final boolean showErrors = true;
final boolean showWarnings = true;
final boolean showInfo = true;
final boolean timedRuleOptionEnabled = false;
KieServices kieServices = KieServices.Factory.get();
KieFileSystem kfs = kieServices.newKieFileSystem();
String virtualRuleFilePathFormat = "src/main/resources/ruleFile%d.drl";
int virtualRuleFilePathIndex = 0;
for (String ruleFilePath : ruleFilePathList) {
virtualRuleFilePathIndex++;
FileInputStream fis = null;
try {
fis = new FileInputStream(ruleFilePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
String virtualRuleFilePath = String.format(virtualRuleFilePathFormat, virtualRuleFilePathIndex);
// System.out.println(virtualRuleFilePath);
kfs = kfs.write(virtualRuleFilePath, kieServices.getResources().newInputStreamResource(fis));
}
KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
Results results = kieBuilder.getResults();
if (showErrors && results.hasMessages(Message.Level.ERROR)) {
System.out.println("~~ERROR~~:");
System.out.println(results.getMessages());
throw new IllegalStateException("### errors ###");
}
if (showWarnings && results.hasMessages(Message.Level.WARNING)) {
System.out.println("~~WARNING~~:");
System.out.println(results.getMessages());
}
if (showInfo && results.hasMessages(Message.Level.INFO)) {
System.out.println("~~INFO~~:");
System.out.println(results.getMessages());
}
KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
// Change the engine mode to 'stream'
KieBaseConfiguration config = kieServices.newKieBaseConfiguration();
config.setOption(EventProcessingOption.STREAM);
config.setOption(EqualityBehaviorOption.EQUALITY);
KieBase kieBase = kieContainer.newKieBase(config);
KieSession kSession = null;
if (timedRuleOptionEnabled) {
// Set TimedRuleException to be true
// It will make fireAllRules() asynchronous ( like fireUntilHalt() )
// in the case of timed rules.
KieSessionConfiguration ksconf = KieServices.Factory.get().newKieSessionConfiguration();
ksconf.setOption(TimedRuleExectionOption.YES);
kSession = kieBase.newKieSession(ksconf, null);
} else {
kSession = kieBase.newKieSession();
}
return kSession;
}
public static Boolean updateOrInsert(KieSession kSession, Object obj) {
FactHandle factHandle = kSession.getFactHandle(obj);
if (factHandle == null) {
factHandle = kSession.insert(obj);
return false;
} else {
kSession.update(factHandle, obj);
return true;
}
}
public static void fireAllRules(KieSession kSession) {
System.out.println("Firing all rules ...");
kSession.fireAllRules();
System.out.println("Rules fired!");
}
}
ruleFile1.drl
:
package app1;
rule "rule1"
calendars "calendar"
when
str: String()
then
System.out.println("In rule - " + drools.getRule().getName());
System.out.println("String matched " + str);
end
初始化和设置日历所需的代码已写入java文件ClassCalendar.java
:
WeeklyCalendar weekDayCal = new WeeklyCalendar();
weekDayCal.setDaysExcluded(new boolean[] { false, false, false, false, false, false, false, false, false });
weekDayCal.setDayExcluded(java.util.Calendar.TUESDAY, true);
Calendar calendar = new CalendarWrapper(weekDayCal);
String ruleFilePath = "src/main/resources/rules/ruleFile1.drl";
KieSession kSession = KSessionUtil.buildKSession(ruleFilePath);
kSession.getCalendars().set("calendar", calendar);
有没有办法可以从规则本身做到这一切,所以我可以在java文件中执行此操作:
public static final void main(String[] args) {
try {
String ruleFilePath = "src/main/resources/rules/ruleFile1.drl";
KieSession kSession = KSessionUtil.buildKSession(ruleFilePath);
kSession.insert(new String("hello"));
kSession.fireAllRules();
System.out.println("Bye");
} catch (Throwable t) {
t.printStackTrace();
}
}
答案 0 :(得分:0)
在Drools中,日历的概念只不过是由日历属性选择为布尔值的时刻图,设置为规则的属性,允许规则触发。 Drools可以根据这样的日历评估当前的日期和时间,并允许或禁止触发规则。但它没有办法改变规则的编译属性。
您可以使用日历事实创建动态逻辑,该日历事实定义可以打开和关闭触发的间隔(&#34;计划&#34;,例如一天中的小时),插入定义计划的事实并使用规则修改这些计划事实。为了评估一组事实,需要根据当前时间评估计划事实,这必须作为另一个事实插入。
rule "determine time to..."
when
Now( $time: time )
Schedule( permitsAt( $time ) )
str: ThisOrThat()
then
//...
这将需要一定量的工作,但随后动态行为总是更加昂贵......; - )
编辑请注意,可以将一对现在加上一些计划放入单个规则中,该规则可以根据此特定计划应该有效的规则集进行扩展。
答案 1 :(得分:0)
我们可以在规则文件本身中编写日历初始化代码,并在规则的RHS中手动调用isTimeIncluded()
方法,以检查规则是否应该在当前时间执行:
package app1;
import java.util.Calendar;
import org.quartz.impl.calendar.WeeklyCalendar;
rule "rule1"
when
str: String()
then
System.out.println("In rule - " + drools.getRule().getName());
WeeklyCalendar weekDayCal = new WeeklyCalendar();
weekDayCal.setDaysExcluded(new boolean[] { false, false, false, false, false, false, false, false, false });
weekDayCal.setDayExcluded(java.util.Calendar.TUESDAY, true);
if ( weekDayCal.isTimeIncluded(System.currentTimeMillis()) )
{
System.out.println(str);
// Other things to do
}
end