[jboss-svn-commits] JBL Code SVN: r30561 - in labs/jbossrules/trunk: drools-api/src/main/java/org/drools/runtime and 20 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Wed Dec 9 00:58:01 EST 2009


Author: mark.proctor at jboss.com
Date: 2009-12-09 00:58:00 -0500 (Wed, 09 Dec 2009)
New Revision: 30561

Added:
   labs/jbossrules/trunk/drools-api/src/main/java/org/drools/runtime/Calendars.java
   labs/jbossrules/trunk/drools-api/src/main/java/org/drools/runtime/help/QuartzHelper.java
   labs/jbossrules/trunk/drools-api/src/main/java/org/drools/time/Calendar.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/CalendarsImpl.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/command/runtime/GetCalendarsCommand.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CalendarUtils.java
Removed:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/CompositeMaxDuration.java
Modified:
   labs/jbossrules/trunk/drools-api/.classpath
   labs/jbossrules/trunk/drools-api/pom.xml
   labs/jbossrules/trunk/drools-api/src/main/java/org/drools/runtime/KnowledgeRuntime.java
   labs/jbossrules/trunk/drools-compiler/.classpath
   labs/jbossrules/trunk/drools-compiler/pom.xml
   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/ExecutionFlowControlTest.java
   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/testframework/MockWorkingMemory.java
   labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_Duration_with_NoLoop.drl
   labs/jbossrules/trunk/drools-core/.classpath
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/command/impl/CommandBasedStatefulKnowledgeSession.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultAgenda.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalAgenda.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalWorkingMemory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/Scheduler.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/StatefulKnowledgeSessionImpl.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/ObjectTypeNode.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/rule/SlidingTimeWindow.java
   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/CronTrigger.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/PointInTimeTrigger.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/PseudoClockScheduler.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/Timer.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/time/impl/CronJobTest.java
Log:
JBRULES-2364 Calendar support in drools
-initial calendaring impl, complete with unit tests for normal rules, and cron and interval timer rules.
-still missing start/end support.

Modified: labs/jbossrules/trunk/drools-api/.classpath
===================================================================
--- labs/jbossrules/trunk/drools-api/.classpath	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-api/.classpath	2009-12-09 05:58:00 UTC (rev 30561)
@@ -31,6 +31,7 @@
   <classpathentry kind="var" path="M2_REPO/org/mvel/mvel/1.3.12-java1.5/mvel-1.3.12-java1.5.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/objenesis/objenesis/1.0/objenesis-1.0.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/apache/poi/poi/3.0.2-FINAL/poi-3.0.2-FINAL.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/opensymphony/quartz/quartz/1.6.1/quartz-1.6.1.jar"/>
   <classpathentry kind="var" path="M2_REPO/javax/xml/stream/stax-api/1.0-2/stax-api-1.0-2.jar"/>
   <classpathentry kind="var" path="M2_REPO/xerces/xercesImpl/2.9.1/xercesImpl-2.9.1.jar"/>
   <classpathentry kind="var" path="M2_REPO/xml-apis/xml-apis/2.0.2/xml-apis-2.0.2.jar"/>

Modified: labs/jbossrules/trunk/drools-api/pom.xml
===================================================================
--- labs/jbossrules/trunk/drools-api/pom.xml	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-api/pom.xml	2009-12-09 05:58:00 UTC (rev 30561)
@@ -54,6 +54,13 @@
           <scope>provided</scope>
         </dependency>  	 
         
+        <dependency>
+  			<groupId>org.opensymphony.quartz</groupId>
+  			<artifactId>quartz</artifactId>
+  			<version>1.6.1</version>
+            <scope>provided</scope>  			
+        </dependency>          
+        
   </dependencies>
   
   <build>

Added: labs/jbossrules/trunk/drools-api/src/main/java/org/drools/runtime/Calendars.java
===================================================================
--- labs/jbossrules/trunk/drools-api/src/main/java/org/drools/runtime/Calendars.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-api/src/main/java/org/drools/runtime/Calendars.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -0,0 +1,10 @@
+package org.drools.runtime;
+
+import org.drools.time.Calendar;
+
+public interface Calendars {
+    Calendar get(String identifier);
+
+    void set(String identifier,
+             Calendar value);
+}

Modified: labs/jbossrules/trunk/drools-api/src/main/java/org/drools/runtime/KnowledgeRuntime.java
===================================================================
--- labs/jbossrules/trunk/drools-api/src/main/java/org/drools/runtime/KnowledgeRuntime.java	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-api/src/main/java/org/drools/runtime/KnowledgeRuntime.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -29,6 +29,8 @@
     Object getGlobal(String identifier);
 
     Globals getGlobals();
+    
+    Calendars getCalendars();
 
     Environment getEnvironment();
 

Added: labs/jbossrules/trunk/drools-api/src/main/java/org/drools/runtime/help/QuartzHelper.java
===================================================================
--- labs/jbossrules/trunk/drools-api/src/main/java/org/drools/runtime/help/QuartzHelper.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-api/src/main/java/org/drools/runtime/help/QuartzHelper.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -0,0 +1,41 @@
+package org.drools.runtime.help;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+import org.drools.time.Calendar;
+
+public class QuartzHelper {
+
+    public static Calendar quartzCalendarAdapter(org.quartz.Calendar calendar) {
+        return new QuartzCalendarAdapter( calendar );
+    }
+
+    public static class QuartzCalendarAdapter
+        implements
+        Calendar,
+        Externalizable {
+        private org.quartz.Calendar calendar;
+
+        public QuartzCalendarAdapter(org.quartz.Calendar calendar) {
+            this.calendar = calendar;
+        }
+
+        public boolean isTimeIncluded(long timestamp) {
+            return this.calendar.isTimeIncluded( timestamp );
+        }
+
+        public void readExternal(ObjectInput in) throws IOException,
+                                                ClassNotFoundException {
+            this.calendar = (org.quartz.Calendar) in.readObject();
+        }
+
+        public void writeExternal(ObjectOutput out) throws IOException {
+            out.writeObject( this.calendar );
+        }
+
+    }
+
+}

Added: labs/jbossrules/trunk/drools-api/src/main/java/org/drools/time/Calendar.java
===================================================================
--- labs/jbossrules/trunk/drools-api/src/main/java/org/drools/time/Calendar.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-api/src/main/java/org/drools/time/Calendar.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -0,0 +1,5 @@
+package org.drools.time;
+
+public interface Calendar {    
+    boolean isTimeIncluded(long timestamp); 
+}

Modified: labs/jbossrules/trunk/drools-compiler/.classpath
===================================================================
--- labs/jbossrules/trunk/drools-compiler/.classpath	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-compiler/.classpath	2009-12-09 05:58:00 UTC (rev 30561)
@@ -1,33 +1,32 @@
-<?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<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>
+  <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="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/opensymphony/quartz/quartz/1.6.1/quartz-1.6.1.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"/>
+</classpath>
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-compiler/pom.xml
===================================================================
--- labs/jbossrules/trunk/drools-compiler/pom.xml	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-compiler/pom.xml	2009-12-09 05:58:00 UTC (rev 30561)
@@ -53,7 +53,14 @@
 			<artifactId>jetty-embedded</artifactId>
 			<version>6.1.15</version>
 			<scope>test</scope>
-		</dependency>					
+		</dependency>	
+		
+        <dependency>
+  			<groupId>org.opensymphony.quartz</groupId>
+  			<artifactId>quartz</artifactId>
+  			<version>1.6.1</version>
+			<scope>test</scope> 			
+        </dependency> 						
 	</dependencies>
 
 	<profiles>

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-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/RuleBuilder.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -18,6 +18,7 @@
 
 import java.text.ParseException;
 import java.util.Calendar;
+import java.util.List;
 
 import org.drools.RuntimeDroolsException;
 import org.drools.base.EnabledBoolean;
@@ -36,6 +37,7 @@
 import org.drools.time.impl.IntervalTimer;
 import org.drools.time.impl.Timer;
 import org.drools.util.DateUtils;
+import org.mvel2.MVEL;
 
 /**
  * This builds the rule structure from an AST.
@@ -118,6 +120,24 @@
             } else if ( name.equals( DroolsSoftKeywords.DURATION ) || name.equals( DroolsSoftKeywords.TIMER ) ) {
                 String duration = attributeDescr.getValue();
                 buildTimer( rule, duration, context);
+            }  else if ( name.equals( "calendars" ) ) {
+                Object val = null;
+                try {
+                    val = MVEL.eval( attributeDescr.getValue() );
+                    String[] calNames = null;
+                    if ( val instanceof List ) {
+                        calNames = ( String[] ) ((List)val).toArray( new String[ ((List)val).size() ] );
+                    } else if ( val instanceof String ) {
+                        calNames = new String[] { (String) val };
+                    } else {
+                        context.getErrors().add( "Calendars attribute did not return a String or String[] '" + val + "'"  );
+                    }
+                    if ( calNames != null ) {
+                        rule.setCalendars( calNames );
+                    }
+                } catch ( Exception e ) {
+                    context.getErrors().add( "Unable to build Calendars attribute '" + val + "'"  + e.getMessage() );
+                }
             } else if ( name.equals( "date-effective" ) ) {
                 final Calendar cal = Calendar.getInstance();
                 cal.setTime( DateUtils.parseDate( attributeDescr.getValue() ) );
@@ -224,7 +244,6 @@
                 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;

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-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/ExecutionFlowControlTest.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -53,6 +53,7 @@
 import org.drools.spi.Activation;
 import org.drools.spi.ActivationGroup;
 import org.drools.spi.AgendaGroup;
+import org.drools.time.Calendar;
 import org.drools.time.impl.PseudoClockScheduler;
 
 public class ExecutionFlowControlTest extends TestCase {
@@ -826,8 +827,19 @@
     }
 
     public void testDurationMemoryLeakonRepeatedUpdate() throws Exception {
-        String str = "package org.drools.test\n" + "import org.drools.Alarm\n" + "global java.util.List list;" + "rule \"COMPTEUR\"\n" + "  duration 50\n" + "  when\n" + "    $alarm : Alarm( number < 5 )\n" + "  then\n"
-                     + "    $alarm.incrementNumber();\n" + "    list.add( $alarm );\n" + "    update($alarm);\n" + "end\n";
+        String str = "";
+        str += "package org.drools.test\n";
+        str += "import org.drools.Alarm\n";
+        str += "global java.util.List list;";
+        str += "rule \"COMPTEUR\"\n";
+        str += "  timer 50\n";
+        str += "  when\n";
+        str += "    $alarm : Alarm( number < 5 )\n";
+        str += "  then\n";
+        str += "    $alarm.incrementNumber();\n";
+        str += "    list.add( $alarm );\n";
+        str += "    update($alarm);\n";
+        str += "end\n";
 
         PackageBuilder builder = new PackageBuilder();
         builder.addPackageFromDrl( new StringReader( str ) );
@@ -913,7 +925,7 @@
         str += "package org.simple \n";
         str += "global java.util.List list \n";
         str += "rule xxx \n";
-        str += "  duration (int:30s 10s) ";
+        str += "  timer (int:30s 10s) ";
         str += "when \n";
         str += "then \n";
         str += "  list.add(\"fired\"); \n";
@@ -971,7 +983,7 @@
         str += "package org.simple \n";
         str += "global java.util.List list \n";
         str += "rule xxx \n";
-        str += "  duration (cron:15 * * * * ?) ";
+        str += "  timer (cron:15 * * * * ?) ";
         str += "when \n";
         str += "then \n";
         str += "  list.add(\"fired\"); \n";
@@ -1022,13 +1034,14 @@
         assertEquals( 2, list.size() );                   
     }        
     
-    public void testCalendarNormalActivation() throws Exception {
+    public void testCalendarNormalRuleSingleCalendar() 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 += "  calendars \"cal1\"\n";
         str += "when \n";
+        str += "  String()\n";
         str += "then \n";
         str += "  list.add(\"fired\"); \n";
         str += "end  \n";
@@ -1042,8 +1055,20 @@
             assertTrue( kbuilder.hasErrors() );
         }
 
+        Calendar calFalse = new Calendar() {
+            public boolean isTimeIncluded(long timestamp) {
+                return false;
+            }           
+        };
+        
+        Calendar calTrue = new Calendar() {
+            public boolean isTimeIncluded(long timestamp) {
+                return true;
+            }           
+        };        
+        
         KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
-        kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
+        kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );              
 
         KnowledgeSessionConfiguration conf = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
         conf.setOption( ClockTypeOption.get( "pseudo" ) );
@@ -1054,30 +1079,284 @@
         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.getCalendars().set( "cal1", calTrue );
         
-        ksession.setGlobal( "list", list );
-  
+        timeService.advanceTime( date.getTime(), TimeUnit.MILLISECONDS );     
+        ksession.setGlobal( "list", list );        
+        ksession.insert( "o1" );        
         ksession.fireAllRules();        
-        assertEquals( 0, list.size() ); 
+        assertEquals( 1, list.size() ); 
                 
         timeService.advanceTime( 10, TimeUnit.SECONDS );
+        ksession.insert( "o2" );
         ksession.fireAllRules();        
-        assertEquals( 0, list.size() ); 
-                 
-        timeService.advanceTime( 10, TimeUnit.SECONDS );            
+        assertEquals( 2, list.size() ); 
+        
+        ksession.getCalendars().set( "cal1", calFalse );        
+        timeService.advanceTime( 10, TimeUnit.SECONDS );        
+        ksession.insert( "o3" );
         ksession.fireAllRules();        
-        assertEquals( 1, list.size() ); 
+        assertEquals( 2, list.size() ); 
         
-        timeService.advanceTime( 30, TimeUnit.SECONDS );   
+        ksession.getCalendars().set( "cal1", calTrue );        
+        timeService.advanceTime( 30, TimeUnit.SECONDS );
+        ksession.insert( "o4" );
         ksession.fireAllRules();        
+        assertEquals( 3, list.size() );                    
+    }   
+    
+    public void testCalendarNormalRuleMultipleCalendars() throws Exception {
+        String str = "";
+        str += "package org.simple \n";
+        str += "global java.util.List list \n";
+        str += "rule xxx \n";
+        str += "  calendars \"cal1\", \"cal2\"\n";      
+        str += "when \n";
+        str += "  String()\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() );
+        }
+
+        Calendar calFalse = new Calendar() {
+            public boolean isTimeIncluded(long timestamp) {
+                return false;
+            }           
+        };
+        
+        Calendar calTrue = new Calendar() {
+            public boolean isTimeIncluded(long timestamp) {
+                return true;
+            }           
+        };        
+        
+        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" );
+        
+        ksession.getCalendars().set( "cal1", calTrue );
+        ksession.getCalendars().set( "cal2", calTrue );
+        
+        timeService.advanceTime( date.getTime(), TimeUnit.MILLISECONDS );     
+        ksession.setGlobal( "list", list );        
+        ksession.insert( "o1" );        
+        ksession.fireAllRules();        
         assertEquals( 1, list.size() ); 
+
+        ksession.getCalendars().set( "cal2", calFalse );        
+        timeService.advanceTime( 10, TimeUnit.SECONDS );
+        ksession.insert( "o2" );
+        ksession.fireAllRules();        
+        assertEquals( 1, list.size() ); 
+                
+        ksession.getCalendars().set( "cal1", calFalse );            
+        timeService.advanceTime( 10, TimeUnit.SECONDS );    
+        ksession.insert( "o3" );
+        ksession.fireAllRules();        
+        assertEquals( 1, list.size() ); 
         
-        timeService.advanceTime( 30, TimeUnit.SECONDS );  
+        ksession.getCalendars().set( "cal1", calTrue );
+        ksession.getCalendars().set( "cal2", calTrue );        
+        timeService.advanceTime( 30, TimeUnit.SECONDS );
+        ksession.insert( "o4" );
         ksession.fireAllRules();        
-        assertEquals( 2, list.size() );                   
-    }         
+        assertEquals( 2, list.size() );                    
+    }      
+    
+    public void testCalendarsWithCron() throws Exception {
+        String str = "";
+        str += "package org.simple \n";
+        str += "global java.util.List list \n";
+        str += "rule xxx \n";
+        str += "  calendars \"cal1\", \"cal2\"\n";           
+        str += "  timer (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 );
+        
+        final Date date1 = new Date( date.getTime() +  (15 * 1000) );
+        final Date date2 = new Date( date1.getTime() + (60 * 1000) );
+        final Date date3 = new Date( date2.getTime() + (60 * 1000) );
+        final Date date4 = new Date( date3.getTime() + (60 * 1000) );
+        
+        Calendar cal1 = new Calendar() {
+            public boolean isTimeIncluded(long timestamp) {
+                if ( timestamp == date1.getTime() ) {
+                    return true;
+                } else if ( timestamp == date4.getTime() ) {
+                    return false;
+                } else {
+                    return true;
+                }
+            }           
+        };  
+        
+        Calendar cal2 = new Calendar() {
+            public boolean isTimeIncluded(long timestamp) {
+               if ( timestamp == date2.getTime() ) {
+                    return false;
+                }  else if ( timestamp == date3.getTime() ) {
+                    return true;
+                } else {
+                    return true;
+                }
+            }           
+        };          
+        
+        ksession.getCalendars().set( "cal1", cal1 );
+        ksession.getCalendars().set( "cal2", cal2 );
+        
+        ksession.setGlobal( "list", list );
+                         
+        ksession.fireAllRules();
+        timeService.advanceTime( 20, TimeUnit.SECONDS );       
+        assertEquals( 1, list.size() ); 
+                      
+        timeService.advanceTime( 60, TimeUnit.SECONDS );                      
+        assertEquals( 1, list.size() ); 
+             
+        timeService.advanceTime( 60, TimeUnit.SECONDS );                  
+        assertEquals( 2, list.size() ); 
+        
+        timeService.advanceTime( 60, TimeUnit.SECONDS );         
+        assertEquals( 2, list.size() );  
+
+        timeService.advanceTime( 60, TimeUnit.SECONDS );         
+        assertEquals( 3, list.size() );  
+        
+        timeService.advanceTime( 60, TimeUnit.SECONDS );         
+        assertEquals( 4, list.size() );          
+    }   
+    
+    public void testCalendarsWithIntervals() throws Exception {
+        String str = "";
+        str += "package org.simple \n";
+        str += "global java.util.List list \n";
+        str += "rule xxx \n";
+        str += "  calendars \"cal1\", \"cal2\"\n";           
+        str += "  timer (15s 60s) "; //int: protocol is assumed
+        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 );
+        
+        final Date date1 = new Date( date.getTime() +  (15 * 1000) );
+        final Date date2 = new Date( date1.getTime() + (60 * 1000) );
+        final Date date3 = new Date( date2.getTime() + (60 * 1000) );
+        final Date date4 = new Date( date3.getTime() + (60 * 1000) );
+        
+        Calendar cal1 = new Calendar() {
+            public boolean isTimeIncluded(long timestamp) {
+                if ( timestamp == date1.getTime() ) {
+                    return true;
+                } else if ( timestamp == date4.getTime() ) {
+                    return false;
+                } else {
+                    return true;
+                }
+            }           
+        };  
+        
+        Calendar cal2 = new Calendar() {
+            public boolean isTimeIncluded(long timestamp) {
+               if ( timestamp == date2.getTime() ) {
+                    return false;
+                }  else if ( timestamp == date3.getTime() ) {
+                    return true;
+                } else {
+                    return true;
+                }
+            }           
+        };          
+        
+        ksession.getCalendars().set( "cal1", cal1 );
+        ksession.getCalendars().set( "cal2", cal2 );
+        
+        ksession.setGlobal( "list", list );
+                         
+        ksession.fireAllRules();
+        timeService.advanceTime( 20, TimeUnit.SECONDS );       
+        assertEquals( 1, list.size() ); 
+                      
+        timeService.advanceTime( 60, TimeUnit.SECONDS );                      
+        assertEquals( 1, list.size() ); 
+             
+        timeService.advanceTime( 60, TimeUnit.SECONDS );                  
+        assertEquals( 2, list.size() ); 
+        
+        timeService.advanceTime( 60, TimeUnit.SECONDS );         
+        assertEquals( 2, list.size() );  
+
+        timeService.advanceTime( 60, TimeUnit.SECONDS );         
+        assertEquals( 3, list.size() );  
+        
+        timeService.advanceTime( 60, TimeUnit.SECONDS );         
+        assertEquals( 4, 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-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/rule/builder/dialect/java/RuleBuilderTest.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -178,6 +178,8 @@
                                                     "false" ) );
         ruleDescr.addAttribute( new AttributeDescr( "duration",
                                                     "60" ) );
+        ruleDescr.addAttribute( new AttributeDescr( "calendars",
+                                                    "\"cal1\"" ) );        
         ruleDescr.addAttribute( new AttributeDescr( "date-effective",
                                                     "10-Jul-1974" ) );
         ruleDescr.addAttribute( new AttributeDescr( "date-expires",
@@ -205,6 +207,7 @@
                 oneOf( rule ).setLockOnActive( true );
                 oneOf( rule ).setEnabled( EnabledBoolean.ENABLED_FALSE );
                 oneOf( rule ).setTimer( new IntervalTimer( null , null, TimeUtils.parseTimeString( "60" ), 0 ) );
+                oneOf( rule ).setCalendars( new String[] { "cal1" } );
                 oneOf( rule ).setDateEffective( effective );
                 oneOf( rule ).setDateExpires( expires );
             }
@@ -228,7 +231,9 @@
         final RuleDescr ruleDescr = new RuleDescr( "my rule" );
         ruleDescr.addAttribute( new AttributeDescr( "duration",
                                                     "( 1h30m )" ) );
-
+        ruleDescr.addAttribute( new AttributeDescr( "calendars",
+                                                    "[\"cal1\", \"cal2\"]" ) ); 
+        
         // defining expectations on the mock object
         mockery.checking( new Expectations() {
             {
@@ -238,6 +243,7 @@
 
                 // expected values for the rule object
                 oneOf( rule ).setTimer( new IntervalTimer( null , null, TimeUtils.parseTimeString( "1h30m" ), 0 ) );
+                oneOf( rule ).setCalendars( new String[] { "cal1", "cal2" } );
             }
         } );
 

Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/testframework/MockWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/testframework/MockWorkingMemory.java	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/testframework/MockWorkingMemory.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -44,6 +44,7 @@
 import org.drools.reteoo.PartitionTaskManager;
 import org.drools.rule.Rule;
 import org.drools.rule.TimeMachine;
+import org.drools.runtime.Calendars;
 import org.drools.runtime.Environment;
 import org.drools.runtime.ExitPoint;
 import org.drools.runtime.KnowledgeRuntime;
@@ -78,6 +79,11 @@
         out.writeObject(timeMachine);
         out.writeObject(globals);
     }
+    
+    public Calendars getCalendars() {
+        return null;
+    }
+    
 	public Iterator iterateObjects() {
 		return this.facts.iterator();
 	}

Modified: labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_Duration_with_NoLoop.drl
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_Duration_with_NoLoop.drl	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_Duration_with_NoLoop.drl	2009-12-09 05:58:00 UTC (rev 30561)
@@ -6,7 +6,7 @@
 global java.util.List list;
 
 rule delayed
-	duration 100
+	timer 100
 	no-loop true
     when
         cheese : Cheese( )

Modified: labs/jbossrules/trunk/drools-core/.classpath
===================================================================
--- labs/jbossrules/trunk/drools-core/.classpath	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/.classpath	2009-12-09 05:58:00 UTC (rev 30561)
@@ -1,22 +1,20 @@
-<?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<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/cglib/cglib-nodep/2.1_3/cglib-nodep-2.1_3.jar"/>
-	<classpathentry kind="src" path="/drools-api"/>
-	<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/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/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/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>
+  <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/cglib/cglib-nodep/2.1_3/cglib-nodep-2.1_3.jar"/>
+  <classpathentry kind="src" path="/drools-api"/>
+  <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/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/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/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"/>
+</classpath>
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/CalendarsImpl.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/CalendarsImpl.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/CalendarsImpl.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -0,0 +1,47 @@
+package org.drools.base;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.drools.runtime.Calendars;
+import org.drools.runtime.Globals;
+import org.drools.spi.GlobalResolver;
+import org.drools.time.Calendar;
+
+public class CalendarsImpl
+    implements
+    Calendars,
+    Externalizable {
+
+    private static final long serialVersionUID = 400L;
+
+    private Map<String, Calendar> map;
+
+    public CalendarsImpl() {
+        this.map = new ConcurrentHashMap<String, Calendar>();
+    }
+
+
+    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        map = (Map)in.readObject();
+    }
+
+    public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeObject( map );
+    }     
+    
+    public Calendar get(String identifier) {
+        return this.map.get( identifier );
+    }
+    
+    public void set(String identifier, Calendar calendar) {
+        this.map.put( identifier, calendar );
+    }
+
+}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/command/impl/CommandBasedStatefulKnowledgeSession.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/command/impl/CommandBasedStatefulKnowledgeSession.java	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/command/impl/CommandBasedStatefulKnowledgeSession.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -52,6 +52,7 @@
 import org.drools.event.rule.WorkingMemoryEventListener;
 import org.drools.impl.StatefulKnowledgeSessionImpl;
 import org.drools.rule.EntryPoint;
+import org.drools.runtime.Calendars;
 import org.drools.runtime.Environment;
 import org.drools.runtime.ExecutionResults;
 import org.drools.runtime.ExitPoint;
@@ -365,6 +366,11 @@
     public Globals getGlobals() {
         return commandService.execute( new GetGlobalsCommand() );
     }
+    
+    public Calendars getCalendars() {
+        // TODO return
+        throw new UnsupportedOperationException();
+    }    
 
     public Object getObject(FactHandle factHandle) {
         return commandService.execute( new GetObjectCommand( factHandle ) );

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/command/runtime/GetCalendarsCommand.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/command/runtime/GetCalendarsCommand.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/command/runtime/GetCalendarsCommand.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -0,0 +1,21 @@
+package org.drools.command.runtime;
+
+import org.drools.command.Context;
+import org.drools.command.impl.GenericCommand;
+import org.drools.command.impl.KnowledgeCommandContext;
+import org.drools.runtime.Calendars;
+import org.drools.runtime.StatefulKnowledgeSession;
+
+public class GetCalendarsCommand
+    implements
+    GenericCommand<Calendars> {
+
+    public Calendars execute(Context context) {
+        StatefulKnowledgeSession ksession = ((KnowledgeCommandContext) context).getStatefulKnowledgesession();
+        return (Calendars) ksession.getCalendars();
+    }
+
+    public String toString() {
+        return "session.getCalendars()";
+    }
+}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -32,6 +32,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
@@ -57,6 +58,7 @@
 import org.drools.rule.Rule;
 import org.drools.rule.TypeDeclaration;
 import org.drools.spi.FactHandleFactory;
+import org.drools.time.Calendar;
 import org.drools.util.ObjectHashSet;
 
 /**
@@ -92,7 +94,7 @@
      */
     private FactHandleFactory                          factHandleFactory;
 
-    private transient Map<String, Class< ? >>          globals;
+    private transient Map<String, Class< ? >>          globals;   
 
     private ReloadPackageCompilationData               reloadPackageCompilationData = null;
 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -50,6 +50,7 @@
 import org.drools.WorkingMemoryEntryPoint;
 import org.drools.RuleBaseConfiguration.AssertBehaviour;
 import org.drools.RuleBaseConfiguration.LogicalOverride;
+import org.drools.base.CalendarsImpl;
 import org.drools.base.MapGlobalResolver;
 import org.drools.concurrent.ExecutorService;
 import org.drools.concurrent.ExternalExecutorService;
@@ -88,6 +89,7 @@
 import org.drools.rule.Rule;
 import org.drools.rule.TimeMachine;
 import org.drools.ruleflow.core.RuleFlowProcess;
+import org.drools.runtime.Calendars;
 import org.drools.runtime.Environment;
 import org.drools.runtime.EnvironmentName;
 import org.drools.runtime.ExecutionResults;
@@ -145,6 +147,8 @@
 
     /** Global values which are associated with this memory. */
     protected GlobalResolver                                     globalResolver;
+    
+    protected Calendars                                          calendars;
 
     /** The eventSupport */
     protected WorkingMemoryEventSupport                          workingMemoryEventSupport;
@@ -279,6 +283,8 @@
         } else {
             this.globalResolver = new MapGlobalResolver();
         }
+        
+        this.calendars = new CalendarsImpl();
 
         final RuleBaseConfiguration conf = this.ruleBase.getConfiguration();
 
@@ -628,6 +634,10 @@
     public GlobalResolver getGlobalResolver() {
         return this.globalResolver;
     }
+    
+    public Calendars getCalendars() {
+        return this.calendars;
+    }
 
     public int getId() {
         return this.id;

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultAgenda.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultAgenda.java	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultAgenda.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -309,10 +309,11 @@
      * @param item
      *            The item to schedule.
      */
-    public void scheduleItem(final ScheduledAgendaItem item) {
+    public void scheduleItem(final ScheduledAgendaItem item, final InternalWorkingMemory wm) {
 
         Scheduler.scheduleAgendaItem( item,
-                                      this );
+                                      this,
+                                      wm );
         this.scheduledActivations.add( item );
 
         // adds item to activation group if appropriate

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalAgenda.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalAgenda.java	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalAgenda.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -24,7 +24,7 @@
 
     public boolean fireNextItem(AgendaFilter filter) throws ConsequenceException;
 
-    public void scheduleItem(final ScheduledAgendaItem item);
+    public void scheduleItem(final ScheduledAgendaItem item, InternalWorkingMemory workingMemory);
 
     public AgendaItem createAgendaItem(final Tuple tuple,
                                        final int salience,

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalWorkingMemory.java	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalWorkingMemory.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -17,6 +17,7 @@
 import org.drools.reteoo.PartitionTaskManager;
 import org.drools.rule.Rule;
 import org.drools.rule.TimeMachine;
+import org.drools.runtime.Calendars;
 import org.drools.runtime.ExitPoint;
 import org.drools.runtime.KnowledgeRuntime;
 import org.drools.runtime.impl.ExecutionResultImpl;
@@ -103,6 +104,8 @@
     
     public InternalFactHandle getInitialFactHandle();       
     
+    public Calendars getCalendars();
+    
     /**
      * Returns the TimerService instance (session clock) for this
      * session.

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-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/Scheduler.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -17,6 +17,7 @@
  */
 
 import org.drools.Agenda;
+import org.drools.runtime.Calendars;
 import org.drools.time.Job;
 import org.drools.time.JobContext;
 import org.drools.time.JobHandle;
@@ -43,12 +44,16 @@
      * 
      * @param item
      *            The item to schedule.
+     * @param wm 
      * @param workingMemory
      *            The working memory session.
      */
-    public static void scheduleAgendaItem(final ScheduledAgendaItem item, InternalAgenda agenda) {
-        Trigger trigger = item.getRule().getTimer().createTrigger( ((InternalWorkingMemory)agenda.getWorkingMemory()).getTimerService().getCurrentTime() );
+    public static void scheduleAgendaItem(final ScheduledAgendaItem item, InternalAgenda agenda, InternalWorkingMemory wm) {
+        String[] calendarNames = item.getRule().getCalendars();
+        Calendars calendars = wm.getCalendars();
         
+        Trigger trigger = item.getRule().getTimer().createTrigger( ((InternalWorkingMemory)agenda.getWorkingMemory()).getTimerService().getCurrentTime(), calendarNames, calendars);
+        
         ActivationTimerJob job = new ActivationTimerJob();        
         ActivationTimerJobContext ctx = new ActivationTimerJobContext( trigger, item, agenda );        
                 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/StatefulKnowledgeSessionImpl.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/StatefulKnowledgeSessionImpl.java	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/StatefulKnowledgeSessionImpl.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -56,6 +56,7 @@
 import org.drools.reteoo.ReteooWorkingMemory;
 import org.drools.rule.EntryPoint;
 import org.drools.rule.Rule;
+import org.drools.runtime.Calendars;
 import org.drools.runtime.CommandExecutor;
 import org.drools.runtime.Environment;
 import org.drools.runtime.ExecutionResults;
@@ -316,6 +317,10 @@
         return (Globals) this.session.getGlobalResolver();
     }
     
+    public Calendars getCalendars() {
+        return this.session.getCalendars();
+    }    
+    
     public Environment getEnvironment() {
         return this.session.getEnvironment();
     }

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-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/process/instance/timer/TimerManager.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -44,7 +44,9 @@
                                                              ctx,
                                                              new IntervalTrigger( timerService.getCurrentTime(),
                                                                                timer.getDelay(),
-                                                                               timer.getPeriod() ) );
+                                                                               timer.getPeriod(),
+                                                                               null,
+                                                                               null ) );
         timer.setJobHandle( jobHandle );
         timers.put(timer.getId(), timer);
     }
@@ -74,7 +76,9 @@
 		JobHandle jobHandle = this.timerService.scheduleJob(
 			processJob, ctx, new IntervalTrigger(timerService.getCurrentTime(),
                                               delay, 
-                                              timer.getPeriod()));
+                                              timer.getPeriod(),
+                                              null,
+                                              null));
 		timer.setJobHandle(jobHandle);
 		timers.put(timer.getId(), timer);
 	}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -196,7 +196,7 @@
                     workingMemory);
             JobHandle handle = clock.scheduleJob(job,
                     jobctx,
-                    new PointInTimeTrigger(nextTimestamp));
+                    new PointInTimeTrigger(nextTimestamp, null, null));
             jobctx.setJobHandle(handle);
         }
 

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-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RuleTerminalNode.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -211,7 +211,7 @@
                                                                                this.subrule );
             final TerminalNodeMemory memory = (TerminalNodeMemory) workingMemory.getNodeMemory( this );
 
-            agenda.scheduleItem( item );
+            agenda.scheduleItem( item, workingMemory );
             tuple.setActivation( item );
 
             if ( this.tupleMemoryEnabled ) {
@@ -221,7 +221,16 @@
             item.setActivated( true );
             ((EventSupport) workingMemory).getAgendaEventSupport().fireActivationCreated( item,
                                                                                           workingMemory );
-        } else {
+        } else {            
+            if ( this.rule.getCalendars() != null ) {
+                // for normal activations check for Calendar inclusion here, scheduled activations check on each trigger point
+                long timestamp = workingMemory.getSessionClock().getCurrentTime();
+                for ( String cal : this.rule.getCalendars() ) {
+                    if ( !workingMemory.getCalendars().get( cal ).isTimeIncluded( timestamp ) ) {
+                        return;
+                    }
+                }            
+            }
             // -----------------
             // Lazy instantiation and addition to the Agenda of AgendGroup
             // implementations

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-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/PatternBuilder.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -33,7 +33,6 @@
 import org.drools.reteoo.ObjectTypeNode;
 import org.drools.reteoo.PropagationQueuingNode;
 import org.drools.rule.Behavior;
-import org.drools.rule.CompositeMaxDuration;
 import org.drools.rule.Declaration;
 import org.drools.rule.EntryPoint;
 import org.drools.rule.FixedDuration;
@@ -197,16 +196,17 @@
                         timer = durationTimer;
                     } else {
                         // timer exists so we need to make a composite
-                        timer = new CompositeMaxDurationTimer();
+                        CompositeMaxDurationTimer temp = new CompositeMaxDurationTimer();
                         if ( timer instanceof DurationTimer ) {
                             // previous timer was a duration, so add another DurationTimer
-                            ((CompositeMaxDurationTimer)timer).addDurationTimer( ( DurationTimer ) timer );                            
+                            temp.addDurationTimer( ( DurationTimer ) timer );                            
                         } else {
                             // previous timer was not a duration, so set it as the delegate Timer.
-                            ((CompositeMaxDurationTimer)timer).setTimer( context.getRule().getTimer() );    
+                            temp.setTimer( context.getRule().getTimer() );    
                         }
                         // now add the new durationTimer
-                        ((CompositeMaxDurationTimer)timer).addDurationTimer( durationTimer );
+                        temp.addDurationTimer( durationTimer );
+                        timer = temp;
                     }
                     // with the composite made, reset it on the Rule
                     context.getRule().setTimer( timer );

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/CompositeMaxDuration.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/CompositeMaxDuration.java	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/CompositeMaxDuration.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -1,91 +0,0 @@
-package org.drools.rule;
-
-/*
- * Copyright 2005 JBoss Inc
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import java.util.LinkedList;
-import java.util.List;
-
-import org.drools.spi.Duration;
-import org.drools.spi.Tuple;
-
-/**
- * A composite duration where the expression
- * is evaluated and the maximum duration between
- * the components is used as the rule's duration.
- * 
- * @see Rule#setDuration
- * @see Rule#getDuration
- * 
- * @author etirelli
- */
-public class CompositeMaxDuration
-    implements
-    Duration {
-
-    private static final long serialVersionUID = 6987782407024443255L;
-
-    // ------------------------------------------------------------
-    // Instance members
-    // ------------------------------------------------------------
-    private List<Duration> durations;
-
-    // ------------------------------------------------------------
-    // Constructors
-    // ------------------------------------------------------------
-
-    /**
-     * Construct.
-     */
-    public CompositeMaxDuration() {
-        this( null );
-    }
-
-    /**
-     * Construct.
-     * 
-     * @param duration a duration to be included as a component of the composed duration
-     *            Number of seconds.
-     */
-    public CompositeMaxDuration( final Duration duration ) {
-        this.durations = new LinkedList<Duration>();
-        this.durations.add( duration );
-    }
-
-    // ------------------------------------------------------------
-    // Instance methods
-    // ------------------------------------------------------------
-
-    public void addDuration( final Duration duration ) {
-        this.durations.add( duration );
-    }
-
-    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-    /**
-     * Returns the maximum duration among the components of this
-     * composite duration.
-     * 
-     * @see Duration
-     */
-    public long getDuration(final Tuple tuple) {
-        long result = 0;
-        for( Duration duration : durations ) {
-            result = Math.max( result, duration.getDuration( tuple ) );
-        }
-        return result;
-    }
-}
\ No newline at end of file

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-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Rule.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -117,6 +117,8 @@
 
     /** indicates that the rule is semantically correct. */
     private boolean           semanticallyValid;
+    
+    private String[]          calendars;
 
     private Calendar          dateEffective;
 
@@ -628,6 +630,14 @@
         return this.semanticallyValid;
     }
 
+    public String[] getCalendars() {
+        return calendars;
+    }
+
+    public void setCalendars(String[] calendars) {
+        this.calendars = calendars;
+    }
+
     /**
      * Sets the date from which this rule takes effect (can include time to the millisecond).
      * @param effectiveDate

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/SlidingTimeWindow.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/SlidingTimeWindow.java	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/SlidingTimeWindow.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -201,7 +201,7 @@
                                                         context );
             JobHandle handle = clock.scheduleJob( job,
                                                   jobctx,
-                                                  new PointInTimeTrigger( nextTimestamp ) );
+                                                  new PointInTimeTrigger( nextTimestamp, null, null ) );
             jobctx.setJobHandle( handle );
         }
     }

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CalendarUtils.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CalendarUtils.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CalendarUtils.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -0,0 +1,41 @@
+package org.drools.time.impl;
+
+import java.util.Date;
+
+import org.drools.runtime.Calendars;
+import org.drools.time.Trigger;
+
+public class CalendarUtils {
+    public static Date updateToNextIncludeDate(String[] calendarNames,
+                                               Calendars calendars,
+                                               Trigger trigger,
+                                               Date next) {
+        if ( calendarNames == null || calendarNames.length == 0 ) {
+            // There are no assigned calendars
+            return next;
+        }
+
+        // If we have calendars, check we can fire, or get next time until we can fire.
+        while ( next != null ) {
+            // this will loop forever if the trigger repeats forever and
+            // included calendar position can be found
+            boolean included = true;
+            for ( String cal : calendarNames ) {
+                // all calendars must not block, as soon as one blocks break
+                if ( !calendars.get( cal ).isTimeIncluded( next.getTime() ) ) {
+                    included = false;
+                    break;
+                }
+            }
+            if ( included == true ) {
+                // if no calendars blocked, break
+                break;
+            } else {
+                // otherwise increase the time and try again
+                next = trigger.nextFireTime();
+            }
+        }
+
+        return next;
+    }
+}

Modified: 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	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CompositeMaxDurationTimer.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -4,6 +4,7 @@
 import java.util.LinkedList;
 import java.util.List;
 
+import org.drools.runtime.Calendars;
 import org.drools.time.Trigger;
 
 /**
@@ -35,9 +36,15 @@
         this.timer = timer;
     }
 
-    public Trigger createTrigger(long timestamp) {
+    public Trigger createTrigger(long timestamp,
+                                 String[] calendarNames,
+                                 Calendars calendars) {
         return new CompositeMaxDurationTrigger( new Date( getMaxDuration() + timestamp ),
-                                                timer.createTrigger( timestamp ) );
+                                                timer.createTrigger( timestamp,
+                                                                     calendarNames,
+                                                                     calendars ),
+                                                calendarNames,
+                                                calendars );
     }
 
     private long getMaxDuration() {

Modified: 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	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CompositeMaxDurationTrigger.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -2,6 +2,7 @@
 
 import java.util.Date;
 
+import org.drools.runtime.Calendars;
 import org.drools.time.Trigger;
 
 public class CompositeMaxDurationTrigger
@@ -11,7 +12,9 @@
     private Date               timestamp;
 
     public CompositeMaxDurationTrigger(Date timestamp, // this is the first duration that takes priority
-                                       Trigger trigger) {
+                                       Trigger trigger,
+                                       String[] calendarNames,
+                                       Calendars calendars) {
         this.timestamp = timestamp;
         this.trigger = trigger;
     }

Modified: 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	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CronTimer.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -7,6 +7,7 @@
 import java.text.ParseException;
 import java.util.Date;
 
+import org.drools.runtime.Calendars;
 import org.drools.time.Trigger;
 
 public class CronTimer
@@ -60,11 +61,15 @@
         return cronExpression;
     }
 
-    public Trigger createTrigger(long timestamp) {
+    public Trigger createTrigger(long timestamp,
+                                 String[] calendarNames,
+                                 Calendars calendars) {
         return new CronTrigger( timestamp,
                                 this.startTime,
                                 this.endTime,
-                                this.cronExpression );
+                                this.cronExpression,
+                                calendarNames,
+                                calendars );
     }
 
     @Override

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-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CronTrigger.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -1,10 +1,10 @@
 package org.drools.time.impl;
 
-import java.text.ParseException;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.TimeZone;
 
+import org.drools.runtime.Calendars;
 import org.drools.time.Trigger;
 
 public class CronTrigger implements Trigger {
@@ -17,25 +17,36 @@
     private Date nextFireTime = null;
     private Date previousFireTime = null;
     private transient TimeZone timeZone = null;   
+    private String[] calendarNames;
+    private Calendars calendars;
     
     
-    public CronTrigger(long timestamp, Date startTime, Date endTime, String cronExpression) {
-        this( timestamp, startTime, endTime, determineCronExpression( cronExpression ));
+    public CronTrigger(long timestamp, Date startTime, Date endTime, String cronExpression, String[] calendarNames, Calendars calendars) {
+        this( timestamp, startTime, endTime, determineCronExpression( cronExpression ), calendarNames, calendars);
     }
     
-    public CronTrigger(long timestamp, Date startTime, Date endTime, CronExpression cronExpression) {
+    public CronTrigger(long timestamp, Date startTime, Date endTime, CronExpression cronExpression, String[] calendarNames, Calendars calendars) {
         setCronExpression(cronExpression);
 
         if (startTime == null) {
             startTime = new Date(timestamp);
         }
         setStartTime(startTime);
+        
         if (endTime != null) {
             setEndTime(endTime);
         }
-        setTimeZone(TimeZone.getDefault());        
+        setTimeZone(TimeZone.getDefault());             
         
-        this.nextFireTime = getFireTimeAfter(new Date(getStartTime().getTime() - 1000l));        
+        // Set the first FireTime, this is sensitive to StartTime
+        this.nextFireTime = getFireTimeAfter(new Date(timestamp - 1000l));  
+        
+        this.calendarNames = calendarNames;
+        this.calendars = calendars;
+        
+        
+        // Update to next include time, if we have calendars
+        updateToNextIncludeDate( );
     }
     
     public Date getStartTime() {
@@ -201,6 +212,7 @@
     public Date nextFireTime() {
         Date date = this.nextFireTime;
         this.nextFireTime = getFireTimeAfter(this.nextFireTime);
+        updateToNextIncludeDate();
         return date;
     }
     
@@ -236,5 +248,34 @@
     protected Date getTimeAfter(Date afterTime) {
         return (cronEx == null) ? null : cronEx.getTimeAfter(afterTime);
     }    
+    
+    public void updateToNextIncludeDate() {
+        if ( calendarNames == null || calendarNames.length == 0 ) {
+            // There are no assigned calendars
+            return;
+        }
 
+        // If we have calendars, check we can fire, or get next time until we can fire.
+        while ( this.nextFireTime != null ) {
+            // this will loop forever if the trigger repeats forever and
+            // included calendar position cannot be found
+            boolean included = true;
+            for ( String calName : this.calendarNames ) {
+                // all calendars must not block, as soon as one blocks break, so we can check next time slot
+                org.drools.time.Calendar cal = this.calendars.get( calName );
+                if ( cal != null && !cal.isTimeIncluded( this.nextFireTime.getTime() ) ) {
+                    included = false;
+                    break;
+                }
+            }
+            if ( included == true ) {
+                // if no calendars blocked, break
+                break;
+            } else {
+                // otherwise increase the time and try again
+                this.nextFireTime = getTimeAfter( this.nextFireTime );
+            }
+        }
+    }    
+
 }

Modified: 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	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/DurationTimer.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -5,6 +5,7 @@
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 
+import org.drools.runtime.Calendars;
 import org.drools.time.Trigger;
 
 public class DurationTimer
@@ -34,8 +35,12 @@
         return duration;
     }
 
-    public Trigger createTrigger(long timestamp) {
-        return new PointInTimeTrigger( timestamp + duration );
+    public Trigger createTrigger(long timestamp,
+                                 String[] calendarNames,
+                                 Calendars calendars) {
+        return new PointInTimeTrigger( timestamp + duration,
+                                       calendarNames,
+                                       calendars );
     }
 
     @Override
@@ -55,5 +60,5 @@
         if ( duration != other.duration ) return false;
         return true;
     }
-   
+
 }

Modified: 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	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/IntervalTimer.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -6,6 +6,7 @@
 import java.io.ObjectOutput;
 import java.util.Date;
 
+import org.drools.runtime.Calendars;
 import org.drools.time.Trigger;
 
 public class IntervalTimer
@@ -62,10 +63,14 @@
         return period;
     }
 
-    public Trigger createTrigger(long timestamp) {
+    public Trigger createTrigger(long timestamp,
+                                 String[] calendarNames,
+                                 Calendars calendars) {
         return new IntervalTrigger( timestamp,
                                     delay,
-                                    period );
+                                    period,
+                                    calendarNames,
+                                    calendars );
     }
 
     @Override

Modified: 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	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/IntervalTrigger.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -8,13 +8,16 @@
 import java.io.ObjectOutput;
 import java.util.Date;
 
+import org.drools.runtime.Calendars;
 import org.drools.time.Trigger;
 
 public class IntervalTrigger
     implements
     Trigger {
-    private Date next;
+    private Date nextFireTime;
     private long period;
+    private String[] calendarNames;
+    private Calendars calendars;    
 
     public IntervalTrigger() {
 
@@ -22,36 +25,81 @@
 
     public IntervalTrigger(long currentTS,
                            long delay,
-                           long period) {
-        this.next = new Date( currentTS + delay );
+                           long period,
+                           String[] calendarNames,
+                           Calendars calendars) {
+        this.nextFireTime = new Date( currentTS + delay );
         this.period = period;
+        
+        this.calendarNames = calendarNames;
+        this.calendars = calendars;
+        
+        
+        // Update to next include time, if we have calendars
+        updateToNextIncludeDate( );         
     }
 
     public Date hasNextFireTime() {
-        return next;
+        return nextFireTime;
     }
 
     public Date nextFireTime() {
-        Date date = next;
+        Date date = nextFireTime;
+        // FIXME: this is not safe for serialization
+        this.nextFireTime = getTimeAfter();
+        updateToNextIncludeDate();
+        return date;
+    }
+    
+    private Date getTimeAfter() {
+        Date date;
         if ( this.period != 0 ) {
             // repeated fires for the given period
-            // FIXME: this is not safe for serialization
-            next = new Date( next.getTime() + this.period );
+            date = new Date( nextFireTime.getTime() + this.period );
         } else {
-            next = null;
+            date = null;
         }
         return date;
     }
 
     public void readExternal(ObjectInput in) throws IOException,
                                             ClassNotFoundException {
-        this.next = (Date) in.readObject();
+        this.nextFireTime = (Date) in.readObject();
         this.period = in.readLong();
     }
 
     public void writeExternal(ObjectOutput out) throws IOException {
-        out.writeObject( this.next );
+        out.writeObject( this.nextFireTime );
         out.writeLong( this.period );
     }
+    
+    public void updateToNextIncludeDate() {
+        if ( calendarNames == null || calendarNames.length == 0 ) {
+            // There are no assigned calendars
+            return;
+        }
 
+        // If we have calendars, check we can fire, or get next time until we can fire.
+        while ( this.nextFireTime != null ) {
+            // this will loop forever if the trigger repeats forever and
+            // included calendar position cannot be found
+            boolean included = true;
+            for ( String calName : this.calendarNames ) {
+                // all calendars must not block, as soon as one blocks break
+                org.drools.time.Calendar cal = this.calendars.get( calName );
+                if ( cal != null && !cal.isTimeIncluded( this.nextFireTime.getTime() ) ) {
+                    included = false;
+                    break;
+                }
+            }
+            if ( included == true ) {
+                // if no calendars blocked, break
+                break;
+            } else {
+                // otherwise increase the time and try again
+                this.nextFireTime = getTimeAfter( );
+            }
+        }
+    }       
+
 }
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/PointInTimeTrigger.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/PointInTimeTrigger.java	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/PointInTimeTrigger.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -21,6 +21,7 @@
 import java.io.ObjectOutput;
 import java.util.Date;
 
+import org.drools.runtime.Calendars;
 import org.drools.time.Trigger;
 
 public class PointInTimeTrigger
@@ -31,10 +32,28 @@
     public PointInTimeTrigger() {
     }
 
-    public PointInTimeTrigger(long timestamp) {
-        this.timestamp = new Date( timestamp );
+    public PointInTimeTrigger(long timestamp,
+                              String[] calendarNames,
+                              Calendars calendars) {
+        boolean included = true;
+
+        if ( calendarNames != null && calendarNames.length > 0 ) {
+            for ( String calName : calendarNames ) {
+                // all calendars must not block, as soon as one blocks break
+                org.drools.time.Calendar cal = calendars.get( calName );
+                if ( cal != null && !cal.isTimeIncluded( timestamp ) ) {
+                    included = false;
+                    break;
+                }
+            }
+        }
+
+        if ( included ) {
+            this.timestamp = new Date( timestamp );
+        }
+
     }
-    
+
     public Date hasNextFireTime() {
         return this.timestamp;
     }
@@ -53,4 +72,5 @@
     public void writeExternal(ObjectOutput out) throws IOException {
         out.writeObject( this.timestamp );
     }
+
 }
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/PseudoClockScheduler.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/PseudoClockScheduler.java	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/PseudoClockScheduler.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -185,9 +185,7 @@
             }
             // get next head
             item = queue.peek();
-        } 
-        
-
+        }
     }
 
     public synchronized long getTimeToNextJob() {

Modified: 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	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/Timer.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -1,7 +1,8 @@
 package org.drools.time.impl;
 
+import org.drools.runtime.Calendars;
 import org.drools.time.Trigger;
 
 public interface Timer {
-    Trigger createTrigger(long timestamp);
+    Trigger createTrigger(long timestamp, String[] calendarNames, Calendars calendars);
 }

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/time/impl/CronJobTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/time/impl/CronJobTest.java	2009-12-09 04:11:02 UTC (rev 30560)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/time/impl/CronJobTest.java	2009-12-09 05:58:00 UTC (rev 30561)
@@ -23,7 +23,7 @@
         
         timeService.advanceTime( date.getTime(), TimeUnit.MILLISECONDS );
         
-        CronTrigger trigger = new CronTrigger(date.getTime(), null, null, "15 * * * * ?");
+        CronTrigger trigger = new CronTrigger(date.getTime(), null, null, "15 * * * * ?", null, null);
         
         HelloWorldJobContext ctx = new HelloWorldJobContext( "hello world", timeService);
         timeService.scheduleJob( new HelloWorldJob(), ctx,  trigger);    



More information about the jboss-svn-commits mailing list