[jboss-svn-commits] JBL Code SVN: r24800 - in labs/jbossrules/trunk: drools-compiler/src/test/java/org/drools/integrationtests and 7 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Mon Jan 19 16:53:25 EST 2009


Author: tirelli
Date: 2009-01-19 16:53:24 -0500 (Mon, 19 Jan 2009)
New Revision: 24800

Modified:
   labs/jbossrules/trunk/drools-api/src/main/java/org/drools/time/SessionClock.java
   labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/CepEspTest.java
   labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.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/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/process/instance/timer/TimerManager.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/BuildContext.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/BuildUtils.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/reteoo/builder/ReteooRuleBuilder.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/Trigger.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/JDKTimerService.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/test/java/org/drools/time/impl/JDKTimerServiceTest.java
   labs/jbossrules/trunk/drools-examples/drools-examples-fusion/src/main/java/org/drools/examples/broker/events/EventFeeder.java
Log:
JBRULES-1920: fixing NOT delay calculation

Modified: labs/jbossrules/trunk/drools-api/src/main/java/org/drools/time/SessionClock.java
===================================================================
--- labs/jbossrules/trunk/drools-api/src/main/java/org/drools/time/SessionClock.java	2009-01-19 20:52:04 UTC (rev 24799)
+++ labs/jbossrules/trunk/drools-api/src/main/java/org/drools/time/SessionClock.java	2009-01-19 21:53:24 UTC (rev 24800)
@@ -26,7 +26,7 @@
     /**
      * Returns the current time. There is no semantics attached
      * to the long return value, so it will depend on the actual
-     * implementation. For isntance, for a real clock it may be
+     * implementation. For instance, for a real time clock it may be
      * milliseconds.
      * 
      * @return The current time. The unit of the time, depends on

Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/CepEspTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/CepEspTest.java	2009-01-19 20:52:04 UTC (rev 24799)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/CepEspTest.java	2009-01-19 21:53:24 UTC (rev 24800)
@@ -26,9 +26,10 @@
 import org.drools.compiler.DrlParser;
 import org.drools.compiler.DroolsParserException;
 import org.drools.compiler.PackageBuilder;
-import org.drools.integrationtests.eventgenerator.PseudoSessionClock;
 import org.drools.lang.descr.PackageDescr;
+import org.drools.rule.CompositeMaxDuration;
 import org.drools.rule.Package;
+import org.drools.rule.Rule;
 import org.drools.time.SessionPseudoClock;
 import org.drools.time.impl.PseudoClockScheduler;
 
@@ -873,7 +874,7 @@
 
     }
 
-    public void FIXME_testDelayingNot() throws Exception {
+    public void testDelayingNot() throws Exception {
         // read in the source
         final Reader reader = new InputStreamReader( getClass().getResourceAsStream( "test_CEP_DelayingNot.drl" ) );
         final RuleBaseConfiguration rbconf = new RuleBaseConfiguration();
@@ -881,6 +882,9 @@
         final RuleBase ruleBase = loadRuleBase( reader,
                                                 rbconf );
 
+        final Rule rule = ruleBase.getPackage( "org.drools" ).getRule( "Delaying Not" );
+        assertEquals( 10000,  rule.getDuration().getDuration( null ) );
+        
         SessionConfiguration conf = new SessionConfiguration();
         conf.setClockType( ClockType.PSEUDO_CLOCK );
         StatefulSession wm = ruleBase.newStatefulSession( conf );

Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java	2009-01-19 20:52:04 UTC (rev 24799)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java	2009-01-19 21:53:24 UTC (rev 24800)
@@ -16,9 +16,6 @@
  * limitations under the License.
  */
 
-import static org.mvel2.MVEL.executeExpression;
-import static org.mvel2.MVEL.parseMacros;
-
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.ObjectInput;
@@ -130,13 +127,6 @@
 import org.drools.spi.ConsequenceExceptionHandler;
 import org.drools.spi.GlobalResolver;
 import org.drools.xml.XmlDumper;
-import org.mvel2.Macro;
-import org.mvel2.ParserContext;
-import org.mvel2.ast.ASTNode;
-import org.mvel2.ast.WithNode;
-import org.mvel2.compiler.ExpressionCompiler;
-import org.mvel2.integration.Interceptor;
-import org.mvel2.integration.VariableResolverFactory;
 
 /** Run all the tests with the ReteOO engine implementation */
 public class MiscTest extends TestCase {
@@ -5957,7 +5947,4 @@
 		assertEquals(1, list.size());
 		assertEquals("Hello World", list.get(0));
     }
-    
-
-
 }

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-01-19 20:52:04 UTC (rev 24799)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultAgenda.java	2009-01-19 21:53:24 UTC (rev 24800)
@@ -280,9 +280,9 @@
      *            The item to schedule.
      */
     public void scheduleItem(final ScheduledAgendaItem item) {
-        // FIXME: should not use a static singleton
-        Scheduler.getInstance().scheduleAgendaItem( item,
-                                                    this );
+
+        Scheduler.scheduleAgendaItem( item,
+                                      this );
         this.scheduledActivations.add( item );
 
         // adds item to activation group if appropriate
@@ -418,8 +418,8 @@
 
     public void removeScheduleItem(final ScheduledAgendaItem item) {
         this.scheduledActivations.remove( item );
-        // FIXME: should not use a static singleton
-        Scheduler.getInstance().removeAgendaItem( item );
+        Scheduler.removeAgendaItem( item,
+                                    this );
     }
 
     public void addAgendaGroup(final AgendaGroup agendaGroup) {
@@ -679,7 +679,8 @@
         // reset scheduled activations
         if ( !this.scheduledActivations.isEmpty() ) {
             for ( ScheduledAgendaItem item = (ScheduledAgendaItem) this.scheduledActivations.removeFirst(); item != null; item = (ScheduledAgendaItem) this.scheduledActivations.removeFirst() ) {
-                Scheduler.getInstance().removeAgendaItem( item );
+                Scheduler.removeAgendaItem( item,
+                                            this );
             }
         }
 
@@ -712,7 +713,8 @@
         final EventSupport eventsupport = (EventSupport) this.workingMemory;
         if ( !this.scheduledActivations.isEmpty() ) {
             for ( ScheduledAgendaItem item = (ScheduledAgendaItem) this.scheduledActivations.removeFirst(); item != null; item = (ScheduledAgendaItem) this.scheduledActivations.removeFirst() ) {
-                Scheduler.getInstance().removeAgendaItem( item );
+                Scheduler.removeAgendaItem( item,
+                                            this );
                 eventsupport.getAgendaEventSupport().fireActivationCancelled( item,
                                                                               this.workingMemory,
                                                                               ActivationCancelledCause.CLEAR );
@@ -944,14 +946,14 @@
         }
 
         // if the tuple contains expired events 
-        for( LeftTuple tuple = (LeftTuple) activation.getTuple(); tuple != null; tuple = tuple.getParent() ) {
-            if( tuple.getLastHandle().isEvent() ) {
+        for ( LeftTuple tuple = (LeftTuple) activation.getTuple(); tuple != null; tuple = tuple.getParent() ) {
+            if ( tuple.getLastHandle().isEvent() ) {
                 EventFactHandle handle = (EventFactHandle) tuple.getLastHandle();
                 // handles "expire" only in stream mode.
-                if( handle.isExpired() ) {
+                if ( handle.isExpired() ) {
                     // decrease the activation count for the event
                     handle.decreaseActivationsCount();
-                    if( handle.getActivationsCount() == 0 ) {
+                    if ( handle.getActivationsCount() == 0 ) {
                         // and if no more activations, retract the handle
                         handle.getEntryPoint().retract( handle );
                     }
@@ -992,38 +994,39 @@
      * @inheritDoc
      */
     public boolean isRuleActiveInRuleFlowGroup(String ruleflowGroupName,
-                                                  String ruleName,
-                                                  long processInstanceId) {
+                                               String ruleName,
+                                               long processInstanceId) {
 
         RuleFlowGroup systemRuleFlowGroup = this.getRuleFlowGroup( ruleflowGroupName );
 
         for ( Iterator<RuleFlowGroupNode> activations = systemRuleFlowGroup.iterator(); activations.hasNext(); ) {
             Activation activation = activations.next().getActivation();
             if ( ruleName.equals( activation.getRule().getName() ) ) {
-            	if (checkProcessInstance(activation, processInstanceId)) {
-            		return true;
-            	}
+                if ( checkProcessInstance( activation,
+                                           processInstanceId ) ) {
+                    return true;
+                }
             }
         }
         return false;
     }
 
-    private boolean checkProcessInstance(Activation activation, long processInstanceId) {
-    	final Map<?, ?> declarations = activation.getSubRule().getOuterDeclarations();
-        for ( Iterator<?> it = declarations.values().iterator(); it.hasNext(); ) {
+    private boolean checkProcessInstance(Activation activation,
+                                         long processInstanceId) {
+        final Map< ? , ? > declarations = activation.getSubRule().getOuterDeclarations();
+        for ( Iterator< ? > it = declarations.values().iterator(); it.hasNext(); ) {
             Declaration declaration = (Declaration) it.next();
-            if ("processInstance".equals(declaration.getIdentifier())) {
-            	Object value = declaration.getValue(
-        			workingMemory,
-        			((InternalFactHandle) activation.getTuple().get(declaration)).getObject());
-            	if (value instanceof ProcessInstance) {
-            		return ((ProcessInstance) value).getId() == processInstanceId;
-            	}
-        	}
+            if ( "processInstance".equals( declaration.getIdentifier() ) ) {
+                Object value = declaration.getValue( workingMemory,
+                                                     ((InternalFactHandle) activation.getTuple().get( declaration )).getObject() );
+                if ( value instanceof ProcessInstance ) {
+                    return ((ProcessInstance) value).getId() == processInstanceId;
+                }
+            }
         }
         return true;
     }
-    
+
     public void addRuleFlowGroupListener(String ruleFlowGroup,
                                          RuleFlowGroupListener listener) {
         InternalRuleFlowGroup rfg = (InternalRuleFlowGroup) this.getRuleFlowGroup( ruleFlowGroup );

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-01-19 20:52:04 UTC (rev 24799)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalWorkingMemory.java	2009-01-19 21:53:24 UTC (rev 24800)
@@ -100,6 +100,12 @@
     
     public InternalFactHandle getInitialFactHandle();       
     
+    /**
+     * Returns the TimerService instance (session clock) for this
+     * session.
+     * 
+     * @return
+     */
     public TimerService getTimerService();
 
     /**

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-01-19 20:52:04 UTC (rev 24799)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/Scheduler.java	2009-01-19 21:53:24 UTC (rev 24800)
@@ -17,13 +17,12 @@
  */
 
 import org.drools.Agenda;
-import org.drools.ClockType;
 import org.drools.process.instance.timer.TimerManager.TimerTrigger;
 import org.drools.time.Job;
 import org.drools.time.JobContext;
 import org.drools.time.JobHandle;
-import org.drools.time.TimerService;
-import org.drools.time.TimerServiceFactory;
+import org.drools.time.Trigger;
+import org.drools.time.impl.PointInTimeTrigger;
 
 /**
  * Scheduler for rules requiring truth duration.
@@ -32,42 +31,12 @@
  */
 final class Scheduler {
     // ------------------------------------------------------------
-    // Class members
-    // ------------------------------------------------------------
-
-    /** Singleton instance. */
-    private static final Scheduler INSTANCE = new Scheduler();
-
-    // ------------------------------------------------------------
-    // Class methods
-    // ------------------------------------------------------------
-
-    /**
-     * Retrieve the singleton instance.
-     * 
-     * @return The singleton instance.
-     */
-    static Scheduler getInstance() {
-        return Scheduler.INSTANCE;
-    }
-
-    // ------------------------------------------------------------
-    // Instance members
-    // ------------------------------------------------------------
-
-    /** Alarm manager. */
-    private final TimerService timerService;
-
-    // ------------------------------------------------------------
     // Constructors
     // ------------------------------------------------------------
-
     /**
      * Construct.
      */
     private Scheduler() {
-        // FIXME: must use the session timer service
-        this.timerService = TimerServiceFactory.getTimerService( ClockType.REALTIME_CLOCK );
     }
 
     /**
@@ -78,18 +47,19 @@
      * @param workingMemory
      *            The working memory session.
      */
-    void scheduleAgendaItem(final ScheduledAgendaItem item, InternalAgenda agenda) {
+    public static void scheduleAgendaItem(final ScheduledAgendaItem item, InternalAgenda agenda) {
         DuractionJob job = new DuractionJob();        
         DuractionJobContext ctx = new DuractionJobContext( item, agenda );
-        TimerTrigger trigger = new TimerTrigger( item.getRule().getDuration().getDuration( item.getTuple() ), 0);
+        Trigger trigger = new PointInTimeTrigger( item.getRule().getDuration().getDuration( item.getTuple() ) +
+                                                       ((InternalWorkingMemory)agenda.getWorkingMemory()).getTimerService().getCurrentTime());
         
         
-        JobHandle jobHandle = this.timerService.scheduleJob( job, ctx, trigger );
+        JobHandle jobHandle = ((InternalWorkingMemory)agenda.getWorkingMemory()).getTimerService().scheduleJob( job, ctx, trigger );
         item.setJobHandle( jobHandle );
     }
     
-    public void removeAgendaItem(final ScheduledAgendaItem item) {
-        this.timerService.removeJob( item.getJobHandle() );
+    public static void removeAgendaItem(final ScheduledAgendaItem item, final InternalAgenda agenda) {
+        ((InternalWorkingMemory)agenda.getWorkingMemory()).getTimerService().removeJob( item.getJobHandle() );
     }    
     
     public static class DuractionJob implements Job {

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-01-19 20:52:04 UTC (rev 24799)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/process/instance/timer/TimerManager.java	2009-01-19 21:53:24 UTC (rev 24800)
@@ -45,7 +45,8 @@
 
         JobHandle jobHandle = this.timerService.scheduleJob( processJob,
                                                              ctx,
-                                                             new TimerTrigger( timer.getDelay(),
+                                                             new TimerTrigger( timerService.getCurrentTime(),
+                                                                               timer.getDelay(),
                                                                                timer.getPeriod() ) );
         timer.setJobHandle( jobHandle );
         timers.put(timer.getId(), timer);
@@ -74,7 +75,9 @@
 			}
 		}
 		JobHandle jobHandle = this.timerService.scheduleJob(
-			processJob, ctx, new TimerTrigger(delay, timer.getPeriod()));
+			processJob, ctx, new TimerTrigger(timerService.getCurrentTime(),
+                                              delay, 
+                                              timer.getPeriod()));
 		timer.setJobHandle(jobHandle);
 		timers.put(timer.getId(), timer);
 	}
@@ -142,43 +145,44 @@
     public static class TimerTrigger
         implements
         Trigger {
-        private long delay;
+        private Date next;
         private long period;
-        private int  count;
 
         public TimerTrigger() {
             
         }
         
-        public TimerTrigger(long delay,
+        public TimerTrigger(long currentTS,
+                            long delay,
                             long period) {
-            this.delay = delay;
+            this.next = new Date( currentTS + delay  );
             this.period = period;
         }
 
-        public Date getNextFireTime() {
-            Date date = null;
-            if ( count == 0 ) {
-                // initial delay before first fire
-                date = new Date( System.currentTimeMillis() + this.delay  );
-            } else if ( this.period != 0 ) {
+        public Date hasNextFireTime() {
+            return next;
+        }
+        
+        public Date nextFireTime() {
+            Date date = next;
+            if ( this.period != 0 ) {
                 // repeated fires for the given period
-                date = new Date( System.currentTimeMillis() + this.period );                
+                // FIXME: this is not safe for serialization
+                next = new Date( next.getTime() + this.period );                
+            } else {
+                next = null;
             }
-            count++;
             return date;
         }
 
         public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
-            this.delay = in.readLong();
+            this.next = (Date) in.readObject();
             this.period = in.readLong();
-            this.count = in.readInt();
         }
 
         public void writeExternal(ObjectOutput out) throws IOException {
-            out.writeLong( this.delay );
+            out.writeObject( this.next );
             out.writeLong( this.period );
-            out.writeInt(  this.count );
         }
 
     }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/BuildContext.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/BuildContext.java	2009-01-19 20:52:04 UTC (rev 24799)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/BuildContext.java	2009-01-19 21:53:24 UTC (rev 24800)
@@ -29,6 +29,7 @@
 import org.drools.reteoo.ReteooBuilder;
 import org.drools.rule.Behavior;
 import org.drools.rule.EntryPoint;
+import org.drools.rule.Rule;
 import org.drools.rule.RuleConditionElement;
 import org.drools.time.TemporalDependencyMatrix;
 
@@ -53,6 +54,9 @@
 
     // rule base to add rules to
     private InternalRuleBase                 rulebase;
+    
+    // rule being added at this moment
+    private Rule                             rule;
 
     // working memories attached to the given rulebase
     private InternalWorkingMemory[]          workingMemories;
@@ -96,6 +100,7 @@
     public BuildContext(final InternalRuleBase rulebase,
                         final ReteooBuilder.IdGenerator idGenerator) {
         this.rulebase = rulebase;
+        this.rule = rule;
 
         this.idGenerator = idGenerator;
 
@@ -278,7 +283,7 @@
         if ( this.buildstack == null ) {
             this.buildstack = new LinkedList<RuleConditionElement>();
         }
-        return this.buildstack.listIterator();
+        return this.buildstack.listIterator( this.buildstack.size() );
     }
 
     /**
@@ -416,4 +421,16 @@
         return this.temporal;
     }
 
+    public LinkedList<RuleConditionElement> getBuildStack() {
+        return this.buildstack;
+    }
+
+    public Rule getRule() {
+        return rule;
+    }
+
+    public void setRule(Rule rule) {
+        this.rule = rule;
+    }
+
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/BuildUtils.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/BuildUtils.java	2009-01-19 20:52:04 UTC (rev 24799)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/BuildUtils.java	2009-01-19 21:53:24 UTC (rev 24800)
@@ -238,13 +238,18 @@
                                          final Declaration[] declarations) throws InvalidPatternException {
         final List<String> list = new ArrayList<String>();
         for ( int i = 0, length = declarations.length; i < length; i++ ) {
+            boolean resolved = false;
             for ( final ListIterator<RuleConditionElement> it = context.stackIterator(); it.hasPrevious(); ) {
                 final RuleConditionElement rce = it.previous();
                 final Declaration decl = rce.resolveDeclaration( declarations[i].getIdentifier() );
-                if ( decl == null || decl.getPattern().getOffset() > declarations[i].getPattern().getOffset() ) {
-                    list.add( declarations[i].getIdentifier() );
+                if ( decl != null && decl.getPattern().getOffset() <= declarations[i].getPattern().getOffset() ) {
+                    resolved = true;
+                    break;
                 }
             }
+            if( ! resolved ) {
+                list.add( declarations[i].getIdentifier() );                
+            }
         }
 
         // Make sure the required declarations
@@ -255,7 +260,7 @@
                 buffer.append( ", " + list.get( i ) );
             }
 
-            throw new InvalidPatternException( "Required Declarations not bound: '" + buffer );
+            throw new InvalidPatternException( "Required Declarations not bound: '" + buffer + "'");
         }
     }
 

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-01-19 20:52:04 UTC (rev 24799)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/PatternBuilder.java	2009-01-19 21:53:24 UTC (rev 24800)
@@ -19,6 +19,7 @@
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.ListIterator;
 
 import org.drools.RuntimeDroolsException;
 import org.drools.RuleBaseConfiguration.EventProcessingMode;
@@ -32,15 +33,20 @@
 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;
+import org.drools.rule.GroupElement;
 import org.drools.rule.InvalidPatternException;
 import org.drools.rule.Pattern;
 import org.drools.rule.PatternSource;
 import org.drools.rule.RuleConditionElement;
 import org.drools.rule.TypeDeclaration;
+import org.drools.rule.VariableConstraint;
 import org.drools.spi.AlphaNodeFieldConstraint;
 import org.drools.spi.Constraint;
+import org.drools.spi.Duration;
 import org.drools.spi.ObjectType;
 
 /**
@@ -141,6 +147,9 @@
                                pattern,
                                betaConstraints );
 
+        // checks if this pattern is nested inside a NOT CE
+        final boolean isNegative = isNegative( context );
+        
         for ( final Iterator<?> it = constraints.iterator(); it.hasNext(); ) {
             final Object object = it.next();
             // Check if its a declaration
@@ -153,25 +162,49 @@
             if ( constraint.getType().equals( Constraint.ConstraintType.ALPHA ) ) {
                 alphaConstraints.add( constraint );
             } else if ( constraint.getType().equals( Constraint.ConstraintType.BETA ) ) {
-                utils.checkUnboundDeclarations( context,
-                                                constraint.getRequiredDeclarations() );
                 betaConstraints.add( constraint );
-                
-                if( pattern.getObjectType().isEvent() && constraint.isTemporal() ) {
-                    checkDelaying( context );
+                if( isNegative && pattern.getObjectType().isEvent() && constraint.isTemporal() ) {
+                    checkDelaying( context, constraint );
                 }
-                
             } else {
                 throw new RuntimeDroolsException( "Unknown constraint type: "+constraint.getType()+". This is a bug. Please contact development team.");
             }
         }
     }
 
-    private void checkDelaying( final BuildContext context ) {
-        //if( context.get)
-        
+    private void checkDelaying( final BuildContext context, final Constraint constraint ) {
+        if( constraint instanceof VariableConstraint ) {
+            // variable constraints always require a single declaration
+            Declaration target = constraint.getRequiredDeclarations()[0];
+            if( target.isPatternDeclaration() && target.getPattern().getObjectType().isEvent() ) {
+                long uplimit = ((VariableConstraint) constraint).getInterval().getUpperBound();
+                Duration dur = context.getRule().getDuration();
+                Duration newDur = new FixedDuration( uplimit ); 
+                if( dur instanceof CompositeMaxDuration ) {
+                    ((CompositeMaxDuration)dur).addDuration( newDur );
+                } else {
+                    if( dur == null ) {
+                        dur = newDur;
+                    } else {
+                        dur = new CompositeMaxDuration( dur );
+                        ((CompositeMaxDuration)dur).addDuration( newDur );
+                    }
+                    context.getRule().setDuration( dur );
+                }
+            }
+        }
     }
 
+    private boolean isNegative(final BuildContext context) {
+        for( ListIterator<RuleConditionElement> it = context.stackIterator(); it.hasPrevious(); ) {
+            RuleConditionElement rce = it.previous();
+            if( rce instanceof GroupElement && ((GroupElement)rce).isNot() ) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     public static ObjectTypeNode attachObjectTypeNode(BuildContext context,
                                                       ObjectType objectType) {
         synchronized ( context.getRuleBase().getPackagesMap() ) {

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/ReteooRuleBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/ReteooRuleBuilder.java	2009-01-19 20:52:04 UTC (rev 24799)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/ReteooRuleBuilder.java	2009-01-19 21:53:24 UTC (rev 24800)
@@ -40,7 +40,6 @@
 import org.drools.rule.Pattern;
 import org.drools.rule.Query;
 import org.drools.rule.Rule;
-import org.drools.time.Interval;
 import org.drools.time.TemporalDependencyMatrix;
 
 /**
@@ -103,6 +102,7 @@
             // creates a clean build context for each subrule
             final BuildContext context = new BuildContext( rulebase,
                                                            idGenerator );
+            context.setRule( rule );
             
             // if running in STREAM mode, calculate temporal distance for events
             if( EventProcessingMode.STREAM.equals( rulebase.getConfiguration().getEventProcessingMode() ) ) {

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/Trigger.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/Trigger.java	2009-01-19 20:52:04 UTC (rev 24799)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/Trigger.java	2009-01-19 21:53:24 UTC (rev 24800)
@@ -2,6 +2,31 @@
 
 import java.util.Date;
 
+/**
+ * A trigger interface for scheduling jobs
+ */
 public interface Trigger {
-    public Date getNextFireTime();
+    
+    /**
+     * This method is used to query the trigger about the existence of a
+     * possible next fire time, but WITHOUT changing any internal state 
+     * of the trigger.  In other words, this method MUST not have side
+     * effects. As an analogy, if a trigger was a stack, this method would
+     * be the equivalent of a "peek()" call.
+     * 
+     * @return the Date of the next fire time or null if there is no  
+     *         next fire time.
+     */
+    public Date hasNextFireTime();
+    
+    /**
+     * This method returns the date of the next fire time and updates
+     * the internal state of the Trigger to the following fire time
+     * if one exists. As an analogy, if a trigger was a stack, this method
+     * would be the equivalent of a "pop()" call.
+     * 
+     * @return the Date of the next fire time or null if there is no
+     *         next fire time.
+     */
+    public Date nextFireTime();
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/JDKTimerService.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/JDKTimerService.java	2009-01-19 20:52:04 UTC (rev 24799)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/JDKTimerService.java	2009-01-19 21:53:24 UTC (rev 24800)
@@ -43,7 +43,7 @@
     private ScheduledThreadPoolExecutor scheduler;
 
     public JDKTimerService() {
-        this( 3 );
+        this( 1 );
     }
 
     public JDKTimerService(int size) {
@@ -66,7 +66,7 @@
                                  Trigger trigger) {
         JDKJobHandle jobHandle = new JDKJobHandle();
 
-        Date date = trigger.getNextFireTime();
+        Date date = trigger.nextFireTime();
 
         if ( date != null ) {
             JDKCallableJob callableJob = new JDKCallableJob( job,
@@ -132,7 +132,7 @@
             this.job.execute( this.ctx );
 
             // our triggers allow for flexible rescheduling
-            Date date = this.trigger.getNextFireTime();
+            Date date = this.trigger.nextFireTime();
             if ( date != null ) {
                 ScheduledFuture<Void> future = schedule( date,
                                                          this,

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-01-19 20:52:04 UTC (rev 24799)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/PointInTimeTrigger.java	2009-01-19 21:53:24 UTC (rev 24800)
@@ -34,14 +34,15 @@
     public PointInTimeTrigger(long timestamp) {
         this.timestamp = new Date( timestamp );
     }
+    
+    public Date hasNextFireTime() {
+        return this.timestamp;
+    }
 
-    public Date getNextFireTime() {
-        if( timestamp != null) {
-            Date next = timestamp;
-            this.timestamp = null;
-            return next;
-        }
-        return null;
+    public Date nextFireTime() {
+        Date next = timestamp;
+        this.timestamp = null;
+        return next;
     }
 
     public void readExternal(ObjectInput in) throws IOException,

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-01-19 20:52:04 UTC (rev 24799)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/time/impl/PseudoClockScheduler.java	2009-01-19 21:53:24 UTC (rev 24800)
@@ -63,6 +63,7 @@
         this.session = session;
     }
 
+    @SuppressWarnings("unchecked")
     public void readExternal(ObjectInput in) throws IOException,
                                             ClassNotFoundException {
         timer = in.readLong();
@@ -98,7 +99,7 @@
                                  JobContext ctx,
                                  Trigger trigger) {
 
-        Date date = trigger.getNextFireTime();
+        Date date = trigger.hasNextFireTime();
 
         if ( date != null ) {
             ScheduledJob callableJob = new ScheduledJob( job,
@@ -157,9 +158,11 @@
 
     private void runCallBacks() {
         ScheduledJob item = queue.peek();
-        while ( item != null && item.getTrigger().getNextFireTime().getTime() <= this.timer ) {
+        while ( item != null && ( item.getTrigger().hasNextFireTime().getTime() <= this.timer ) ) {
             // remove the head
             queue.remove();
+            // updates the trigger
+            item.getTrigger().nextFireTime();
             try {
                 // execute the call
                 item.call();
@@ -204,7 +207,7 @@
         }
 
         public int compareTo(ScheduledJob o) {
-            return this.trigger.getNextFireTime().compareTo( o.getTrigger().getNextFireTime() );
+            return this.trigger.hasNextFireTime().compareTo( o.getTrigger().hasNextFireTime() );
         }
 
         public Void call() throws Exception {

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/time/impl/JDKTimerServiceTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/time/impl/JDKTimerServiceTest.java	2009-01-19 20:52:04 UTC (rev 24799)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/time/impl/JDKTimerServiceTest.java	2009-01-19 21:53:24 UTC (rev 24800)
@@ -110,36 +110,37 @@
 	}
 	
 	public static class DelayedTrigger implements Trigger {
-	    public Stack<Long> stack;
+	    private Stack<Date> stack;
 	    
 	    public DelayedTrigger(long delay) {
 	        this( new long[] { delay } );
 	    }
 	    
         public DelayedTrigger(long[] delay) {
-            this.stack = new Stack<Long>();
+            this.stack = new Stack<Date>();
             for( int i = delay.length-1; i >= 0; i-- ) {
-                this.stack.push( delay[i] );
+                this.stack.push( new Date( delay[i] ) );
             }
         }	    
 
-        public Date getNextFireTime() {
-            if ( !this.stack.isEmpty() ) {
-                return new Date( this.stack.pop() );    
-            } else {
-                return null;
-            }
+        public Date hasNextFireTime() {
+            return this.stack.isEmpty() ? null : this.stack.peek();
         }
+        
+        public Date nextFireTime() {
+            return this.stack.isEmpty() ? null : this.stack.pop();
+        }
 
         public void readExternal(ObjectInput in) throws IOException,
                                                 ClassNotFoundException {
-            // TODO Auto-generated method stub
+            // FIXME : not safe, since timestamps will be wrong
+            this.stack = (Stack<Date>) in.readObject();
             
         }
 
         public void writeExternal(ObjectOutput out) throws IOException {
-            // TODO Auto-generated method stub
-            
+            // FIXME : not safe, since timestamps will be wrong
+            out.writeObject( stack );
         }
 	    
 	}

Modified: labs/jbossrules/trunk/drools-examples/drools-examples-fusion/src/main/java/org/drools/examples/broker/events/EventFeeder.java
===================================================================
--- labs/jbossrules/trunk/drools-examples/drools-examples-fusion/src/main/java/org/drools/examples/broker/events/EventFeeder.java	2009-01-19 20:52:04 UTC (rev 24799)
+++ labs/jbossrules/trunk/drools-examples/drools-examples-fusion/src/main/java/org/drools/examples/broker/events/EventFeeder.java	2009-01-19 21:53:24 UTC (rev 24800)
@@ -31,12 +31,14 @@
  * @author etirelli
  */
 public class EventFeeder {
-    
-    private final TimerService clock;
-    private final EventSource source;
+
+    private final TimerService  clock;
+    private final EventSource   source;
     private final EventReceiver sink;
-    
-    public EventFeeder( final TimerService clock, final EventSource source, final EventReceiver sink ) {
+
+    public EventFeeder(final TimerService clock,
+                       final EventSource source,
+                       final EventReceiver sink) {
         this.clock = clock;
         this.source = source;
         this.sink = sink;
@@ -48,70 +50,98 @@
      * 
      */
     public void feed() {
-        if( source.hasNext() ) {
-            Event<?> event = source.getNext();
+        if ( source.hasNext() ) {
+            Event< ? > event = source.getNext();
             FeedContext context = new FeedContext( event );
             FeedTrigger trigger = new FeedTrigger();
             trigger.setNextFireTime( event.getDate() );
-            FeedJob job = new FeedJob( source, sink, trigger, clock );
-            clock.scheduleJob( job, context, trigger );
+            FeedJob job = new FeedJob( source,
+                                       sink,
+                                       trigger,
+                                       clock );
+            clock.scheduleJob( job,
+                               context,
+                               trigger );
         }
     }
-    
-    private static class FeedJob implements Job {
-        
-        private final EventSource source;
+
+    private static class FeedJob
+        implements
+        Job {
+
+        private final EventSource   source;
         private final EventReceiver sink;
-        private final FeedTrigger trigger;
-        private final TimerService clock;
-        
-        public FeedJob( final EventSource source, final EventReceiver sink, final FeedTrigger trigger, final TimerService clock ) {
+        private final FeedTrigger   trigger;
+        private final TimerService  clock;
+
+        public FeedJob(final EventSource source,
+                       final EventReceiver sink,
+                       final FeedTrigger trigger,
+                       final TimerService clock) {
             this.source = source;
             this.sink = sink;
             this.trigger = trigger;
             this.clock = clock;
         }
-        
+
         public void execute(JobContext context) {
-            this.sink.receive( ((FeedContext)context).event );
-            if( this.source.hasNext() ) {
-                ((FeedContext)context).setEvent( this.source.getNext() );
-                this.trigger.setNextFireTime( ((FeedContext)context).getEvent().getDate() );
-                clock.scheduleJob( this, context, trigger );
+            this.sink.receive( ((FeedContext) context).event );
+            if ( this.source.hasNext() ) {
+                ((FeedContext) context).setEvent( this.source.getNext() );
+                this.trigger.setNextFireTime( ((FeedContext) context).getEvent().getDate() );
+                clock.scheduleJob( this,
+                                   context,
+                                   trigger );
             }
         }
     }
-    
-    private static class FeedContext implements JobContext {
-        private JobHandle handle;
-        private Event<?> event;
-        
-        public FeedContext(Event<?> event) {
+
+    private static class FeedContext
+        implements
+        JobContext {
+        private JobHandle  handle;
+        private Event< ? > event;
+
+        public FeedContext(Event< ? > event) {
             super();
             this.event = event;
         }
+
         public JobHandle getJobHandle() {
             return this.handle;
         }
+
         public void setJobHandle(JobHandle handle) {
             this.handle = handle;
         }
-        public Event<?> getEvent() {
+
+        public Event< ? > getEvent() {
             return event;
         }
-        public void setEvent(Event<?> event) {
+
+        public void setEvent(Event< ? > event) {
             this.event = event;
         }
     }
-    
-    private static class FeedTrigger implements Trigger {
+
+    private static class FeedTrigger
+        implements
+        Trigger {
         private Date next;
-        public void setNextFireTime( Date date ) {
+
+        public void setNextFireTime(Date date) {
             this.next = date;
         }
-        public Date getNextFireTime() {
+
+        public Date hasNextFireTime() {
             return next;
         }
+
+        public Date nextFireTime() {
+            Date ret = next;
+            next = null;
+            return ret;
+        }
     }
-    
+
 }




More information about the jboss-svn-commits mailing list