[jboss-svn-commits] JBL Code SVN: r30566 - in labs/jbossrules/trunk: drools-core/src/main/java/org/drools/process/instance/timer and 2 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Wed Dec 9 15:50:53 EST 2009


Author: mark.proctor at jboss.com
Date: 2009-12-09 15:50:53 -0500 (Wed, 09 Dec 2009)
New Revision: 30566

Modified:
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/RuleBuilder.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/time/impl/CronTrigger.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-vsm/src/main/java/org/drools/vsm/remote/StatefulKnowledgeSessionRemoteClient.java
Log:
JBRULES-1944 Timer support
-added start end parsing capabilities
-missing tests and actual time limits

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 16:21:54 UTC (rev 30565)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/rule/builder/RuleBuilder.java	2009-12-09 20:50:53 UTC (rev 30566)
@@ -18,6 +18,7 @@
 
 import java.text.ParseException;
 import java.util.Calendar;
+import java.util.Date;
 import java.util.List;
 
 import org.drools.RuntimeDroolsException;
@@ -121,23 +122,7 @@
                 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() );
-                }
+                buildCalendars( rule, attributeDescr.getValue(), context );
             } else if ( name.equals( "date-effective" ) ) {
                 final Calendar cal = Calendar.getInstance();
                 cal.setTime( DateUtils.parseDate( attributeDescr.getValue() ) );
@@ -204,6 +189,26 @@
         }
     }
     
+    private void buildCalendars(Rule rule, String calendarsString, RuleBuildContext context) {
+        Object val = null;
+        try {
+            val = MVEL.eval( calendarsString );
+            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() );
+        }
+    }
+    
     private void buildTimer(Rule rule, String timerString, RuleBuildContext context) {
         if( timerString.indexOf( '(' ) >=0 ) {
             timerString = timerString.substring( timerString.indexOf( '(' )+1, timerString.lastIndexOf( ')' ) );
@@ -218,12 +223,44 @@
             protocol = timerString.substring( 0, colonPos );
         }
         
-        String body = timerString.substring( colonPos + 1 );
+        int startPos = timerString.indexOf( "start" );
+        int endPos = timerString.indexOf( "end" );
         
+        int  optionsPos = timerString.length();
+        
+        Date startDate = null;
+        Date endDate = null;
+        
+        if ( startPos != -1 && endPos != -1 ) {
+            // support case where someone puts end before start
+            if ( startPos < endPos ) {
+                // start is first
+                optionsPos = startPos;
+                int equalsPos = timerString.indexOf( '=', startPos );
+                startDate = DateUtils.parseDate( timerString.substring( equalsPos + 2, endPos ).trim() );                   
+            } else {
+                // end is first
+                optionsPos = endPos;   
+                int equalsPos = timerString.indexOf( '=', endPos );
+                startDate = DateUtils.parseDate( timerString.substring( equalsPos + 2, startPos ).trim() );                   
+            }
+        } else if ( startPos != -1 ) {
+            optionsPos = startPos;
+            int equalsPos = timerString.indexOf( '=', startPos );
+            startDate = DateUtils.parseDate( timerString.substring( equalsPos + 2 ).trim() );            
+        } else  if ( endPos != -1 ) {
+            optionsPos = endPos;   
+            int equalsPos = timerString.indexOf( '=', endPos );
+            endDate = DateUtils.parseDate( timerString.substring( equalsPos + 2 ).trim() );                
+        }
+              
+        
+        String body = timerString.substring( colonPos + 1, optionsPos ).trim();        
+        
         Timer timer = null;
         if ( "cron".equals( protocol ) ) {
             try {
-                timer = new CronTimer( null, null, new CronExpression( body ) );
+                timer = new CronTimer( startDate, endDate, new CronExpression( body ) );
             } catch ( ParseException e ) {
                 context.getErrors().add( "Unable to build set timer '" + timerString + "'");
                 return;
@@ -243,7 +280,7 @@
                 context.getErrors().add( "Incorrect number of arguments for interval timer '" + timerString + "'");
                 return;
             }
-            timer = new IntervalTimer(null, null, delay, period);
+            timer = new IntervalTimer(startDate, endDate, delay, period);
         } else {
             context.getErrors().add( "Protocol for timer does not exist '" + timerString +"'");
             return;

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 16:21:54 UTC (rev 30565)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/process/instance/timer/TimerManager.java	2009-12-09 20:50:53 UTC (rev 30566)
@@ -18,14 +18,15 @@
  * @author <a href="mailto:kris_verlaenen at hotmail.com">Kris Verlaenen</a>
  */
 public class TimerManager {
-    private long          timerId = 0;
+    private long                     timerId    = 0;
 
-    private WorkingMemory workingMemory;
-    private TimerService  timerService;
-    private Map<Long, TimerInstance> timers = new HashMap<Long, TimerInstance>();
-    private Job processJob = new ProcessJob();
+    private WorkingMemory            workingMemory;
+    private TimerService             timerService;
+    private Map<Long, TimerInstance> timers     = new HashMap<Long, TimerInstance>();
+    private Job                      processJob = new ProcessJob();
 
-    public TimerManager(WorkingMemory workingMemory, TimerService timerService) {
+    public TimerManager(WorkingMemory workingMemory,
+                        TimerService timerService) {
         this.workingMemory = workingMemory;
         this.timerService = timerService;
     }
@@ -33,9 +34,9 @@
     public void registerTimer(final TimerInstance timer,
                               ProcessInstance processInstance) {
         timer.setId( ++timerId );
-        timer.setProcessInstanceId(processInstance.getId());
-        timer.setActivated(new Date());
-        
+        timer.setProcessInstanceId( processInstance.getId() );
+        timer.setActivated( new Date() );
+
         ProcessJobContext ctx = new ProcessJobContext( timer,
                                                        processInstance.getId(),
                                                        this.workingMemory );
@@ -43,82 +44,92 @@
         JobHandle jobHandle = this.timerService.scheduleJob( processJob,
                                                              ctx,
                                                              new IntervalTrigger( timerService.getCurrentTime(),
-                                                                               timer.getDelay(),
-                                                                               timer.getPeriod(),
-                                                                               null,
-                                                                               null ) );
+                                                                                  null,
+                                                                                  null,
+                                                                                  timer.getDelay(),
+                                                                                  timer.getPeriod(),
+                                                                                  null,
+                                                                                  null ) );
         timer.setJobHandle( jobHandle );
-        timers.put(timer.getId(), timer);
+        timers.put( timer.getId(),
+                    timer );
     }
 
     public void internalAddTimer(final TimerInstance timer) {
-		ProcessJobContext ctx = new ProcessJobContext(
-			timer, timer.getProcessInstanceId(), this.workingMemory);
+        ProcessJobContext ctx = new ProcessJobContext( timer,
+                                                       timer.getProcessInstanceId(),
+                                                       this.workingMemory );
 
-		long delay;
-		Date lastTriggered = timer.getLastTriggered();
-		if (lastTriggered == null) {
-			Date activated = timer.getActivated();
-			Date now = new Date();
-			long timespan = now.getTime() - activated.getTime();
-			delay = timer.getDelay() - timespan;
-			if (delay < 0) {
-				delay = 0;
-			}
-		} else {
-			Date now = new Date();
-			long timespan = now.getTime() - lastTriggered.getTime();
-			delay = timespan - timer.getPeriod();
-			if (delay < 0) {
-				delay = 0;
-			}
-		}
-		JobHandle jobHandle = this.timerService.scheduleJob(
-			processJob, ctx, new IntervalTrigger(timerService.getCurrentTime(),
-                                              delay, 
-                                              timer.getPeriod(),
-                                              null,
-                                              null));
-		timer.setJobHandle(jobHandle);
-		timers.put(timer.getId(), timer);
-	}
+        long delay;
+        Date lastTriggered = timer.getLastTriggered();
+        if ( lastTriggered == null ) {
+            Date activated = timer.getActivated();
+            Date now = new Date();
+            long timespan = now.getTime() - activated.getTime();
+            delay = timer.getDelay() - timespan;
+            if ( delay < 0 ) {
+                delay = 0;
+            }
+        } else {
+            Date now = new Date();
+            long timespan = now.getTime() - lastTriggered.getTime();
+            delay = timespan - timer.getPeriod();
+            if ( delay < 0 ) {
+                delay = 0;
+            }
+        }
+        JobHandle jobHandle = this.timerService.scheduleJob( processJob,
+                                                             ctx,
+                                                             new IntervalTrigger( timerService.getCurrentTime(),
+                                                                                  null,
+                                                                                  null,
+                                                                                  delay,
+                                                                                  timer.getPeriod(),
+                                                                                  null,
+                                                                                  null ) );
+        timer.setJobHandle( jobHandle );
+        timers.put( timer.getId(),
+                    timer );
+    }
 
     public void cancelTimer(long timerId) {
-    	TimerInstance timer = timers.remove(timerId);
-    	if (timer != null) {
-    		timerService.removeJob( timer.getJobHandle() );
-    	}
+        TimerInstance timer = timers.remove( timerId );
+        if ( timer != null ) {
+            timerService.removeJob( timer.getJobHandle() );
+        }
     }
-    
+
     public void dispose() {
-    	for (TimerInstance timer: timers.values()) {
-    		timerService.removeJob( timer.getJobHandle() );
-    	}
-    	timerService.shutdown();
+        for ( TimerInstance timer : timers.values() ) {
+            timerService.removeJob( timer.getJobHandle() );
+        }
+        timerService.shutdown();
     }
-    
+
     public TimerService getTimerService() {
         return this.timerService;
     }
-    
+
     public Collection<TimerInstance> getTimers() {
-    	return timers.values();
+        return timers.values();
     }
-    
+
     public long internalGetTimerId() {
-    	return timerId;
+        return timerId;
     }
-    
+
     public void internalSetTimerId(long timerId) {
-    	this.timerId = timerId;
+        this.timerId = timerId;
     }
-    
+
     public void setTimerService(TimerService timerService) {
         this.timerService = timerService;
     }
 
-    public class ProcessJob implements Job {
-    	
+    public class ProcessJob
+        implements
+        Job {
+
         public void execute(JobContext c) {
             ProcessJobContext ctx = (ProcessJobContext) c;
 
@@ -128,13 +139,15 @@
             if ( processInstanceId == null ) {
                 throw new IllegalArgumentException( "Could not find process instance for timer " );
             }
-            
-            ctx.getTimer().setLastTriggered(new Date());
-            
-            workingMemory.getSignalManager().signalEvent(processInstanceId, "timerTriggered", ctx.getTimer());
 
-            if (ctx.getTimer().getPeriod() == 0) {
-            	TimerManager.this.timers.remove(ctx.getTimer().getId());
+            ctx.getTimer().setLastTriggered( new Date() );
+
+            workingMemory.getSignalManager().signalEvent( processInstanceId,
+                                                          "timerTriggered",
+                                                          ctx.getTimer() );
+
+            if ( ctx.getTimer().getPeriod() == 0 ) {
+                TimerManager.this.timers.remove( ctx.getTimer().getId() );
             }
         }
 

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 16:21:54 UTC (rev 30565)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/CronTrigger.java	2009-12-09 20:50:53 UTC (rev 30566)
@@ -39,7 +39,8 @@
         setTimeZone(TimeZone.getDefault());             
         
         // Set the first FireTime, this is sensitive to StartTime
-        this.nextFireTime = getFireTimeAfter(new Date(timestamp - 1000l));  
+        this.nextFireTime = new Date(timestamp - 1000l);
+        setFirstFireTimeAfter();
         
         this.calendarNames = calendarNames;
         this.calendars = calendars;
@@ -211,7 +212,7 @@
 
     public Date nextFireTime() {
         Date date = this.nextFireTime;
-        this.nextFireTime = getFireTimeAfter(this.nextFireTime);
+        this.nextFireTime = getTimeAfter(this.nextFireTime);
         updateToNextIncludeDate();
         return date;
     }
@@ -228,21 +229,21 @@
      * org.quartz.Calendar (if any)
      * </p>
      */
-    public Date getFireTimeAfter(Date afterTime) {
-        if (getStartTime().after(afterTime)) {
-            afterTime = new Date(getStartTime().getTime() - 1000l);
+    public void setFirstFireTimeAfter() {
+        if (getStartTime().after(this.nextFireTime)) {
+            this.nextFireTime = new Date(getStartTime().getTime() - 1000l);
         }
 
-        if (getEndTime() != null && (afterTime.compareTo(getEndTime()) >= 0)) {
-            return null;
+        if (getEndTime() != null && (this.nextFireTime.compareTo(getEndTime()) >= 0)) {
+            this.nextFireTime =  null;
         }
         
-        Date pot = getTimeAfter(afterTime);
+        Date pot = getTimeAfter(this.nextFireTime);
         if (getEndTime() != null && pot != null && pot.after(getEndTime())) {
-            return null;
+            this.nextFireTime = null;
+        } else {
+            this.nextFireTime = pot;
         }
-
-        return pot;
     }
     
     protected Date getTimeAfter(Date afterTime) {

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 16:21:54 UTC (rev 30565)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/IntervalTimer.java	2009-12-09 20:50:53 UTC (rev 30566)
@@ -67,8 +67,10 @@
                                  String[] calendarNames,
                                  Calendars calendars) {
         return new IntervalTrigger( timestamp,
-                                    delay,
-                                    period,
+                                    this.startTime,
+                                    this.endTime,
+                                    this.delay,
+                                    this.period,
                                     calendarNames,
                                     calendars );
     }

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 16:21:54 UTC (rev 30565)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/IntervalTrigger.java	2009-12-09 20:50:53 UTC (rev 30566)
@@ -6,6 +6,7 @@
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
+import java.util.Calendar;
 import java.util.Date;
 
 import org.drools.runtime.Calendars;
@@ -14,6 +15,8 @@
 public class IntervalTrigger
     implements
     Trigger {
+    private Date           startTime;
+    private Date           endTime;    
     private Date nextFireTime;
     private long period;
     private String[] calendarNames;
@@ -23,22 +26,98 @@
 
     }
 
-    public IntervalTrigger(long currentTS,
+    public IntervalTrigger(long timestamp,
+                           Date startTime,
+                           Date endTime,
                            long delay,
                            long period,
                            String[] calendarNames,
                            Calendars calendars) {
-        this.nextFireTime = new Date( currentTS + delay );
         this.period = period;
         
+        if (startTime == null) {
+            startTime = new Date(timestamp);
+        }
+        setStartTime(startTime);
+        
+        if (endTime != null) {
+            setEndTime(endTime);
+        }     
+                
         this.calendarNames = calendarNames;
         this.calendars = calendars;
         
+        this.nextFireTime = new Date( timestamp + delay );
         
+        setFirstFireTime();
+        
         // Update to next include time, if we have calendars
         updateToNextIncludeDate( );         
     }
+    
+    public Date getStartTime() {
+        return this.startTime;
+    }    
+    
+    public void setStartTime(Date startTime) {
+        if (startTime == null) {
+            throw new IllegalArgumentException("Start time cannot be null");
+        }
 
+        Date eTime = getEndTime();
+        if (eTime != null && startTime != null && eTime.before(startTime)) {
+            throw new IllegalArgumentException(
+                "End time cannot be before start time");
+        }
+        
+        // round off millisecond...
+        // Note timeZone is not needed here as parameter for
+        // Calendar.getInstance(),
+        // since time zone is implicit when using a Date in the setTime method.
+        Calendar cl = Calendar.getInstance();
+        cl.setTime(startTime);
+        cl.set(Calendar.MILLISECOND, 0);
+
+        this.startTime = cl.getTime();
+    }
+
+    /**
+     * <p>
+     * Get the time at which the <code>CronTrigger</code> should quit
+     * repeating - even if repeastCount isn't yet satisfied.
+     * </p>
+     * 
+     * @see #getFinalFireTime()
+     */
+    public Date getEndTime() {
+        return this.endTime;
+    }
+
+    public void setEndTime(Date endTime) {
+        Date sTime = getStartTime();
+        if (sTime != null && endTime != null && sTime.after(endTime)) {
+            throw new IllegalArgumentException(
+                    "End time cannot be before start time");
+        }
+
+        this.endTime = endTime;
+    }
+    
+    public void setFirstFireTime() {
+        if (getStartTime().after(this.nextFireTime)) {
+            this.nextFireTime = new Date(getStartTime().getTime() - 1000l);
+        }
+
+        if (getEndTime() != null && (this.nextFireTime.compareTo(getEndTime()) >= 0)) {
+            this.nextFireTime = null;
+        }
+        
+        Date pot = getTimeAfter();
+        if (getEndTime() != null && pot != null && pot.after(getEndTime())) {
+            this.nextFireTime = null;
+        }
+    }    
+
     public Date hasNextFireTime() {
         return nextFireTime;
     }

Modified: labs/jbossrules/trunk/drools-vsm/src/main/java/org/drools/vsm/remote/StatefulKnowledgeSessionRemoteClient.java
===================================================================
--- labs/jbossrules/trunk/drools-vsm/src/main/java/org/drools/vsm/remote/StatefulKnowledgeSessionRemoteClient.java	2009-12-09 16:21:54 UTC (rev 30565)
+++ labs/jbossrules/trunk/drools-vsm/src/main/java/org/drools/vsm/remote/StatefulKnowledgeSessionRemoteClient.java	2009-12-09 20:50:53 UTC (rev 30566)
@@ -11,6 +11,7 @@
 import org.drools.event.process.ProcessEventListener;
 import org.drools.event.rule.AgendaEventListener;
 import org.drools.event.rule.WorkingMemoryEventListener;
+import org.drools.runtime.Calendars;
 import org.drools.runtime.Environment;
 import org.drools.runtime.ExecutionResults;
 import org.drools.runtime.ExitPoint;
@@ -347,4 +348,9 @@
         
     }
 
+    public Calendars getCalendars() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
 }



More information about the jboss-svn-commits mailing list