[jboss-svn-commits] JBL Code SVN: r30429 - in labs/jbossrules/trunk: drools-compiler/src/main/java/org/drools/rule/builder and 9 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Wed Dec 2 00:00:54 EST 2009
Author: mark.proctor at jboss.com
Date: 2009-12-02 00:00:53 -0500 (Wed, 02 Dec 2009)
New Revision: 30429
Added:
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CompositeMaxDurationTimer.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CompositeMaxDurationTrigger.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CronTimer.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/DurationTimer.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/IntervalTimer.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/IntervalTrigger.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/Timer.java
Modified:
labs/jbossrules/trunk/drools-compiler/.classpath
labs/jbossrules/trunk/drools-compiler/.project
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/RuleBuilder.java
labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/CepEspTest.java
labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/ExecutionFlowControlTest.java
labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/rule/builder/dialect/java/RuleBuilderTest.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/Scheduler.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/process/instance/timer/TimerManager.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RuleTerminalNode.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/PatternBuilder.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Rule.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CronTrigger.java
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/AgendaTest.java
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/SchedulerTest.java
Log:
JBRULES-1944 Adding crontab type functionality for repetitive rules
-Add full working semantics with tests for cron and interval based timers
Modified: labs/jbossrules/trunk/drools-compiler/.classpath
===================================================================
--- labs/jbossrules/trunk/drools-compiler/.classpath 2009-12-01 20:57:44 UTC (rev 30428)
+++ labs/jbossrules/trunk/drools-compiler/.classpath 2009-12-02 05:00:53 UTC (rev 30429)
@@ -1,31 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry kind="src" path="src/main/java"/>
- <classpathentry kind="src" path="src/main/resources" excluding="**/*.java"/>
- <classpathentry kind="src" path="src/test/java" output="target/test-classes"/>
- <classpathentry kind="src" path="src/test/resources" output="target/test-classes" including="**" excluding="**/*.java"/>
- <classpathentry kind="output" path="target/classes"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="var" path="M2_REPO/antlr/antlr/2.7.7/antlr-2.7.7.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/antlr/antlr/3.1.1/antlr-3.1.1.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/antlr/antlr-runtime/3.1.1/antlr-runtime-3.1.1.jar"/>
- <classpathentry kind="var" path="M2_REPO/cglib/cglib-nodep/2.1_3/cglib-nodep-2.1_3.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/eclipse/jdt/core/3.4.2.v_883_R34x/core-3.4.2.v_883_R34x.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/drools/drools-api/5.1.0.SNAPSHOT/drools-api-5.1.0.SNAPSHOT.jar" sourcepath="M2_REPO/org/drools/drools-api/5.1.0.SNAPSHOT/drools-api-5.1.0.SNAPSHOT-sources.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/drools/drools-core/5.1.0.SNAPSHOT/drools-core-5.1.0.SNAPSHOT.jar" sourcepath="M2_REPO/org/drools/drools-core/5.1.0.SNAPSHOT/drools-core-5.1.0.SNAPSHOT-sources.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/hamcrest/hamcrest-core/1.1/hamcrest-core-1.1.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/hamcrest/hamcrest-library/1.1/hamcrest-library-1.1.jar"/>
- <classpathentry kind="var" path="M2_REPO/janino/janino/2.5.15/janino-2.5.15.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/mortbay/jetty/jetty/6.1.15/jetty-6.1.15.jar" sourcepath="M2_REPO/org/mortbay/jetty/jetty/6.1.15/jetty-6.1.15-sources.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/mortbay/jetty/jetty-embedded/6.1.15/jetty-embedded-6.1.15.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/mortbay/jetty/jetty-util/6.1.15/jetty-util-6.1.15.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/jmock/jmock/2.5.1/jmock-2.5.1.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/jmock/jmock-legacy/2.5.1/jmock-legacy-2.5.1.jar"/>
- <classpathentry kind="var" path="M2_REPO/joda-time/joda-time/1.6/joda-time-1.6.jar"/>
- <classpathentry kind="var" path="M2_REPO/javax/servlet/jsp/jsp-api/2.1/jsp-api-2.1.jar"/>
- <classpathentry kind="var" path="M2_REPO/junit/junit/4.6/junit-4.6.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/mvel/mvel2/2.0.12/mvel2-2.0.12.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/objenesis/objenesis/1.0/objenesis-1.0.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/mortbay/jetty/servlet-api/2.5-20081211/servlet-api-2.5-20081211.jar"/>
- <classpathentry kind="var" path="M2_REPO/xpp3/xpp3_min/1.1.4c/xpp3_min-1.1.4c.jar"/>
- <classpathentry kind="var" path="M2_REPO/com/thoughtworks/xstream/xstream/1.3.1/xstream-1.3.1.jar"/>
-</classpath>
\ No newline at end of file
+ <classpathentry kind="src" path="src/main/java"/>
+ <classpathentry excluding="**/*.java" kind="src" path="src/main/resources"/>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+ <classpathentry excluding="**/*.java" including="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="var" path="M2_REPO/antlr/antlr/2.7.7/antlr-2.7.7.jar"/>
+ <classpathentry kind="var" path="M2_REPO/org/antlr/antlr/3.1.1/antlr-3.1.1.jar"/>
+ <classpathentry kind="var" path="M2_REPO/org/antlr/antlr-runtime/3.1.1/antlr-runtime-3.1.1.jar"/>
+ <classpathentry kind="var" path="M2_REPO/cglib/cglib-nodep/2.1_3/cglib-nodep-2.1_3.jar"/>
+ <classpathentry kind="var" path="M2_REPO/org/eclipse/jdt/core/3.4.2.v_883_R34x/core-3.4.2.v_883_R34x.jar"/>
+ <classpathentry kind="src" path="/drools-api"/>
+ <classpathentry kind="src" path="/drools-core"/>
+ <classpathentry kind="var" path="M2_REPO/org/hamcrest/hamcrest-core/1.1/hamcrest-core-1.1.jar"/>
+ <classpathentry kind="var" path="M2_REPO/org/hamcrest/hamcrest-library/1.1/hamcrest-library-1.1.jar"/>
+ <classpathentry kind="var" path="M2_REPO/janino/janino/2.5.15/janino-2.5.15.jar"/>
+ <classpathentry kind="var" path="M2_REPO/org/mortbay/jetty/jetty/6.1.15/jetty-6.1.15.jar" sourcepath="M2_REPO/org/mortbay/jetty/jetty/6.1.15/jetty-6.1.15-sources.jar"/>
+ <classpathentry kind="var" path="M2_REPO/org/mortbay/jetty/jetty-embedded/6.1.15/jetty-embedded-6.1.15.jar"/>
+ <classpathentry kind="var" path="M2_REPO/org/mortbay/jetty/jetty-util/6.1.15/jetty-util-6.1.15.jar"/>
+ <classpathentry kind="var" path="M2_REPO/org/jmock/jmock/2.5.1/jmock-2.5.1.jar"/>
+ <classpathentry kind="var" path="M2_REPO/org/jmock/jmock-legacy/2.5.1/jmock-legacy-2.5.1.jar"/>
+ <classpathentry kind="var" path="M2_REPO/joda-time/joda-time/1.6/joda-time-1.6.jar"/>
+ <classpathentry kind="var" path="M2_REPO/javax/servlet/jsp/jsp-api/2.1/jsp-api-2.1.jar"/>
+ <classpathentry kind="var" path="M2_REPO/junit/junit/4.6/junit-4.6.jar"/>
+ <classpathentry kind="var" path="M2_REPO/org/mvel/mvel2/2.0.12/mvel2-2.0.12.jar"/>
+ <classpathentry kind="var" path="M2_REPO/org/objenesis/objenesis/1.0/objenesis-1.0.jar"/>
+ <classpathentry kind="var" path="M2_REPO/org/mortbay/jetty/servlet-api/2.5-20081211/servlet-api-2.5-20081211.jar"/>
+ <classpathentry kind="var" path="M2_REPO/xpp3/xpp3_min/1.1.4c/xpp3_min-1.1.4c.jar"/>
+ <classpathentry kind="var" path="M2_REPO/com/thoughtworks/xstream/xstream/1.3.1/xstream-1.3.1.jar" sourcepath="M2_REPO/com/thoughtworks/xstream/xstream/1.3.1/xstream-1.3.1-sources.jar"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
Modified: labs/jbossrules/trunk/drools-compiler/.project
===================================================================
--- labs/jbossrules/trunk/drools-compiler/.project 2009-12-01 20:57:44 UTC (rev 30428)
+++ labs/jbossrules/trunk/drools-compiler/.project 2009-12-02 05:00:53 UTC (rev 30429)
@@ -1,7 +1,10 @@
<projectDescription>
<name>drools-compiler</name>
<comment>A rule production system</comment>
- <projects/>
+ <projects>
+ <project>drools-api</project>
+ <project>drools-core</project>
+ </projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
Modified: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/RuleBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/RuleBuilder.java 2009-12-01 20:57:44 UTC (rev 30428)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/RuleBuilder.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -16,6 +16,7 @@
* limitations under the License.
*/
+import java.text.ParseException;
import java.util.Calendar;
import org.drools.RuntimeDroolsException;
@@ -29,6 +30,10 @@
import org.drools.rule.Rule;
import org.drools.spi.Salience;
import org.drools.time.TimeUtils;
+import org.drools.time.impl.CronExpression;
+import org.drools.time.impl.CronTimer;
+import org.drools.time.impl.IntervalTimer;
+import org.drools.time.impl.Timer;
import org.drools.util.DateUtils;
/**
@@ -111,10 +116,7 @@
true ) );
} else if ( name.equals( "duration" ) ) {
String duration = attributeDescr.getValue();
- if( duration.indexOf( '(' ) >=0 ) {
- duration = duration.substring( duration.indexOf( '(' )+1, duration.lastIndexOf( ')' ) );
- }
- rule.setDuration( TimeUtils.parseTimeString( duration ) );
+ buildTimer( rule, duration, context);
} else if ( name.equals( "date-effective" ) ) {
final Calendar cal = Calendar.getInstance();
cal.setTime( DateUtils.parseDate( attributeDescr.getValue() ) );
@@ -180,5 +182,53 @@
}
}
}
+
+ private void buildTimer(Rule rule, String timerString, RuleBuildContext context) {
+ if( timerString.indexOf( '(' ) >=0 ) {
+ timerString = timerString.substring( timerString.indexOf( '(' )+1, timerString.lastIndexOf( ')' ) );
+ }
+
+ int colonPos = timerString.indexOf( ":" );
+ String protocol = null;
+ if ( colonPos == -1 ) {
+ // no protocol so assume interval semantics
+ protocol = "int";
+ } else {
+ protocol = timerString.substring( 0, colonPos );
+ }
+
+ String body = timerString.substring( colonPos + 1 );
+
+ Timer timer = null;
+ if ( "cron".equals( protocol ) ) {
+ try {
+ timer = new CronTimer( null, null, new CronExpression( body ) );
+ } catch ( ParseException e ) {
+ context.getErrors().add( "Unable to build set timer '" + timerString + "'");
+ return;
+ }
+ } else if ( "int".equals( protocol ) ) {
+ String[] times = body.trim().split( "\\s" );
+ long delay = 0;
+ long period = 0;
+ if ( times.length == 1 ) {
+ // only defines a delay
+ delay = TimeUtils.parseTimeString( times[0] );
+ } else if ( times.length == 2 ) {
+ // defines a delay and a period for intervals
+ delay = TimeUtils.parseTimeString( times[0] );
+ period = TimeUtils.parseTimeString( times[1] );
+ } else {
+ context.getErrors().add( "Incorrect number of arguments for interval timer '" + timerString + "'");
+ return;
+ }
+ timer = new IntervalTimer(null, null, delay, period);
+ //rule.setDuration( TimeUtils.parseTimeString( duration ) );
+ } else {
+ context.getErrors().add( "Protocol for timer does not exist '" + timerString +"'");
+ return;
+ }
+ rule.setTimer( timer );
+ }
}
\ No newline at end of file
Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/CepEspTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/CepEspTest.java 2009-12-01 20:57:44 UTC (rev 30428)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/CepEspTest.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -47,6 +47,7 @@
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.conf.ClockTypeOption;
import org.drools.time.SessionPseudoClock;
+import org.drools.time.impl.DurationTimer;
import org.drools.time.impl.PseudoClockScheduler;
import org.drools.util.DroolsStreamUtils;
@@ -984,7 +985,7 @@
final Rule rule = ruleBase.getPackage( "org.drools" ).getRule( "Delaying Not" );
assertEquals( 10000,
- rule.getDuration().getDuration( null ) );
+ ((DurationTimer)rule.getTimer()).getDuration() );
SessionConfiguration conf = new SessionConfiguration();
conf.setClockType( ClockType.PSEUDO_CLOCK );
Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/ExecutionFlowControlTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/ExecutionFlowControlTest.java 2009-12-01 20:57:44 UTC (rev 30428)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/ExecutionFlowControlTest.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -4,8 +4,12 @@
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import junit.framework.Assert;
import junit.framework.TestCase;
@@ -13,6 +17,7 @@
import org.drools.Alarm;
import org.drools.Cell;
import org.drools.Cheese;
+import org.drools.ClockType;
import org.drools.FactHandle;
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
@@ -35,19 +40,29 @@
import org.drools.compiler.DroolsParserException;
import org.drools.compiler.PackageBuilder;
import org.drools.compiler.PackageBuilder.PackageMergeException;
+import org.drools.conf.Option;
import org.drools.event.ActivationCancelledEvent;
import org.drools.event.ActivationCreatedEvent;
import org.drools.event.AgendaEventListener;
import org.drools.event.DefaultAgendaEventListener;
+import org.drools.integrationtests.eventgenerator.PseudoSessionClock;
import org.drools.io.ResourceFactory;
import org.drools.lang.descr.PackageDescr;
import org.drools.process.instance.ProcessInstance;
import org.drools.rule.Package;
+import org.drools.runtime.KnowledgeSessionConfiguration;
import org.drools.runtime.StatefulKnowledgeSession;
+import org.drools.runtime.conf.ClockTypeOption;
import org.drools.spi.Activation;
import org.drools.spi.ActivationGroup;
import org.drools.spi.AgendaGroup;
+import org.drools.time.impl.CronTrigger;
+import org.drools.time.impl.PseudoClockScheduler;
+import org.drools.time.impl.JDKTimerServiceTest.HelloWorldJob;
+import org.drools.time.impl.JDKTimerServiceTest.HelloWorldJobContext;
+import sun.net.dns.ResolverConfiguration.Options;
+
public class ExecutionFlowControlTest extends TestCase {
protected RuleBase getRuleBase() throws Exception {
@@ -843,7 +858,177 @@
assertEquals( 0,
session.getAgenda().getScheduledActivations().length );
}
+
+ public void testNoProtocolIntervalTimer() throws Exception {
+ String str = "";
+ str += "package org.simple \n";
+ str += "global java.util.List list \n";
+ str += "rule xxx \n";
+ str += " duration (30s 10s) ";
+ str += "when \n";
+ str += "then \n";
+ str += " list.add(\"fired\"); \n";
+ str += "end \n";
+ KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+ kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ),
+ ResourceType.DRL );
+
+ if ( kbuilder.hasErrors() ) {
+ System.out.println( kbuilder.getErrors() );
+ assertTrue( kbuilder.hasErrors() );
+ }
+
+ KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
+ kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
+
+ KnowledgeSessionConfiguration conf = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
+ conf.setOption( ClockTypeOption.get( "pseudo" ) );
+
+ List list = new ArrayList();
+ StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession( conf, null );
+ PseudoClockScheduler timeService = ( PseudoClockScheduler ) ksession.getSessionClock();
+ timeService.advanceTime( new Date().getTime(), TimeUnit.MILLISECONDS );
+
+ ksession.setGlobal( "list", list );
+
+ ksession.fireAllRules();
+ assertEquals( 0, list.size() );
+
+ timeService.advanceTime( 20, TimeUnit.SECONDS );
+ ksession.fireAllRules();
+ assertEquals( 0, list.size() );
+
+ timeService.advanceTime( 15, TimeUnit.SECONDS );
+ ksession.fireAllRules();
+ assertEquals( 1, list.size() );
+
+ timeService.advanceTime( 3, TimeUnit.SECONDS );
+ ksession.fireAllRules();
+ assertEquals( 1, list.size() );
+
+ timeService.advanceTime( 2, TimeUnit.SECONDS );
+ ksession.fireAllRules();
+ assertEquals( 2, list.size() );
+
+ timeService.advanceTime( 10, TimeUnit.SECONDS );
+ ksession.fireAllRules();
+ assertEquals( 3, list.size() );
+ }
+
+ public void testIntervalTimer() throws Exception {
+ String str = "";
+ str += "package org.simple \n";
+ str += "global java.util.List list \n";
+ str += "rule xxx \n";
+ str += " duration (int:30s 10s) ";
+ str += "when \n";
+ str += "then \n";
+ str += " list.add(\"fired\"); \n";
+ str += "end \n";
+
+ KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+ kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ),
+ ResourceType.DRL );
+
+ if ( kbuilder.hasErrors() ) {
+ System.out.println( kbuilder.getErrors() );
+ assertTrue( kbuilder.hasErrors() );
+ }
+
+ KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
+ kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
+
+ KnowledgeSessionConfiguration conf = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
+ conf.setOption( ClockTypeOption.get( "pseudo" ) );
+
+ List list = new ArrayList();
+ StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession( conf, null );
+ PseudoClockScheduler timeService = ( PseudoClockScheduler ) ksession.getSessionClock();
+ timeService.advanceTime( new Date().getTime(), TimeUnit.MILLISECONDS );
+
+ ksession.setGlobal( "list", list );
+
+ ksession.fireAllRules();
+ assertEquals( 0, list.size() );
+
+ timeService.advanceTime( 20, TimeUnit.SECONDS );
+ ksession.fireAllRules();
+ assertEquals( 0, list.size() );
+
+ timeService.advanceTime( 15, TimeUnit.SECONDS );
+ ksession.fireAllRules();
+ assertEquals( 1, list.size() );
+
+ timeService.advanceTime( 3, TimeUnit.SECONDS );
+ ksession.fireAllRules();
+ assertEquals( 1, list.size() );
+
+ timeService.advanceTime( 2, TimeUnit.SECONDS );
+ ksession.fireAllRules();
+ assertEquals( 2, list.size() );
+
+ timeService.advanceTime( 10, TimeUnit.SECONDS );
+ ksession.fireAllRules();
+ assertEquals( 3, list.size() );
+ }
+
+ public void testCronTimer() throws Exception {
+ String str = "";
+ str += "package org.simple \n";
+ str += "global java.util.List list \n";
+ str += "rule xxx \n";
+ str += " duration (cron:15 * * * * ?) ";
+ str += "when \n";
+ str += "then \n";
+ str += " list.add(\"fired\"); \n";
+ str += "end \n";
+
+ KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+ kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ),
+ ResourceType.DRL );
+
+ if ( kbuilder.hasErrors() ) {
+ System.out.println( kbuilder.getErrors() );
+ assertTrue( kbuilder.hasErrors() );
+ }
+
+ KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
+ kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
+
+ KnowledgeSessionConfiguration conf = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
+ conf.setOption( ClockTypeOption.get( "pseudo" ) );
+
+ List list = new ArrayList();
+ StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession( conf, null );
+ PseudoClockScheduler timeService = ( PseudoClockScheduler ) ksession.getSessionClock();
+ DateFormat df = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss.SSSZ" );
+ Date date = df.parse( "2009-01-01T00:00:00.000-0000" );
+
+ timeService.advanceTime( date.getTime(), TimeUnit.MILLISECONDS );
+
+ ksession.setGlobal( "list", list );
+
+ ksession.fireAllRules();
+ assertEquals( 0, list.size() );
+
+ timeService.advanceTime( 10, TimeUnit.SECONDS );
+ ksession.fireAllRules();
+ assertEquals( 0, list.size() );
+
+ timeService.advanceTime( 10, TimeUnit.SECONDS );
+ ksession.fireAllRules();
+ assertEquals( 1, list.size() );
+
+ timeService.advanceTime( 30, TimeUnit.SECONDS );
+ ksession.fireAllRules();
+ assertEquals( 1, list.size() );
+
+ timeService.advanceTime( 30, TimeUnit.SECONDS );
+ ksession.fireAllRules();
+ assertEquals( 2, list.size() );
+ }
+
public void testFireRuleAfterDuration() throws Exception {
final PackageBuilder builder = new PackageBuilder();
builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_FireRuleAfterDuration.drl" ) ) );
Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/rule/builder/dialect/java/RuleBuilderTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/rule/builder/dialect/java/RuleBuilderTest.java 2009-12-01 20:57:44 UTC (rev 30428)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/rule/builder/dialect/java/RuleBuilderTest.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -50,6 +50,8 @@
import org.drools.rule.builder.RuleBuildContext;
import org.drools.rule.builder.RuleBuilder;
import org.drools.time.TimeUtils;
+import org.drools.time.impl.DurationTimer;
+import org.drools.time.impl.IntervalTimer;
import org.drools.util.DateUtils;
import org.jmock.Expectations;
import org.jmock.Mockery;
@@ -202,7 +204,7 @@
oneOf( rule ).setRuleFlowGroup( "mygroup" );
oneOf( rule ).setLockOnActive( true );
oneOf( rule ).setEnabled( EnabledBoolean.ENABLED_FALSE );
- oneOf( rule ).setDuration( 60 );
+ oneOf( rule ).setTimer( new IntervalTimer( null , null, TimeUtils.parseTimeString( "60" ), 0 ) );
oneOf( rule ).setDateEffective( effective );
oneOf( rule ).setDateExpires( expires );
}
@@ -235,7 +237,7 @@
allowing( context ).getRuleDescr(); will( returnValue( ruleDescr ) );
// expected values for the rule object
- oneOf( rule ).setDuration( TimeUtils.parseTimeString( "1h30m" ) );
+ oneOf( rule ).setTimer( new IntervalTimer( null , null, TimeUtils.parseTimeString( "1h30m" ), 0 ) );
}
} );
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/Scheduler.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/Scheduler.java 2009-12-01 20:57:44 UTC (rev 30428)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/Scheduler.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -17,7 +17,6 @@
*/
import org.drools.Agenda;
-import org.drools.process.instance.timer.TimerManager.TimerTrigger;
import org.drools.time.Job;
import org.drools.time.JobContext;
import org.drools.time.JobHandle;
@@ -48,12 +47,11 @@
* The working memory session.
*/
public static void scheduleAgendaItem(final ScheduledAgendaItem item, InternalAgenda agenda) {
- DuractionJob job = new DuractionJob();
- DuractionJobContext ctx = new DuractionJobContext( item, agenda );
- Trigger trigger = new PointInTimeTrigger( item.getRule().getDuration().getDuration( item.getTuple() ) +
- ((InternalWorkingMemory)agenda.getWorkingMemory()).getTimerService().getCurrentTime());
+ Trigger trigger = item.getRule().getTimer().createTrigger( ((InternalWorkingMemory)agenda.getWorkingMemory()).getTimerService().getCurrentTime() );
-
+ ActivationTimerJob job = new ActivationTimerJob();
+ ActivationTimerJobContext ctx = new ActivationTimerJobContext( trigger, item, agenda );
+
JobHandle jobHandle = ((InternalWorkingMemory)agenda.getWorkingMemory()).getTimerService().scheduleJob( job, ctx, trigger );
item.setJobHandle( jobHandle );
}
@@ -62,31 +60,32 @@
((InternalWorkingMemory)agenda.getWorkingMemory()).getTimerService().removeJob( item.getJobHandle() );
}
- public static class DuractionJob implements Job {
+ public static class ActivationTimerJob implements Job {
public void execute(JobContext ctx) {
- InternalAgenda agenda = ( InternalAgenda ) ((DuractionJobContext)ctx).getAgenda();
- ScheduledAgendaItem item = ((DuractionJobContext)ctx).getScheduledAgendaItem();
+ InternalAgenda agenda = ( InternalAgenda ) ((ActivationTimerJobContext)ctx).getAgenda();
+ ScheduledAgendaItem item = ((ActivationTimerJobContext)ctx).getScheduledAgendaItem();
agenda.fireActivation( item );
- agenda.getScheduledActivationsLinkedList().remove( item );
+ if ( ((ActivationTimerJobContext)ctx).getTrigger().hasNextFireTime() == null ) {
+ agenda.getScheduledActivationsLinkedList().remove( item );
+ }
agenda.getWorkingMemory().fireAllRules();
}
}
- public static class DuractionJobContext implements JobContext {
+ public static class ActivationTimerJobContext implements JobContext {
private JobHandle jobHandle;
private ScheduledAgendaItem scheduledAgendaItem;
- private Agenda agenda;
+ private Agenda agenda;
+ private Trigger trigger;
- public DuractionJobContext(ScheduledAgendaItem scheduledAgendaItem,
+ public ActivationTimerJobContext(Trigger trigger,
+ ScheduledAgendaItem scheduledAgendaItem,
Agenda agenda) {
+ this.trigger = trigger;
this.scheduledAgendaItem = scheduledAgendaItem;
this.agenda = agenda;
}
-
- public DuractionJobContext(ScheduledAgendaItem scheduledAgendaItem) {
- this.scheduledAgendaItem = scheduledAgendaItem;
- }
public Agenda getAgenda() {
return this.agenda;
@@ -102,6 +101,10 @@
public void setJobHandle(JobHandle jobHandle) {
this.jobHandle = jobHandle;
+ }
+
+ public Trigger getTrigger() {
+ return trigger;
}
}
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/process/instance/timer/TimerManager.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/process/instance/timer/TimerManager.java 2009-12-01 20:57:44 UTC (rev 30428)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/process/instance/timer/TimerManager.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -1,8 +1,5 @@
package org.drools.process.instance.timer;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
@@ -14,7 +11,7 @@
import org.drools.time.JobContext;
import org.drools.time.JobHandle;
import org.drools.time.TimerService;
-import org.drools.time.Trigger;
+import org.drools.time.impl.IntervalTrigger;
/**
*
@@ -45,7 +42,7 @@
JobHandle jobHandle = this.timerService.scheduleJob( processJob,
ctx,
- new TimerTrigger( timerService.getCurrentTime(),
+ new IntervalTrigger( timerService.getCurrentTime(),
timer.getDelay(),
timer.getPeriod() ) );
timer.setJobHandle( jobHandle );
@@ -75,7 +72,7 @@
}
}
JobHandle jobHandle = this.timerService.scheduleJob(
- processJob, ctx, new TimerTrigger(timerService.getCurrentTime(),
+ processJob, ctx, new IntervalTrigger(timerService.getCurrentTime(),
delay,
timer.getPeriod()));
timer.setJobHandle(jobHandle);
@@ -139,51 +136,6 @@
}
- public static class TimerTrigger
- implements
- Trigger {
- private Date next;
- private long period;
-
- public TimerTrigger() {
-
- }
-
- public TimerTrigger(long currentTS,
- long delay,
- long period) {
- this.next = new Date( currentTS + delay );
- this.period = period;
- }
-
- public Date hasNextFireTime() {
- return next;
- }
-
- public Date nextFireTime() {
- Date date = next;
- if ( this.period != 0 ) {
- // repeated fires for the given period
- // FIXME: this is not safe for serialization
- next = new Date( next.getTime() + this.period );
- } else {
- next = null;
- }
- return date;
- }
-
- public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
- this.next = (Date) in.readObject();
- this.period = in.readLong();
- }
-
- public void writeExternal(ObjectOutput out) throws IOException {
- out.writeObject( this.next );
- out.writeLong( this.period );
- }
-
- }
-
public static class ProcessJobContext
implements
JobContext {
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RuleTerminalNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RuleTerminalNode.java 2009-12-01 20:57:44 UTC (rev 30428)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RuleTerminalNode.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -39,6 +39,7 @@
import org.drools.spi.Activation;
import org.drools.spi.Duration;
import org.drools.spi.PropagationContext;
+import org.drools.time.impl.Timer;
import org.drools.util.Iterator;
import org.drools.util.LeftTupleList;
@@ -200,10 +201,10 @@
}
final InternalAgenda agenda = (InternalAgenda) workingMemory.getAgenda();
+
+ final Timer timer = this.rule.getTimer();
- final Duration dur = this.rule.getDuration();
-
- if ( dur != null && dur.getDuration( tuple ) > 0 ) {
+ if ( timer != null ) {
final ScheduledAgendaItem item = agenda.createScheduledAgendaItem( tuple,
context,
this.rule,
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/PatternBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/PatternBuilder.java 2009-12-01 20:57:44 UTC (rev 30428)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/PatternBuilder.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -48,6 +48,9 @@
import org.drools.spi.Constraint;
import org.drools.spi.Duration;
import org.drools.spi.ObjectType;
+import org.drools.time.impl.CompositeMaxDurationTimer;
+import org.drools.time.impl.DurationTimer;
+import org.drools.time.impl.Timer;
/**
* A builder for patterns
@@ -181,18 +184,32 @@
Declaration target = constraint.getRequiredDeclarations()[0];
if( target.isPatternDeclaration() && target.getPattern().getObjectType().isEvent() ) {
long uplimit = ((VariableConstraint) constraint).getInterval().getUpperBound();
- Duration dur = context.getRule().getDuration();
- Duration newDur = new FixedDuration( uplimit );
- if( dur instanceof CompositeMaxDuration ) {
- ((CompositeMaxDuration)dur).addDuration( newDur );
+
+ Timer timer = context.getRule().getTimer();
+ DurationTimer durationTimer = new DurationTimer(uplimit);
+
+ if ( timer instanceof CompositeMaxDurationTimer ) {
+ // already a composite so just add
+ ((CompositeMaxDurationTimer)timer).addDurationTimer( durationTimer );
} else {
- if( dur == null ) {
- dur = newDur;
+ if ( timer == null ) {
+ // no timer exists, so ok on it's own
+ timer = durationTimer;
} else {
- dur = new CompositeMaxDuration( dur );
- ((CompositeMaxDuration)dur).addDuration( newDur );
+ // timer exists so we need to make a composite
+ timer = new CompositeMaxDurationTimer();
+ if ( timer instanceof DurationTimer ) {
+ // previous timer was a duration, so add another DurationTimer
+ ((CompositeMaxDurationTimer)timer).addDurationTimer( ( DurationTimer ) timer );
+ } else {
+ // previous timer was not a duration, so set it as the delegate Timer.
+ ((CompositeMaxDurationTimer)timer).setTimer( context.getRule().getTimer() );
+ }
+ // now add the new durationTimer
+ ((CompositeMaxDurationTimer)timer).addDurationTimer( durationTimer );
}
- context.getRule().setDuration( dur );
+ // with the composite made, reset it on the Rule
+ context.getRule().setTimer( timer );
}
}
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Rule.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Rule.java 2009-12-01 20:57:44 UTC (rev 30428)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Rule.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -38,6 +38,7 @@
import org.drools.spi.Salience;
import org.drools.spi.Tuple;
import org.drools.spi.Wireable;
+import org.drools.time.impl.Timer;
/**
* A <code>Rule</code> contains a set of <code>Test</code>s and a
@@ -93,10 +94,10 @@
/** Consequence. */
private Consequence consequence;
+
+ /** Timer semantics that controls the firing of a rule */
+ private Timer timer;
- /** Truthness duration. */
- private Duration duration;
-
/** Load order in Package */
private long loadOrder;
@@ -143,7 +144,7 @@
} else {
out.writeObject(this.consequence);
}
- out.writeObject(duration);
+ out.writeObject(timer);
out.writeLong(loadOrder);
out.writeBoolean(noLoop);
out.writeBoolean(autoFocus);
@@ -173,7 +174,7 @@
metaAttributes = (Map<String,String>)in.readObject();
consequence = (Consequence)in.readObject();
- duration = (Duration)in.readObject();
+ timer = (Timer)in.readObject();
loadOrder = in.readLong();
noLoop = in.readBoolean();
autoFocus = in.readBoolean();
@@ -255,48 +256,24 @@
}
/**
- * Set the truthness duration. This causes a delay before the firing of the
- * <code>Consequence</code> if the rule is still true at the end of the
- * duration.
- *
- * <p>
- * This is merely a convenience method for calling
- * {@link #setDuration(Duration)}with a <code>FixedDuration</code>.
- * </p>
- *
- * @see #setDuration(Duration)
- * @see FixedDuration
- *
- * @param seconds -
- * The number of seconds the rule must hold true in order to
- * fire.
+ * Returns the Timer semantics for a rule. Timer based rules are not added directly to the Agenda
+ * instead they are scheduled for Agenda addition, based on the timer.
+ * @return
*/
- public void setDuration(final long ms) {
- this.duration = new FixedDuration( ms );
+ public Timer getTimer() {
+ return timer;
}
/**
- * Set the truthness duration object. This causes a delay before the firing
- * of the <code>Consequence</code> if the rule is still true at the end of
- * the duration.
- *
- * @param duration
- * The truth duration object.
+ * Sets the timer semantics for a rule. Timer based rules are not added directly to the Agenda
+ * instead they are scheduled for Agenda addition, based on the timer.
+ * @param timer
*/
- public void setDuration(final Duration duration) {
- this.duration = duration;
+ public void setTimer(Timer timer) {
+ this.timer = timer;
}
/**
- * Retrieve the truthness duration object.
- *
- * @return The truthness duration object.
- */
- public Duration getDuration() {
- return this.duration;
- }
-
- /**
* Determine if this rule is internally consistent and valid.
* This will include checks to make sure the rules semantic components (actions and predicates)
* are valid.
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CompositeMaxDurationTimer.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CompositeMaxDurationTimer.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CompositeMaxDurationTimer.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -0,0 +1,51 @@
+package org.drools.time.impl;
+
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.drools.time.Trigger;
+
+/**
+ * While a rule might have multiple DurationTimers, due to LHS CEP rules, there can only ever
+ * be one timer attribute. Duration rules should be considered a priority over the one timer rule.
+ * So the Timer cannot fire, until the maximum duration has passed.
+ *
+ */
+public class CompositeMaxDurationTimer
+ implements
+ Timer {
+
+ private List<DurationTimer> durations;
+
+ private Timer timer;
+
+ public CompositeMaxDurationTimer() {
+
+ }
+
+ public void addDurationTimer(final DurationTimer durationTimer) {
+ if ( this.durations == null ) {
+ this.durations = new LinkedList<DurationTimer>();
+ }
+ this.durations.add( durationTimer );
+ }
+
+ public void setTimer(Timer timer) {
+ this.timer = timer;
+ }
+
+ public Trigger createTrigger(long timestamp) {
+ return new CompositeMaxDurationTrigger( new Date( getMaxDuration() + timestamp ),
+ timer.createTrigger( timestamp ) );
+ }
+
+ private long getMaxDuration() {
+ long result = 0;
+ for ( DurationTimer durationTimer : durations ) {
+ result = Math.max( result,
+ durationTimer.getDuration() );
+ }
+ return result;
+ }
+}
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CompositeMaxDurationTrigger.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CompositeMaxDurationTrigger.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CompositeMaxDurationTrigger.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -0,0 +1,37 @@
+package org.drools.time.impl;
+
+import java.util.Date;
+
+import org.drools.time.Trigger;
+
+public class CompositeMaxDurationTrigger
+ implements
+ Trigger {
+ private Trigger trigger;
+ private Date timestamp;
+
+ public CompositeMaxDurationTrigger(Date timestamp, // this is the first duration that takes priority
+ Trigger trigger) {
+ this.timestamp = timestamp;
+ this.trigger = trigger;
+ }
+
+ public Date hasNextFireTime() {
+ if ( this.timestamp != null ) {
+ return this.timestamp;
+ } else {
+ return this.trigger.hasNextFireTime();
+ }
+ }
+
+ public Date nextFireTime() {
+ if ( this.timestamp != null ) {
+ Date next = this.timestamp;
+ this.timestamp = null;
+ return next;
+ } else {
+ return trigger.nextFireTime();
+ }
+ }
+
+}
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CronTimer.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CronTimer.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CronTimer.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -0,0 +1,98 @@
+package org.drools.time.impl;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.text.ParseException;
+import java.util.Date;
+
+import org.drools.time.Trigger;
+
+public class CronTimer
+ implements
+ Timer,
+ Externalizable {
+ private Date startTime;
+ private Date endTime;
+ private CronExpression cronExpression;
+
+ public CronTimer() {
+
+ }
+
+ public CronTimer(Date startTime,
+ Date endTime,
+ CronExpression cronExpression) {
+ this.startTime = startTime;
+ this.endTime = endTime;
+ this.cronExpression = cronExpression;
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeObject( startTime );
+ out.writeObject( endTime );
+ out.writeObject( cronExpression.getCronExpression() );
+ }
+
+ public void readExternal(ObjectInput in) throws IOException,
+ ClassNotFoundException {
+ this.startTime = (Date) in.readObject();
+ this.endTime = (Date) in.readObject();
+ String string = (String) in.readObject();
+ try {
+ this.cronExpression = new CronExpression( string );
+ } catch ( ParseException e ) {
+ throw new RuntimeException( "Unable to marshal CronExpression '" + string + "'",
+ e );
+ }
+ }
+
+ public Date getStartTime() {
+ return startTime;
+ }
+
+ public Date getEndTime() {
+ return endTime;
+ }
+
+ public CronExpression getCronExpression() {
+ return cronExpression;
+ }
+
+ public Trigger createTrigger(long timestamp) {
+ return new CronTrigger( timestamp,
+ this.startTime,
+ this.endTime,
+ this.cronExpression );
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((cronExpression.getCronExpression() == null) ? 0 : cronExpression.getCronExpression().hashCode());
+ result = prime * result + ((endTime == null) ? 0 : endTime.hashCode());
+ result = prime * result + ((startTime == null) ? 0 : startTime.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if ( this == obj ) return true;
+ if ( obj == null ) return false;
+ if ( getClass() != obj.getClass() ) return false;
+ CronTimer other = (CronTimer) obj;
+ if ( cronExpression.getCronExpression() == null ) {
+ if ( other.cronExpression.getCronExpression() != null ) return false;
+ } else if ( !cronExpression.getCronExpression().equals( other.cronExpression.getCronExpression() ) ) return false;
+ if ( endTime == null ) {
+ if ( other.endTime != null ) return false;
+ } else if ( !endTime.equals( other.endTime ) ) return false;
+ if ( startTime == null ) {
+ if ( other.startTime != null ) return false;
+ } else if ( !startTime.equals( other.startTime ) ) return false;
+ return true;
+ }
+
+}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CronTrigger.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CronTrigger.java 2009-12-01 20:57:44 UTC (rev 30428)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CronTrigger.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -18,7 +18,12 @@
private Date previousFireTime = null;
private transient TimeZone timeZone = null;
+
public CronTrigger(long timestamp, Date startTime, Date endTime, String cronExpression) {
+ this( timestamp, startTime, endTime, determineCronExpression( cronExpression ));
+ }
+
+ public CronTrigger(long timestamp, Date startTime, Date endTime, CronExpression cronExpression) {
setCronExpression(cronExpression);
if (startTime == null) {
@@ -30,7 +35,7 @@
}
setTimeZone(TimeZone.getDefault());
- this.nextFireTime = getFireTimeAfter(new Date(getStartTime().getTime() - 1000l));
+ this.nextFireTime = getFireTimeAfter(new Date(getStartTime().getTime() - 1000l));
}
public Date getStartTime() {
@@ -172,14 +177,22 @@
}
public void setCronExpression(String cronExpression) {
- try {
+ setCronExpression( determineCronExpression(cronExpression) );
+ }
+
+ public void setCronExpression(CronExpression cronExpression) {
TimeZone origTz = getTimeZone();
- this.cronEx = new CronExpression(cronExpression);
+ this.cronEx = cronExpression;
this.cronEx.setTimeZone(origTz);
+ }
+
+ public static CronExpression determineCronExpression(String cronExpression) {
+ try {
+ return new CronExpression(cronExpression);
} catch ( Exception e ) {
throw new RuntimeException("Unable to parse cron expression '" + cronExpression + "'", e);
- }
- }
+ }
+ }
public Date hasNextFireTime() {
return this.nextFireTime;
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/DurationTimer.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/DurationTimer.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/DurationTimer.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -0,0 +1,59 @@
+package org.drools.time.impl;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+import org.drools.time.Trigger;
+
+public class DurationTimer
+ implements
+ Timer,
+ Externalizable {
+ private long duration;
+
+ public DurationTimer() {
+
+ }
+
+ public DurationTimer(long duration) {
+ this.duration = duration;
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeLong( duration );
+ }
+
+ public void readExternal(ObjectInput in) throws IOException,
+ ClassNotFoundException {
+ duration = in.readLong();
+ }
+
+ public long getDuration() {
+ return duration;
+ }
+
+ public Trigger createTrigger(long timestamp) {
+ return new PointInTimeTrigger( timestamp + duration );
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (duration ^ (duration >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if ( this == obj ) return true;
+ if ( obj == null ) return false;
+ if ( getClass() != obj.getClass() ) return false;
+ DurationTimer other = (DurationTimer) obj;
+ if ( duration != other.duration ) return false;
+ return true;
+ }
+
+}
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/IntervalTimer.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/IntervalTimer.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/IntervalTimer.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -0,0 +1,98 @@
+package org.drools.time.impl;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Date;
+
+import org.drools.time.Trigger;
+
+public class IntervalTimer
+ implements
+ Timer,
+ Externalizable {
+ private Date startTime;
+ private Date endTime;
+ private long delay;
+ private long period;
+
+ public IntervalTimer() {
+
+ }
+
+ public IntervalTimer(Date startTime,
+ Date endTime,
+ long delay,
+ long period) {
+ this.startTime = startTime;
+ this.endTime = endTime;
+ this.delay = delay;
+ this.period = period;
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeObject( startTime );
+ out.writeObject( endTime );
+ out.writeLong( delay );
+ out.writeLong( period );
+ }
+
+ public void readExternal(ObjectInput in) throws IOException,
+ ClassNotFoundException {
+ this.startTime = (Date) in.readObject();
+ this.endTime = (Date) in.readObject();
+ this.delay = in.readLong();
+ this.period = in.readLong();
+ }
+
+ public Date getStartTime() {
+ return startTime;
+ }
+
+ public Date getEndTime() {
+ return endTime;
+ }
+
+ public long getDelay() {
+ return delay;
+ }
+
+ public long getPeriod() {
+ return period;
+ }
+
+ public Trigger createTrigger(long timestamp) {
+ return new IntervalTrigger( timestamp,
+ delay,
+ period );
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (delay ^ (delay >>> 32));
+ result = prime * result + ((endTime == null) ? 0 : endTime.hashCode());
+ result = prime * result + (int) (period ^ (period >>> 32));
+ result = prime * result + ((startTime == null) ? 0 : startTime.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if ( this == obj ) return true;
+ if ( obj == null ) return false;
+ if ( getClass() != obj.getClass() ) return false;
+ IntervalTimer other = (IntervalTimer) obj;
+ if ( delay != other.delay ) return false;
+ if ( endTime == null ) {
+ if ( other.endTime != null ) return false;
+ } else if ( !endTime.equals( other.endTime ) ) return false;
+ if ( period != other.period ) return false;
+ if ( startTime == null ) {
+ if ( other.startTime != null ) return false;
+ } else if ( !startTime.equals( other.startTime ) ) return false;
+ return true;
+ }
+}
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/IntervalTrigger.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/IntervalTrigger.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/IntervalTrigger.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -0,0 +1,57 @@
+/**
+ *
+ */
+package org.drools.time.impl;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Date;
+
+import org.drools.time.Trigger;
+
+public class IntervalTrigger
+ implements
+ Trigger {
+ private Date next;
+ private long period;
+
+ public IntervalTrigger() {
+
+ }
+
+ public IntervalTrigger(long currentTS,
+ long delay,
+ long period) {
+ this.next = new Date( currentTS + delay );
+ this.period = period;
+ }
+
+ public Date hasNextFireTime() {
+ return next;
+ }
+
+ public Date nextFireTime() {
+ Date date = next;
+ if ( this.period != 0 ) {
+ // repeated fires for the given period
+ // FIXME: this is not safe for serialization
+ next = new Date( next.getTime() + this.period );
+ } else {
+ next = null;
+ }
+ return date;
+ }
+
+ public void readExternal(ObjectInput in) throws IOException,
+ ClassNotFoundException {
+ this.next = (Date) in.readObject();
+ this.period = in.readLong();
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeObject( this.next );
+ out.writeLong( this.period );
+ }
+
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/Timer.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/Timer.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/Timer.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -0,0 +1,7 @@
+package org.drools.time.impl;
+
+import org.drools.time.Trigger;
+
+public interface Timer {
+ Trigger createTrigger(long timestamp);
+}
Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/AgendaTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/AgendaTest.java 2009-12-01 20:57:44 UTC (rev 30428)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/AgendaTest.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -57,6 +57,7 @@
import org.drools.spi.PropagationContext;
import org.drools.spi.RuleFlowGroup;
import org.drools.spi.Salience;
+import org.drools.time.impl.DurationTimer;
/**
* @author mproctor
@@ -153,7 +154,7 @@
agenda.getFocus().size() );
rule1.setNoLoop( false );
- rule2.setDuration( 5000 );
+ rule2.setTimer( new DurationTimer( 5000 ) );
node1.assertLeftTuple( tuple,
context1,
Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/SchedulerTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/SchedulerTest.java 2009-12-01 20:57:44 UTC (rev 30428)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/SchedulerTest.java 2009-12-02 05:00:53 UTC (rev 30429)
@@ -36,6 +36,7 @@
import org.drools.spi.KnowledgeHelper;
import org.drools.spi.PropagationContext;
import org.drools.spi.Tuple;
+import org.drools.time.impl.DurationTimer;
/**
* @author mproctor
@@ -83,20 +84,8 @@
}
} );
- /* 1/10th of a second */
- final Duration duration = new Duration() {
- /**
- *
- */
- private static final long serialVersionUID = 400L;
+ rule.setTimer( new DurationTimer(100) );
- public long getDuration(Tuple tuple) {
- return 100;
- }
-
- };
- rule.setDuration( duration );
-
final PropagationContext context = new PropagationContextImpl( 0,
PropagationContext.ASSERTION,
null,
@@ -136,20 +125,6 @@
buildContext );
final List data = new ArrayList();
- /* 1/10th of a second */
- final Duration duration = new Duration() {
- /**
- *
- */
- private static final long serialVersionUID = 400L;
-
- public long getDuration(Tuple tuple) {
- return 100;
- }
-
- };
-
-
// add consequence
rule.setConsequence( new org.drools.spi.Consequence() {
/**
@@ -193,7 +168,7 @@
final LeftTuple tuple1 = new LeftTuple( new DefaultFactHandle( 1,
"cheese" ), null,
true );
- rule.setDuration( duration );
+ rule.setTimer( new DurationTimer(100) );
node.assertLeftTuple( tuple1,
context1,
@@ -227,20 +202,7 @@
rule.getLhs(),
buildContext );
- /* 1/10th of a second */
- final Duration duration = new Duration() {
- /**
- *
- */
- private static final long serialVersionUID = 400L;
-
- public long getDuration(Tuple tuple) {
- return 100;
- }
-
- };
-
- rule.setDuration( duration );
+ rule.setTimer( new DurationTimer(100) );
rule.setNoLoop( true );
// add consequence
More information about the jboss-svn-commits
mailing list