[jboss-svn-commits] JBL Code SVN: r37795 - labs/jbossrules/soa_branches/BRMS-5.1-GA_BZ-761715/drools-core/src/main/java/org/drools/common.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Wed Dec 14 09:12:19 EST 2011
Author: tsurdilovic
Date: 2011-12-14 09:12:18 -0500 (Wed, 14 Dec 2011)
New Revision: 37795
Modified:
labs/jbossrules/soa_branches/BRMS-5.1-GA_BZ-761715/drools-core/src/main/java/org/drools/common/DefaultAgenda.java
Log:
fix for BZ-761715
Modified: labs/jbossrules/soa_branches/BRMS-5.1-GA_BZ-761715/drools-core/src/main/java/org/drools/common/DefaultAgenda.java
===================================================================
--- labs/jbossrules/soa_branches/BRMS-5.1-GA_BZ-761715/drools-core/src/main/java/org/drools/common/DefaultAgenda.java 2011-12-14 13:17:08 UTC (rev 37794)
+++ labs/jbossrules/soa_branches/BRMS-5.1-GA_BZ-761715/drools-core/src/main/java/org/drools/common/DefaultAgenda.java 2011-12-14 14:12:18 UTC (rev 37795)
@@ -1,1106 +1,1109 @@
-/**
- * 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.
- */
-
-package org.drools.common;
-
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.drools.WorkingMemory;
-import org.drools.base.DefaultKnowledgeHelper;
-import org.drools.base.SequentialKnowledgeHelper;
-import org.drools.common.RuleFlowGroupImpl.DeactivateCallback;
-import org.drools.core.util.ClassUtils;
-import org.drools.core.util.LinkedListNode;
-import org.drools.event.rule.ActivationCancelledCause;
-import org.drools.impl.StatefulKnowledgeSessionImpl;
-import org.drools.process.instance.ProcessInstance;
-import org.drools.reteoo.LeftTuple;
-import org.drools.reteoo.ReteooWorkingMemory;
-import org.drools.rule.Declaration;
-import org.drools.rule.GroupElement;
-import org.drools.rule.Rule;
-import org.drools.spi.Activation;
-import org.drools.spi.ActivationGroup;
-import org.drools.spi.AgendaFilter;
-import org.drools.spi.AgendaGroup;
-import org.drools.spi.ConsequenceException;
-import org.drools.spi.ConsequenceExceptionHandler;
-import org.drools.spi.KnowledgeHelper;
-import org.drools.spi.PropagationContext;
-import org.drools.spi.RuleFlowGroup;
-import org.drools.spi.Tuple;
-
-/**
- * Rule-firing Agenda.
- *
- * <p>
- * Since many rules may be matched by a single assertObject(...) all scheduled
- * actions are placed into the <code>Agenda</code>.
- * </p>
- *
- * <p>
- * While processing a scheduled action, it may update or retract objects in
- * other scheduled actions, which must then be removed from the agenda.
- * Non-invalidated actions are left on the agenda, and are executed in turn.
- * </p>
- *
- * @author <a href="mailto:bob at eng.werken.com">bob mcwhirter </a>
- * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
- */
-public class DefaultAgenda
- implements
- Externalizable,
- InternalAgenda {
- // ------------------------------------------------------------
- // Instance members
- // ------------------------------------------------------------
-
- /**
- *
- */
- private static final long serialVersionUID = 510l;
-
- /** Working memory of this Agenda. */
- private InternalWorkingMemory workingMemory;
-
- private org.drools.core.util.LinkedList scheduledActivations;
-
- /** Items time-delayed. */
-
- private Map<String, InternalAgendaGroup> agendaGroups;
-
- private Map<String, ActivationGroup> activationGroups;
-
- private Map<String, RuleFlowGroup> ruleFlowGroups;
-
- private LinkedList<AgendaGroup> focusStack;
-
- private InternalAgendaGroup currentModule;
-
- private InternalAgendaGroup main;
-
- private AgendaGroupFactory agendaGroupFactory;
-
- private KnowledgeHelper knowledgeHelper;
-
- public int activeActivations;
-
- public int dormantActivations;
-
- private ConsequenceExceptionHandler legacyConsequenceExceptionHandler;
-
- private org.drools.runtime.rule.ConsequenceExceptionHandler consequenceExceptionHandler;
-
- protected volatile AtomicBoolean halt = new AtomicBoolean( false );
-
- private int activationCounter;
-
- // ------------------------------------------------------------
- // Constructors
- // ------------------------------------------------------------
- public DefaultAgenda() {
- }
-
- /**
- * Construct.
- *
- * @param workingMemory
- * The <code>WorkingMemory</code> of this agenda.
- * @param conflictResolver
- * The conflict resolver.
- */
- public DefaultAgenda(InternalRuleBase rb) {
- this( rb,
- true );
- }
-
- /**
- * Construct.
- *
- * @param workingMemory
- * The <code>WorkingMemory</code> of this agenda.
- * @param conflictResolver
- * The conflict resolver.
- */
- public DefaultAgenda(InternalRuleBase rb,
- boolean initMain) {
-
- this.agendaGroups = new HashMap<String, InternalAgendaGroup>();
- this.activationGroups = new HashMap<String, ActivationGroup>();
- this.ruleFlowGroups = new HashMap<String, RuleFlowGroup>();
- this.focusStack = new LinkedList<AgendaGroup>();
- this.scheduledActivations = new org.drools.core.util.LinkedList();
- this.agendaGroupFactory = rb.getConfiguration().getAgendaGroupFactory();
-
- if ( initMain ) {
- // MAIN should always be the first AgendaGroup and can never be
- // removed
- this.main = agendaGroupFactory.createAgendaGroup( AgendaGroup.MAIN,
- rb );
-
- this.agendaGroups.put( AgendaGroup.MAIN,
- this.main );
-
- this.focusStack.add( this.main );
- }
- Object object = ClassUtils.instantiateObject( rb.getConfiguration().getConsequenceExceptionHandler(),
- rb.getConfiguration().getClassLoader() );
- if ( object instanceof ConsequenceExceptionHandler ) {
- this.legacyConsequenceExceptionHandler = (ConsequenceExceptionHandler) object;
- } else {
- this.consequenceExceptionHandler = (org.drools.runtime.rule.ConsequenceExceptionHandler) object;
- }
- }
-
- public AgendaItem createAgendaItem(final Tuple tuple,
- final int salience,
- final PropagationContext context,
- final Rule rule,
- final GroupElement subrule) {
- return new AgendaItem( activationCounter++,
- tuple,
- salience,
- context,
- rule,
- subrule );
- }
-
- public ScheduledAgendaItem createScheduledAgendaItem(final Tuple tuple,
- final PropagationContext context,
- final Rule rule,
- final GroupElement subrule) {
- return new ScheduledAgendaItem( activationCounter++,
- tuple,
- this,
- context,
- rule,
- subrule );
- }
-
- public void setWorkingMemory(final InternalWorkingMemory workingMemory) {
- this.workingMemory = workingMemory;
- if ( ((InternalRuleBase) this.workingMemory.getRuleBase()).getConfiguration().isSequential() ) {
- this.knowledgeHelper = new SequentialKnowledgeHelper( this.workingMemory );
- } else {
- this.knowledgeHelper = new DefaultKnowledgeHelper( this.workingMemory );
- }
- }
-
- // public void write(WMSerialisationOutContext context) throws IOException {
- // BinaryHeapQueueAgendaGroup[] agendaGroups = (BinaryHeapQueueAgendaGroup[]) this.agendaGroups.values().toArray( new AgendaGroup[this.agendaGroups.size()] );
- // Arrays.sort( agendaGroups,
- // AgendaGroupSorter.instance );
- //
- // for ( BinaryHeapQueueAgendaGroup group : agendaGroups ) {
- // context.writeInt( PersisterEnums.AGENDA_GROUP );
- // group.write( context );
- // }
- // context.writeInt( PersisterEnums.END );
- //
- // for ( ListIterator it = this.focusStack.listIterator( this.focusStack.size() - 1 ); it.hasPrevious(); ) {
- // AgendaGroup group = (AgendaGroup) it.previous();
- // context.writeInt( PersisterEnums.AGENDA_GROUP );
- // context.writeUTF( group.getName() );
- // }
- // context.writeInt( PersisterEnums.END );
- //
- // RuleFlowGroupImpl[] ruleFlowGroups = (RuleFlowGroupImpl[]) this.ruleFlowGroups.values().toArray( new RuleFlowGroupImpl[this.ruleFlowGroups.size()] );
- // Arrays.sort( agendaGroups,
- // AgendaGroupSorter.instance );
- //
- // for ( BinaryHeapQueueAgendaGroup group : agendaGroups ) {
- // context.writeInt( PersisterEnums.RULE_FLOW_GROUP );
- // group.write( context );
- // }
- // context.writeInt( PersisterEnums.END );
- // }
-
- // public static class AgendaGroupSorter
- // implements
- // Comparator<AgendaGroup> {
- // public static final AgendaGroupSorter instance = new AgendaGroupSorter();
- //
- // public int compare(AgendaGroup group1,
- // AgendaGroup group2) {
- // return group1.getName().compareTo( group2.getName() );
- // }
- // }
- //
- // public static class RuleFlowGroupSorter
- // implements
- // Comparator<AgendaGroup> {
- // public static final AgendaGroupSorter instance = new AgendaGroupSorter();
- //
- // public int compare(AgendaGroup group1,
- // AgendaGroup group2) {
- // return group1.getName().compareTo( group2.getName() );
- // }
- // }
-
- public void readExternal(ObjectInput in) throws IOException,
- ClassNotFoundException {
- workingMemory = (InternalWorkingMemory) in.readObject();
- scheduledActivations = (org.drools.core.util.LinkedList) in.readObject();
- agendaGroups = (Map) in.readObject();
- activationGroups = (Map) in.readObject();
- ruleFlowGroups = (Map) in.readObject();
- focusStack = (LinkedList) in.readObject();
- currentModule = (InternalAgendaGroup) in.readObject();
- main = (InternalAgendaGroup) in.readObject();
- agendaGroupFactory = (AgendaGroupFactory) in.readObject();
- knowledgeHelper = (KnowledgeHelper) in.readObject();
- activeActivations = in.readInt();
- dormantActivations = in.readInt();
- legacyConsequenceExceptionHandler = (ConsequenceExceptionHandler) in.readObject();
- }
-
- public void writeExternal(ObjectOutput out) throws IOException {
- out.writeObject( workingMemory );
- out.writeObject( scheduledActivations );
- out.writeObject( agendaGroups );
- out.writeObject( activationGroups );
- out.writeObject( ruleFlowGroups );
- out.writeObject( focusStack );
- out.writeObject( currentModule );
- out.writeObject( main );
- out.writeObject( agendaGroupFactory );
- out.writeObject( knowledgeHelper );
- out.writeInt( activeActivations );
- out.writeInt( dormantActivations );
- out.writeObject( legacyConsequenceExceptionHandler );
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#getWorkingMemory()
- */
- public WorkingMemory getWorkingMemory() {
- return this.workingMemory;
- }
-
- /**
- * Schedule an agenda item for delayed firing.
- *
- * @param item
- * The item to schedule.
- */
- public void scheduleItem(final ScheduledAgendaItem item, final InternalWorkingMemory wm) {
-
- Scheduler.scheduleAgendaItem( item,
- this,
- wm );
- this.scheduledActivations.add( item );
-
- // adds item to activation group if appropriate
- addItemToActivationGroup( item );
-
- }
-
- /**
- * If the item belongs to an activation group, add it
- *
- * @param item
- */
- private void addItemToActivationGroup(final AgendaItem item) {
- String group = item.getRule().getActivationGroup();
- if ( group != null && group.length() > 0 ) {
- this.getActivationGroup( group ).addActivation( item );
- }
- }
-
- /**
- * @inheritDoc
- */
- public boolean addActivation(final AgendaItem activation) {
- // set the focus if rule autoFocus is true
- if ( activation.getRule().getAutoFocus() ) {
- this.setFocus( activation.getRule().getAgendaGroup() );
- }
-
- // adds item to activation group if appropriate
- addItemToActivationGroup( activation );
-
- InternalAgendaGroup agendaGroup = (InternalAgendaGroup) this.getAgendaGroup( activation.getRule().getAgendaGroup() );
- activation.setAgendaGroup( agendaGroup );
-
- if ( activation.getRule().getRuleFlowGroup() == null ) {
- // No RuleFlowNode so add it directly to the Agenda
-
- // do not add the activation if the rule is "lock-on-active" and the
- // AgendaGroup is active
- if ( activation.getRule().isLockOnActive() && agendaGroup.isActive() ) {
- return false;
- }
-
- agendaGroup.add( activation );
- } else {
- // There is a RuleFlowNode so add it there, instead of the Agenda
- InternalRuleFlowGroup rfg = (InternalRuleFlowGroup) this.getRuleFlowGroup( activation.getRule().getRuleFlowGroup() );
-
- // do not add the activation if the rule is "lock-on-active" and the
- // RuleFlowGroup is active
- if ( activation.getRule().isLockOnActive() && rfg.isActive() ) {
- return false;
- }
-
- rfg.addActivation( activation );
- }
-
- // making sure we re-evaluate agenda in case we are waiting for activations
- synchronized ( this.halt ) {
- this.halt.notifyAll();
- }
- return true;
-
- }
-
- public void removeScheduleItem(final ScheduledAgendaItem item) {
- this.scheduledActivations.remove( item );
- Scheduler.removeAgendaItem( item,
- this );
- }
-
- public void addAgendaGroup(final AgendaGroup agendaGroup) {
- this.agendaGroups.put( agendaGroup.getName(),
- (InternalAgendaGroup) agendaGroup );
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#setFocus(org.drools.spi.AgendaGroup)
- */
- public boolean setFocus(final AgendaGroup agendaGroup) {
- // Set the focus to the agendaGroup if it doesn't already have the focus
- if ( this.focusStack.getLast() != agendaGroup ) {
- ((InternalAgendaGroup) this.focusStack.getLast()).setActive( false );
- this.focusStack.add( agendaGroup );
- ((InternalAgendaGroup) agendaGroup).setActive( true );
- final EventSupport eventsupport = (EventSupport) this.workingMemory;
- eventsupport.getAgendaEventSupport().fireAgendaGroupPushed( agendaGroup,
- this.workingMemory );
- return true;
- } else {
- return false;
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#setFocus(java.lang.String)
- */
- public void setFocus(final String name) {
- AgendaGroup agendaGroup = getAgendaGroup( name );
- setFocus( agendaGroup );
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#getFocus()
- */
- public AgendaGroup getFocus() {
- return (AgendaGroup) this.focusStack.getLast();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#getNextFocus()
- */
- public AgendaGroup getNextFocus() {
- InternalAgendaGroup agendaGroup = null;
- // Iterate until we find a populate AgendaModule or we reach the MAIN,
- // default, AgendaGroup
- while ( true ) {
- agendaGroup = (InternalAgendaGroup) this.focusStack.getLast();
-
- final boolean empty = agendaGroup.isEmpty();
-
- // No populated queues found so pop the focusStack and repeat
- if ( empty && (this.focusStack.size() > 1) ) {
- agendaGroup.setActive( false );
- this.focusStack.removeLast();
- final EventSupport eventsupport = (EventSupport) this.workingMemory;
- eventsupport.getAgendaEventSupport().fireAgendaGroupPopped( agendaGroup,
- this.workingMemory );
- } else {
- agendaGroup = (empty) ? null : agendaGroup;
- break;
- }
- }
-
- if ( agendaGroup != null ) {
- agendaGroup.setActive( true );
- }
- return agendaGroup;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#setCurrentAgendaGroup(org.drools.spi.AgendaGroup)
- */
- public void setCurrentAgendaGroup(final InternalAgendaGroup agendaGroup) {
- this.currentModule = agendaGroup;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#getCurrentAgendaGroup()
- */
- public AgendaGroup getCurrentAgendaGroup() {
- return this.currentModule;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#getAgendaGroup(java.lang.String)
- */
- public AgendaGroup getAgendaGroup(final String name) {
- String groupName = (name == null || name.length() == 0) ? AgendaGroup.MAIN : name;
-
- AgendaGroup agendaGroup = (AgendaGroup) this.agendaGroups.get( groupName );
- if ( agendaGroup == null ) {
- // The AgendaGroup is defined but not yet added to the
- // Agenda, so create the AgendaGroup and add to the Agenda.
- agendaGroup = agendaGroupFactory.createAgendaGroup( name,
- ((InternalRuleBase) this.workingMemory.getRuleBase()) );
- addAgendaGroup( agendaGroup );
- }
- return agendaGroup;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#getAgendaGroups()
- */
- public AgendaGroup[] getAgendaGroups() {
- return (AgendaGroup[]) this.agendaGroups.values().toArray( new AgendaGroup[this.agendaGroups.size()] );
- }
-
- public Map<String, InternalAgendaGroup> getAgendaGroupsMap() {
- return this.agendaGroups;
- }
-
- public InternalAgendaGroup getMainAgendaGroup() {
- if ( this.main == null ) {
- this.main = (InternalAgendaGroup) getAgendaGroup( AgendaGroup.MAIN );
- }
-
- return this.main;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#getStack()
- */
- public AgendaGroup[] getStack() {
- return (AgendaGroup[]) this.focusStack.toArray( new AgendaGroup[this.focusStack.size()] );
- }
-
- public LinkedList<AgendaGroup> getStackList() {
- return this.focusStack;
- }
-
- public Map<String, RuleFlowGroup> getRuleFlowGroupsMap() {
- return this.ruleFlowGroups;
- }
-
- public Map<String, ActivationGroup> getActivationGroupsMap() {
- return this.activationGroups;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#getActivationGroup(java.lang.String)
- */
- public ActivationGroup getActivationGroup(final String name) {
- ActivationGroupImpl activationGroup = (ActivationGroupImpl) this.activationGroups.get( name );
- if ( activationGroup == null ) {
- activationGroup = new ActivationGroupImpl( name );
- this.activationGroups.put( name,
- activationGroup );
- }
- return activationGroup;
- }
-
- public RuleFlowGroup getRuleFlowGroup(final String name) {
- RuleFlowGroup ruleFlowGroup = (RuleFlowGroup) this.ruleFlowGroups.get( name );
- if ( ruleFlowGroup == null ) {
- ruleFlowGroup = new RuleFlowGroupImpl( name );
- ((InternalRuleFlowGroup) ruleFlowGroup).setWorkingMemory( (InternalWorkingMemory) getWorkingMemory() );
- this.ruleFlowGroups.put( name,
- ruleFlowGroup );
- }
- return ruleFlowGroup;
- }
-
- public void activateRuleFlowGroup(final String name) {
- ((InternalRuleFlowGroup) getRuleFlowGroup( name )).setActive( true );
- }
-
- public void activateRuleFlowGroup(final String name, long processInstanceId, String nodeInstanceId) {
- InternalRuleFlowGroup ruleFlowGroup = (InternalRuleFlowGroup) getRuleFlowGroup( name );
- ruleFlowGroup.addNodeInstance(processInstanceId, nodeInstanceId);
- ruleFlowGroup.setActive( true );
- }
-
- public void deactivateRuleFlowGroup(final String name) {
- ((InternalRuleFlowGroup) getRuleFlowGroup( name )).setActive( false );
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#focusStackSize()
- */
- public int focusStackSize() {
- int size = 0;
- for ( final java.util.Iterator iterator = this.focusStack.iterator(); iterator.hasNext(); ) {
- final AgendaGroup group = (AgendaGroup) iterator.next();
- size += group.size();
- }
- return size;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#agendaSize()
- */
- public int agendaSize() {
- int size = 0;
- for ( final java.util.Iterator iterator = this.agendaGroups.values().iterator(); iterator.hasNext(); ) {
- final AgendaGroup group = (AgendaGroup) iterator.next();
- size += group.size();
- }
- return size;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#getActivations()
- */
- public Activation[] getActivations() {
- final List list = new ArrayList();
- for ( final java.util.Iterator it = this.agendaGroups.values().iterator(); it.hasNext(); ) {
- final AgendaGroup group = (AgendaGroup) it.next();
- list.addAll( Arrays.asList( group.getActivations() ) );
- }
- return (Activation[]) list.toArray( new Activation[list.size()] );
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#getScheduledActivations()
- */
- public Activation[] getScheduledActivations() {
- final List list = new ArrayList( this.scheduledActivations.size() );
- for ( LinkedListNode node = this.scheduledActivations.getFirst(); node != null; node = node.getNext() ) {
- list.add( node );
- }
- return (Activation[]) list.toArray( new Activation[list.size()] );
- }
-
- public org.drools.core.util.LinkedList getScheduledActivationsLinkedList() {
- return this.scheduledActivations;
- }
-
- public void clear() {
- // reset focus stack
- this.focusStack.clear();
- this.focusStack.add( getMainAgendaGroup() );
-
- // reset scheduled activations
- if ( !this.scheduledActivations.isEmpty() ) {
- for ( ScheduledAgendaItem item = (ScheduledAgendaItem) this.scheduledActivations.removeFirst(); item != null; item = (ScheduledAgendaItem) this.scheduledActivations.removeFirst() ) {
- Scheduler.removeAgendaItem( item,
- this );
- }
- }
-
- //reset all agenda groups
- for ( InternalAgendaGroup group : this.agendaGroups.values() ) {
- group.clear();
- }
-
- // reset all ruleflows
- for ( RuleFlowGroup group : this.ruleFlowGroups.values() ) {
- group.clear();
- }
-
- // reset all activation groups.
- for ( ActivationGroup group : this.activationGroups.values() ) {
- group.clear();
- }
- }
-
- /** (non-Javadoc)
- * @see org.drools.common.AgendaI#clearAgenda()
- */
- public void clearAndCancel() {
- // Cancel all items and fire a Cancelled event for each Activation
- for ( final java.util.Iterator agendaGroupIterator = this.agendaGroups.values().iterator(); agendaGroupIterator.hasNext(); ) {
- final AgendaGroup group = (AgendaGroup) agendaGroupIterator.next();
- clearAndCancelAgendaGroup( group );
- }
-
- 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.removeAgendaItem( item,
- this );
- eventsupport.getAgendaEventSupport().fireActivationCancelled( item,
- this.workingMemory,
- ActivationCancelledCause.CLEAR );
- }
- }
-
- // cancel all ruleflows
- for ( RuleFlowGroup group : this.ruleFlowGroups.values() ) {
- clearAndCancelAndCancel( group );
- }
-
- // cancel all activation groups.
- for ( ActivationGroup group : this.activationGroups.values() ) {
- clearAndCancelActivationGroup( group );
- }
-
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#clearAgendaGroup(java.lang.String)
- */
- public void clearAndCancelAgendaGroup(final String name) {
- final AgendaGroup agendaGroup = (AgendaGroup) this.agendaGroups.get( name );
- if ( agendaGroup != null ) {
- clearAndCancelAgendaGroup( agendaGroup );
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#clearAgendaGroup(org.drools.common.AgendaGroupImpl)
- */
- public void clearAndCancelAgendaGroup(final AgendaGroup agendaGroup) {
- final EventSupport eventsupport = (EventSupport) this.workingMemory;
-
- final Activation[] queueable = ((InternalAgendaGroup) agendaGroup).getQueue();
- for ( int i = 0, length = queueable.length; i < length; i++ ) {
- final AgendaItem item = (AgendaItem) queueable[i];
- if ( item == null ) {
- continue;
- }
-
- // this must be set false before removal from the activationGroup.
- // Otherwise the activationGroup will also try to cancel the
- // Actvation
- item.setActivated( false );
-
- if ( item.getActivationGroupNode() != null ) {
- item.getActivationGroupNode().getActivationGroup().removeActivation( item );
- }
-
- if ( item.getActivationNode() != null ) {
- final InternalRuleFlowGroup ruleFlowGroup = (InternalRuleFlowGroup) item.getActivationNode().getParentContainer();
- ruleFlowGroup.removeActivation( item );
- }
-
- eventsupport.getAgendaEventSupport().fireActivationCancelled( item,
- this.workingMemory,
- ActivationCancelledCause.CLEAR );
- }
- ((InternalAgendaGroup) agendaGroup).clear();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#clearActivationGroup(java.lang.String)
- */
- public void clearAndCancelActivationGroup(final String name) {
- final ActivationGroup activationGroup = (ActivationGroup) this.activationGroups.get( name );
- if ( activationGroup != null ) {
- clearAndCancelActivationGroup( activationGroup );
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.drools.common.AgendaI#clearActivationGroup(org.drools.spi.ActivationGroup)
- */
- public void clearAndCancelActivationGroup(final ActivationGroup activationGroup) {
- final EventSupport eventsupport = (EventSupport) this.workingMemory;
-
- for ( final Iterator it = activationGroup.iterator(); it.hasNext(); ) {
- final ActivationGroupNode node = (ActivationGroupNode) it.next();
- final Activation activation = node.getActivation();
- activation.setActivationGroupNode( null );
-
- if ( activation.isActivated() ) {
- activation.setActivated( false );
- activation.remove();
-
- if ( activation.getActivationNode() != null ) {
- final InternalRuleFlowGroup ruleFlowGroup = (InternalRuleFlowGroup) activation.getActivationNode().getParentContainer();
- ruleFlowGroup.removeActivation( activation );
- }
-
- eventsupport.getAgendaEventSupport().fireActivationCancelled( activation,
- this.workingMemory,
- ActivationCancelledCause.CLEAR );
- }
- }
- activationGroup.clear();
- }
-
- public void clearAndCancelRuleFlowGroup(final String name) {
- final RuleFlowGroup ruleFlowGrlup = (RuleFlowGroup) this.ruleFlowGroups.get( name );
- if ( ruleFlowGrlup != null ) {
- clearAndCancelAndCancel( ruleFlowGrlup );
- }
- }
-
- public void clearAndCancelAndCancel(final RuleFlowGroup ruleFlowGroup) {
- final EventSupport eventsupport = (EventSupport) this.workingMemory;
-
- for ( Iterator it = ruleFlowGroup.iterator(); it.hasNext(); ) {
- ActivationNode node = (ActivationNode) it.next();
- AgendaItem item = (AgendaItem) node.getActivation();
- if ( item != null ) {
- item.setActivated( false );
- item.remove();
-
- if ( item.getActivationGroupNode() != null ) {
- item.getActivationGroupNode().getActivationGroup().removeActivation( item );
- }
- }
-
- eventsupport.getAgendaEventSupport().fireActivationCancelled( item,
- this.workingMemory,
- ActivationCancelledCause.CLEAR );
- }
-
- ((InternalRuleFlowGroup) ruleFlowGroup).clear();
-
- if ( ruleFlowGroup.isActive() && ruleFlowGroup.isAutoDeactivate() ) {
- // deactivate callback
- WorkingMemoryAction action = new DeactivateCallback( (InternalRuleFlowGroup) ruleFlowGroup );
- this.workingMemory.queueWorkingMemoryAction( action );
- }
- }
-
- /**
- * Fire the next scheduled <code>Agenda</code> item, skipping items
- * that are not allowed by the agenda filter.
- *
- * @return true if an activation was fired. false if no more activations
- * to fire
- *
- * @throws ConsequenceException
- * If an error occurs while firing an agenda item.
- */
- public boolean fireNextItem(final AgendaFilter filter) throws ConsequenceException {
- boolean tryagain, result;
- try {
- do {
- this.workingMemory.prepareToFireActivation();
- tryagain = result = false;
- final InternalAgendaGroup group = (InternalAgendaGroup) getNextFocus();
- // if there is a group with focus
- if ( group != null ) {
- final AgendaItem item = (AgendaItem) group.getNext();
- // if there is an item to fire from that group
- if ( item != null ) {
- // if that item is allowed to fire
- if ( filter == null || filter.accept( item ) ) {
- // fire it
- fireActivation( item );
- result = true;
- } else {
- // otherwise cancel it and try the next
- final EventSupport eventsupport = (EventSupport) this.workingMemory;
-
- eventsupport.getAgendaEventSupport().fireActivationCancelled( item,
- this.workingMemory,
- ActivationCancelledCause.FILTER );
- tryagain = true;
- }
- }
- }
- } while ( tryagain );
- } finally {
- this.workingMemory.activationFired();
- }
- return result;
- }
-
- /**
- * Fire this item.
- *
- * @param workingMemory
- * The working memory context.
- *
- * @throws ConsequenceException
- * If an error occurs while attempting to fire the consequence.
- */
- public synchronized void fireActivation(final Activation activation) throws ConsequenceException {
- // We do this first as if a node modifies a fact that causes a recursion
- // on an empty pattern
- // we need to make sure it re-activates
- this.workingMemory.startOperation();
- try {
- increaseDormantActivations();
-
- final EventSupport eventsupport = (EventSupport) this.workingMemory;
-
- eventsupport.getAgendaEventSupport().fireBeforeActivationFired( activation,
- this.workingMemory );
-
- if ( activation.getActivationGroupNode() != null ) {
- // We know that this rule will cancel all other activations in the group
- // so lets remove the information now, before the consequence fires
- final ActivationGroup activationGroup = activation.getActivationGroupNode().getActivationGroup();
- activationGroup.removeActivation( activation );
- clearAndCancelActivationGroup( activationGroup );
- }
- activation.setActivated( false );
-
- InternalRuleFlowGroup ruleFlowGroup = null;
- if ( activation.getActivationNode() != null ) {
- ruleFlowGroup = (InternalRuleFlowGroup) activation.getActivationNode().getParentContainer();
- // it is possible that the ruleflow group is no longer active if it was
- // cleared during execution of this activation
- ruleFlowGroup.removeActivation( activation );
- }
-
- try {
- this.knowledgeHelper.setActivation( activation );
- activation.getRule().getConsequence().evaluate( this.knowledgeHelper,
- this.workingMemory );
- this.knowledgeHelper.cancelRemainingPreviousLogicalDependencies();
- this.knowledgeHelper.reset();
- } catch ( final Exception e ) {
- if ( this.legacyConsequenceExceptionHandler != null ) {
- this.legacyConsequenceExceptionHandler.handleException( activation,
- this.workingMemory,
- e );
- } else if ( this.consequenceExceptionHandler != null ) {
- this.consequenceExceptionHandler.handleException( activation,
- new StatefulKnowledgeSessionImpl( (ReteooWorkingMemory) this.workingMemory ),
- e );
- } else {
- throw new RuntimeException( e );
- }
- }
-
- if( ruleFlowGroup != null ) {
- ruleFlowGroup.deactivateIfEmpty();
- }
-
- // if the tuple contains expired events
- 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() ) {
- // decrease the activation count for the event
- handle.decreaseActivationsCount();
- if ( handle.getActivationsCount() == 0 ) {
- // and if no more activations, retract the handle
- handle.getEntryPoint().retract( handle );
- }
- }
- }
- }
-
- eventsupport.getAgendaEventSupport().fireAfterActivationFired( activation,
- this.workingMemory );
- } finally {
- this.workingMemory.endOperation();
- }
- }
-
- public void increaseActiveActivations() {
- this.activeActivations++;
- }
-
- public void decreaseActiveActivations() {
- this.activeActivations--;
- }
-
- public void increaseDormantActivations() {
- this.activeActivations--;
- this.dormantActivations++;
- }
-
- public void decreaseDormantActivations() {
- this.dormantActivations--;
- }
-
- public int getActiveActivations() {
- return this.activeActivations;
- }
-
- public int getDormantActivations() {
- return this.dormantActivations;
- }
-
- /**
- * @inheritDoc
- */
- public boolean isRuleActiveInRuleFlowGroup(String ruleflowGroupName,
- String ruleName,
- long processInstanceId) {
-
- RuleFlowGroup systemRuleFlowGroup = this.getRuleFlowGroup( ruleflowGroupName );
-
- for ( Iterator<ActivationNode> activations = systemRuleFlowGroup.iterator(); activations.hasNext(); ) {
- Activation activation = activations.next().getActivation();
- if ( ruleName.equals( activation.getRule().getName() ) ) {
- 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(); ) {
- 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;
- }
- }
- }
- return true;
- }
-
- public void addRuleFlowGroupListener(String ruleFlowGroup,
- RuleFlowGroupListener listener) {
- InternalRuleFlowGroup rfg = (InternalRuleFlowGroup) this.getRuleFlowGroup( ruleFlowGroup );
- rfg.addRuleFlowGroupListener( listener );
- }
-
- public void removeRuleFlowGroupListener(String ruleFlowGroup,
- RuleFlowGroupListener listener) {
- InternalRuleFlowGroup rfg = (InternalRuleFlowGroup) this.getRuleFlowGroup( ruleFlowGroup );
- rfg.removeRuleFlowGroupListener( listener );
- }
-
- public String getFocusName() {
- return this.getFocus().getName();
- }
-
- public void fireUntilHalt() {
- fireUntilHalt( null );
- }
-
- private AtomicBoolean missedNotifyAll = new AtomicBoolean(false);
-
- public void fireUntilHalt(final AgendaFilter agendaFilter) {
- this.halt.set( false );
- while ( continueFiring( -1 ) ) {
- boolean fired = fireNextItem( agendaFilter );
- fired = fired || !((AbstractWorkingMemory) this.workingMemory).getActionQueue().isEmpty();
- this.workingMemory.executeQueuedActions();
- if ( !fired && !missedNotifyAll.get()) {
- try {
- synchronized ( this.halt ) {
- this.halt.wait();
- }
- } catch ( InterruptedException e ) {
- this.halt.set( true );
- }
- this.missedNotifyAll.set( false );
- } else {
- this.workingMemory.executeQueuedActions();
- }
- }
- }
-
- public int fireAllRules(AgendaFilter agendaFilter,
- int fireLimit) {
- this.halt.set( false );
- int fireCount = 0;
- while ( continueFiring( fireLimit ) && fireNextItem( agendaFilter ) ) {
- fireCount++;
- fireLimit = updateFireLimit( fireLimit );
- this.workingMemory.executeQueuedActions();
- }
- if ( this.focusStack.size() == 1 && getMainAgendaGroup().isEmpty() ) {
- // the root MAIN agenda group is empty, reset active to false, so it can receive more activations.
- getMainAgendaGroup().setActive( false );
- }
- return fireCount;
- }
-
- private final boolean continueFiring(final int fireLimit) {
- return (!halt.get()) && (fireLimit != 0);
- }
-
- private final int updateFireLimit(final int fireLimit) {
- return fireLimit > 0 ? fireLimit - 1 : fireLimit;
- }
-
- public void notifyHalt() {
- synchronized ( this.halt ) {
- this.missedNotifyAll.set( true );
- this.halt.notifyAll();
- }
- }
-
- public void halt() {
- this.halt.set( true );
- notifyHalt();
- }
-
- public ConsequenceExceptionHandler getConsequenceExceptionHandler() {
- return this.legacyConsequenceExceptionHandler;
- }
-}
+/**
+ * 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.
+ */
+
+package org.drools.common;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.drools.WorkingMemory;
+import org.drools.base.DefaultKnowledgeHelper;
+import org.drools.base.SequentialKnowledgeHelper;
+import org.drools.common.RuleFlowGroupImpl.DeactivateCallback;
+import org.drools.core.util.ClassUtils;
+import org.drools.core.util.LinkedListNode;
+import org.drools.event.rule.ActivationCancelledCause;
+import org.drools.impl.StatefulKnowledgeSessionImpl;
+import org.drools.process.instance.ProcessInstance;
+import org.drools.reteoo.LeftTuple;
+import org.drools.reteoo.ReteooWorkingMemory;
+import org.drools.rule.Declaration;
+import org.drools.rule.GroupElement;
+import org.drools.rule.Rule;
+import org.drools.spi.Activation;
+import org.drools.spi.ActivationGroup;
+import org.drools.spi.AgendaFilter;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.ConsequenceException;
+import org.drools.spi.ConsequenceExceptionHandler;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.RuleFlowGroup;
+import org.drools.spi.Tuple;
+
+/**
+ * Rule-firing Agenda.
+ *
+ * <p>
+ * Since many rules may be matched by a single assertObject(...) all scheduled
+ * actions are placed into the <code>Agenda</code>.
+ * </p>
+ *
+ * <p>
+ * While processing a scheduled action, it may update or retract objects in
+ * other scheduled actions, which must then be removed from the agenda.
+ * Non-invalidated actions are left on the agenda, and are executed in turn.
+ * </p>
+ *
+ * @author <a href="mailto:bob at eng.werken.com">bob mcwhirter </a>
+ * @author <a href="mailto:simon at redhillconsulting.com.au">Simon Harris </a>
+ */
+public class DefaultAgenda
+ implements
+ Externalizable,
+ InternalAgenda {
+ // ------------------------------------------------------------
+ // Instance members
+ // ------------------------------------------------------------
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 510l;
+
+ /** Working memory of this Agenda. */
+ private InternalWorkingMemory workingMemory;
+
+ private org.drools.core.util.LinkedList scheduledActivations;
+
+ /** Items time-delayed. */
+
+ private Map<String, InternalAgendaGroup> agendaGroups;
+
+ private Map<String, ActivationGroup> activationGroups;
+
+ private Map<String, RuleFlowGroup> ruleFlowGroups;
+
+ private LinkedList<AgendaGroup> focusStack;
+
+ private InternalAgendaGroup currentModule;
+
+ private InternalAgendaGroup main;
+
+ private AgendaGroupFactory agendaGroupFactory;
+
+ private KnowledgeHelper knowledgeHelper;
+
+ public int activeActivations;
+
+ public int dormantActivations;
+
+ private ConsequenceExceptionHandler legacyConsequenceExceptionHandler;
+
+ private org.drools.runtime.rule.ConsequenceExceptionHandler consequenceExceptionHandler;
+
+ protected volatile AtomicBoolean halt = new AtomicBoolean( false );
+
+ private int activationCounter;
+
+ // ------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------
+ public DefaultAgenda() {
+ }
+
+ /**
+ * Construct.
+ *
+ * @param workingMemory
+ * The <code>WorkingMemory</code> of this agenda.
+ * @param conflictResolver
+ * The conflict resolver.
+ */
+ public DefaultAgenda(InternalRuleBase rb) {
+ this( rb,
+ true );
+ }
+
+ /**
+ * Construct.
+ *
+ * @param workingMemory
+ * The <code>WorkingMemory</code> of this agenda.
+ * @param conflictResolver
+ * The conflict resolver.
+ */
+ public DefaultAgenda(InternalRuleBase rb,
+ boolean initMain) {
+
+ this.agendaGroups = new HashMap<String, InternalAgendaGroup>();
+ this.activationGroups = new HashMap<String, ActivationGroup>();
+ this.ruleFlowGroups = new HashMap<String, RuleFlowGroup>();
+ this.focusStack = new LinkedList<AgendaGroup>();
+ this.scheduledActivations = new org.drools.core.util.LinkedList();
+ this.agendaGroupFactory = rb.getConfiguration().getAgendaGroupFactory();
+
+ if ( initMain ) {
+ // MAIN should always be the first AgendaGroup and can never be
+ // removed
+ this.main = agendaGroupFactory.createAgendaGroup( AgendaGroup.MAIN,
+ rb );
+
+ this.agendaGroups.put( AgendaGroup.MAIN,
+ this.main );
+
+ this.focusStack.add( this.main );
+ }
+ Object object = ClassUtils.instantiateObject( rb.getConfiguration().getConsequenceExceptionHandler(),
+ rb.getConfiguration().getClassLoader() );
+ if ( object instanceof ConsequenceExceptionHandler ) {
+ this.legacyConsequenceExceptionHandler = (ConsequenceExceptionHandler) object;
+ } else {
+ this.consequenceExceptionHandler = (org.drools.runtime.rule.ConsequenceExceptionHandler) object;
+ }
+ }
+
+ public AgendaItem createAgendaItem(final Tuple tuple,
+ final int salience,
+ final PropagationContext context,
+ final Rule rule,
+ final GroupElement subrule) {
+ return new AgendaItem( activationCounter++,
+ tuple,
+ salience,
+ context,
+ rule,
+ subrule );
+ }
+
+ public ScheduledAgendaItem createScheduledAgendaItem(final Tuple tuple,
+ final PropagationContext context,
+ final Rule rule,
+ final GroupElement subrule) {
+ return new ScheduledAgendaItem( activationCounter++,
+ tuple,
+ this,
+ context,
+ rule,
+ subrule );
+ }
+
+ public void setWorkingMemory(final InternalWorkingMemory workingMemory) {
+ this.workingMemory = workingMemory;
+ if ( ((InternalRuleBase) this.workingMemory.getRuleBase()).getConfiguration().isSequential() ) {
+ this.knowledgeHelper = new SequentialKnowledgeHelper( this.workingMemory );
+ } else {
+ this.knowledgeHelper = new DefaultKnowledgeHelper( this.workingMemory );
+ }
+ }
+
+ // public void write(WMSerialisationOutContext context) throws IOException {
+ // BinaryHeapQueueAgendaGroup[] agendaGroups = (BinaryHeapQueueAgendaGroup[]) this.agendaGroups.values().toArray( new AgendaGroup[this.agendaGroups.size()] );
+ // Arrays.sort( agendaGroups,
+ // AgendaGroupSorter.instance );
+ //
+ // for ( BinaryHeapQueueAgendaGroup group : agendaGroups ) {
+ // context.writeInt( PersisterEnums.AGENDA_GROUP );
+ // group.write( context );
+ // }
+ // context.writeInt( PersisterEnums.END );
+ //
+ // for ( ListIterator it = this.focusStack.listIterator( this.focusStack.size() - 1 ); it.hasPrevious(); ) {
+ // AgendaGroup group = (AgendaGroup) it.previous();
+ // context.writeInt( PersisterEnums.AGENDA_GROUP );
+ // context.writeUTF( group.getName() );
+ // }
+ // context.writeInt( PersisterEnums.END );
+ //
+ // RuleFlowGroupImpl[] ruleFlowGroups = (RuleFlowGroupImpl[]) this.ruleFlowGroups.values().toArray( new RuleFlowGroupImpl[this.ruleFlowGroups.size()] );
+ // Arrays.sort( agendaGroups,
+ // AgendaGroupSorter.instance );
+ //
+ // for ( BinaryHeapQueueAgendaGroup group : agendaGroups ) {
+ // context.writeInt( PersisterEnums.RULE_FLOW_GROUP );
+ // group.write( context );
+ // }
+ // context.writeInt( PersisterEnums.END );
+ // }
+
+ // public static class AgendaGroupSorter
+ // implements
+ // Comparator<AgendaGroup> {
+ // public static final AgendaGroupSorter instance = new AgendaGroupSorter();
+ //
+ // public int compare(AgendaGroup group1,
+ // AgendaGroup group2) {
+ // return group1.getName().compareTo( group2.getName() );
+ // }
+ // }
+ //
+ // public static class RuleFlowGroupSorter
+ // implements
+ // Comparator<AgendaGroup> {
+ // public static final AgendaGroupSorter instance = new AgendaGroupSorter();
+ //
+ // public int compare(AgendaGroup group1,
+ // AgendaGroup group2) {
+ // return group1.getName().compareTo( group2.getName() );
+ // }
+ // }
+
+ public void readExternal(ObjectInput in) throws IOException,
+ ClassNotFoundException {
+ workingMemory = (InternalWorkingMemory) in.readObject();
+ scheduledActivations = (org.drools.core.util.LinkedList) in.readObject();
+ agendaGroups = (Map) in.readObject();
+ activationGroups = (Map) in.readObject();
+ ruleFlowGroups = (Map) in.readObject();
+ focusStack = (LinkedList) in.readObject();
+ currentModule = (InternalAgendaGroup) in.readObject();
+ main = (InternalAgendaGroup) in.readObject();
+ agendaGroupFactory = (AgendaGroupFactory) in.readObject();
+ knowledgeHelper = (KnowledgeHelper) in.readObject();
+ activeActivations = in.readInt();
+ dormantActivations = in.readInt();
+ legacyConsequenceExceptionHandler = (ConsequenceExceptionHandler) in.readObject();
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeObject( workingMemory );
+ out.writeObject( scheduledActivations );
+ out.writeObject( agendaGroups );
+ out.writeObject( activationGroups );
+ out.writeObject( ruleFlowGroups );
+ out.writeObject( focusStack );
+ out.writeObject( currentModule );
+ out.writeObject( main );
+ out.writeObject( agendaGroupFactory );
+ out.writeObject( knowledgeHelper );
+ out.writeInt( activeActivations );
+ out.writeInt( dormantActivations );
+ out.writeObject( legacyConsequenceExceptionHandler );
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#getWorkingMemory()
+ */
+ public WorkingMemory getWorkingMemory() {
+ return this.workingMemory;
+ }
+
+ /**
+ * Schedule an agenda item for delayed firing.
+ *
+ * @param item
+ * The item to schedule.
+ */
+ public void scheduleItem(final ScheduledAgendaItem item, final InternalWorkingMemory wm) {
+
+ Scheduler.scheduleAgendaItem( item,
+ this,
+ wm );
+ this.scheduledActivations.add( item );
+
+ // adds item to activation group if appropriate
+ addItemToActivationGroup( item );
+
+ }
+
+ /**
+ * If the item belongs to an activation group, add it
+ *
+ * @param item
+ */
+ private void addItemToActivationGroup(final AgendaItem item) {
+ String group = item.getRule().getActivationGroup();
+ if ( group != null && group.length() > 0 ) {
+ this.getActivationGroup( group ).addActivation( item );
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public boolean addActivation(final AgendaItem activation) {
+ // set the focus if rule autoFocus is true
+ if ( activation.getRule().getAutoFocus() ) {
+ this.setFocus( activation.getRule().getAgendaGroup() );
+ }
+
+ // adds item to activation group if appropriate
+ addItemToActivationGroup( activation );
+
+ InternalAgendaGroup agendaGroup = (InternalAgendaGroup) this.getAgendaGroup( activation.getRule().getAgendaGroup() );
+ activation.setAgendaGroup( agendaGroup );
+
+ if ( activation.getRule().getRuleFlowGroup() == null ) {
+ // No RuleFlowNode so add it directly to the Agenda
+
+ // do not add the activation if the rule is "lock-on-active" and the
+ // AgendaGroup is active
+ if ( activation.getRule().isLockOnActive() && agendaGroup.isActive() ) {
+ return false;
+ }
+
+ agendaGroup.add( activation );
+ } else {
+ // There is a RuleFlowNode so add it there, instead of the Agenda
+ InternalRuleFlowGroup rfg = (InternalRuleFlowGroup) this.getRuleFlowGroup( activation.getRule().getRuleFlowGroup() );
+
+ // do not add the activation if the rule is "lock-on-active" and the
+ // RuleFlowGroup is active
+ if ( activation.getRule().isLockOnActive() && rfg.isActive() ) {
+ return false;
+ }
+
+ rfg.addActivation( activation );
+ }
+
+ // making sure we re-evaluate agenda in case we are waiting for activations
+ synchronized ( this.halt ) {
+ this.halt.notifyAll();
+ }
+ return true;
+
+ }
+
+ public void removeScheduleItem(final ScheduledAgendaItem item) {
+ this.scheduledActivations.remove( item );
+ Scheduler.removeAgendaItem( item,
+ this );
+ }
+
+ public void addAgendaGroup(final AgendaGroup agendaGroup) {
+ this.agendaGroups.put( agendaGroup.getName(),
+ (InternalAgendaGroup) agendaGroup );
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#setFocus(org.drools.spi.AgendaGroup)
+ */
+ public boolean setFocus(final AgendaGroup agendaGroup) {
+ // Set the focus to the agendaGroup if it doesn't already have the focus
+ if ( this.focusStack.getLast() != agendaGroup ) {
+ ((InternalAgendaGroup) this.focusStack.getLast()).setActive( false );
+ this.focusStack.add( agendaGroup );
+ ((InternalAgendaGroup) agendaGroup).setActive( true );
+ final EventSupport eventsupport = (EventSupport) this.workingMemory;
+ eventsupport.getAgendaEventSupport().fireAgendaGroupPushed( agendaGroup,
+ this.workingMemory );
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#setFocus(java.lang.String)
+ */
+ public void setFocus(final String name) {
+ AgendaGroup agendaGroup = getAgendaGroup( name );
+ setFocus( agendaGroup );
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#getFocus()
+ */
+ public AgendaGroup getFocus() {
+ return (AgendaGroup) this.focusStack.getLast();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#getNextFocus()
+ */
+ public AgendaGroup getNextFocus() {
+ InternalAgendaGroup agendaGroup = null;
+ // Iterate until we find a populate AgendaModule or we reach the MAIN,
+ // default, AgendaGroup
+ while ( true ) {
+ agendaGroup = (InternalAgendaGroup) this.focusStack.getLast();
+
+ final boolean empty = agendaGroup.isEmpty();
+
+ // No populated queues found so pop the focusStack and repeat
+ if ( empty && (this.focusStack.size() > 1) ) {
+ agendaGroup.setActive( false );
+ this.focusStack.removeLast();
+ final EventSupport eventsupport = (EventSupport) this.workingMemory;
+ eventsupport.getAgendaEventSupport().fireAgendaGroupPopped( agendaGroup,
+ this.workingMemory );
+ } else {
+ agendaGroup = (empty) ? null : agendaGroup;
+ break;
+ }
+ }
+
+ if ( agendaGroup != null ) {
+ agendaGroup.setActive( true );
+ }
+ return agendaGroup;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#setCurrentAgendaGroup(org.drools.spi.AgendaGroup)
+ */
+ public void setCurrentAgendaGroup(final InternalAgendaGroup agendaGroup) {
+ this.currentModule = agendaGroup;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#getCurrentAgendaGroup()
+ */
+ public AgendaGroup getCurrentAgendaGroup() {
+ return this.currentModule;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#getAgendaGroup(java.lang.String)
+ */
+ public AgendaGroup getAgendaGroup(final String name) {
+ String groupName = (name == null || name.length() == 0) ? AgendaGroup.MAIN : name;
+
+ AgendaGroup agendaGroup = (AgendaGroup) this.agendaGroups.get( groupName );
+ if ( agendaGroup == null ) {
+ // The AgendaGroup is defined but not yet added to the
+ // Agenda, so create the AgendaGroup and add to the Agenda.
+ agendaGroup = agendaGroupFactory.createAgendaGroup( name,
+ ((InternalRuleBase) this.workingMemory.getRuleBase()) );
+ addAgendaGroup( agendaGroup );
+ }
+ return agendaGroup;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#getAgendaGroups()
+ */
+ public AgendaGroup[] getAgendaGroups() {
+ return (AgendaGroup[]) this.agendaGroups.values().toArray( new AgendaGroup[this.agendaGroups.size()] );
+ }
+
+ public Map<String, InternalAgendaGroup> getAgendaGroupsMap() {
+ return this.agendaGroups;
+ }
+
+ public InternalAgendaGroup getMainAgendaGroup() {
+ if ( this.main == null ) {
+ this.main = (InternalAgendaGroup) getAgendaGroup( AgendaGroup.MAIN );
+ }
+
+ return this.main;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#getStack()
+ */
+ public AgendaGroup[] getStack() {
+ return (AgendaGroup[]) this.focusStack.toArray( new AgendaGroup[this.focusStack.size()] );
+ }
+
+ public LinkedList<AgendaGroup> getStackList() {
+ return this.focusStack;
+ }
+
+ public Map<String, RuleFlowGroup> getRuleFlowGroupsMap() {
+ return this.ruleFlowGroups;
+ }
+
+ public Map<String, ActivationGroup> getActivationGroupsMap() {
+ return this.activationGroups;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#getActivationGroup(java.lang.String)
+ */
+ public ActivationGroup getActivationGroup(final String name) {
+ ActivationGroupImpl activationGroup = (ActivationGroupImpl) this.activationGroups.get( name );
+ if ( activationGroup == null ) {
+ activationGroup = new ActivationGroupImpl( name );
+ this.activationGroups.put( name,
+ activationGroup );
+ }
+ return activationGroup;
+ }
+
+ public RuleFlowGroup getRuleFlowGroup(final String name) {
+ RuleFlowGroup ruleFlowGroup = (RuleFlowGroup) this.ruleFlowGroups.get( name );
+ if ( ruleFlowGroup == null ) {
+ ruleFlowGroup = new RuleFlowGroupImpl( name );
+ ((InternalRuleFlowGroup) ruleFlowGroup).setWorkingMemory( (InternalWorkingMemory) getWorkingMemory() );
+ this.ruleFlowGroups.put( name,
+ ruleFlowGroup );
+ }
+ return ruleFlowGroup;
+ }
+
+ public void activateRuleFlowGroup(final String name) {
+ ((InternalRuleFlowGroup) getRuleFlowGroup( name )).setActive( true );
+ }
+
+ public void activateRuleFlowGroup(final String name, long processInstanceId, String nodeInstanceId) {
+ InternalRuleFlowGroup ruleFlowGroup = (InternalRuleFlowGroup) getRuleFlowGroup( name );
+ ruleFlowGroup.addNodeInstance(processInstanceId, nodeInstanceId);
+ ruleFlowGroup.setActive( true );
+ }
+
+ public void deactivateRuleFlowGroup(final String name) {
+ ((InternalRuleFlowGroup) getRuleFlowGroup( name )).setActive( false );
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#focusStackSize()
+ */
+ public int focusStackSize() {
+ int size = 0;
+ for ( final java.util.Iterator iterator = this.focusStack.iterator(); iterator.hasNext(); ) {
+ final AgendaGroup group = (AgendaGroup) iterator.next();
+ size += group.size();
+ }
+ return size;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#agendaSize()
+ */
+ public int agendaSize() {
+ int size = 0;
+ for ( final java.util.Iterator iterator = this.agendaGroups.values().iterator(); iterator.hasNext(); ) {
+ final AgendaGroup group = (AgendaGroup) iterator.next();
+ size += group.size();
+ }
+ return size;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#getActivations()
+ */
+ public Activation[] getActivations() {
+ final List list = new ArrayList();
+ for ( final java.util.Iterator it = this.agendaGroups.values().iterator(); it.hasNext(); ) {
+ final AgendaGroup group = (AgendaGroup) it.next();
+ list.addAll( Arrays.asList( group.getActivations() ) );
+ }
+ return (Activation[]) list.toArray( new Activation[list.size()] );
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#getScheduledActivations()
+ */
+ public Activation[] getScheduledActivations() {
+ final List list = new ArrayList( this.scheduledActivations.size() );
+ for ( LinkedListNode node = this.scheduledActivations.getFirst(); node != null; node = node.getNext() ) {
+ list.add( node );
+ }
+ return (Activation[]) list.toArray( new Activation[list.size()] );
+ }
+
+ public org.drools.core.util.LinkedList getScheduledActivationsLinkedList() {
+ return this.scheduledActivations;
+ }
+
+ public void clear() {
+ // reset focus stack
+ this.focusStack.clear();
+ this.focusStack.add( getMainAgendaGroup() );
+
+ // reset scheduled activations
+ if ( !this.scheduledActivations.isEmpty() ) {
+ for ( ScheduledAgendaItem item = (ScheduledAgendaItem) this.scheduledActivations.removeFirst(); item != null; item = (ScheduledAgendaItem) this.scheduledActivations.removeFirst() ) {
+ Scheduler.removeAgendaItem( item,
+ this );
+ }
+ }
+
+ //reset all agenda groups
+ for ( InternalAgendaGroup group : this.agendaGroups.values() ) {
+ group.clear();
+ }
+
+ // reset all ruleflows
+ for ( RuleFlowGroup group : this.ruleFlowGroups.values() ) {
+ group.clear();
+ }
+
+ // reset all activation groups.
+ for ( ActivationGroup group : this.activationGroups.values() ) {
+ group.clear();
+ }
+ }
+
+ /** (non-Javadoc)
+ * @see org.drools.common.AgendaI#clearAgenda()
+ */
+ public void clearAndCancel() {
+ // Cancel all items and fire a Cancelled event for each Activation
+ for ( final java.util.Iterator agendaGroupIterator = this.agendaGroups.values().iterator(); agendaGroupIterator.hasNext(); ) {
+ final AgendaGroup group = (AgendaGroup) agendaGroupIterator.next();
+ clearAndCancelAgendaGroup( group );
+ }
+
+ 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.removeAgendaItem( item,
+ this );
+ eventsupport.getAgendaEventSupport().fireActivationCancelled( item,
+ this.workingMemory,
+ ActivationCancelledCause.CLEAR );
+ }
+ }
+
+ // cancel all ruleflows
+ for ( RuleFlowGroup group : this.ruleFlowGroups.values() ) {
+ clearAndCancelAndCancel( group );
+ }
+
+ // cancel all activation groups.
+ for ( ActivationGroup group : this.activationGroups.values() ) {
+ clearAndCancelActivationGroup( group );
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#clearAgendaGroup(java.lang.String)
+ */
+ public void clearAndCancelAgendaGroup(final String name) {
+ final AgendaGroup agendaGroup = (AgendaGroup) this.agendaGroups.get( name );
+ if ( agendaGroup != null ) {
+ clearAndCancelAgendaGroup( agendaGroup );
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#clearAgendaGroup(org.drools.common.AgendaGroupImpl)
+ */
+ public void clearAndCancelAgendaGroup(final AgendaGroup agendaGroup) {
+ final EventSupport eventsupport = (EventSupport) this.workingMemory;
+
+ final Activation[] queueable = ((InternalAgendaGroup) agendaGroup).getQueue();
+ for ( int i = 0, length = queueable.length; i < length; i++ ) {
+ final AgendaItem item = (AgendaItem) queueable[i];
+ if ( item == null ) {
+ continue;
+ }
+
+ // this must be set false before removal from the activationGroup.
+ // Otherwise the activationGroup will also try to cancel the
+ // Actvation
+ item.setActivated( false );
+
+ if ( item.getActivationGroupNode() != null ) {
+ item.getActivationGroupNode().getActivationGroup().removeActivation( item );
+ }
+
+ if ( item.getActivationNode() != null ) {
+ final InternalRuleFlowGroup ruleFlowGroup = (InternalRuleFlowGroup) item.getActivationNode().getParentContainer();
+ ruleFlowGroup.removeActivation( item );
+ }
+
+ eventsupport.getAgendaEventSupport().fireActivationCancelled( item,
+ this.workingMemory,
+ ActivationCancelledCause.CLEAR );
+ }
+ ((InternalAgendaGroup) agendaGroup).clear();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#clearActivationGroup(java.lang.String)
+ */
+ public void clearAndCancelActivationGroup(final String name) {
+ final ActivationGroup activationGroup = (ActivationGroup) this.activationGroups.get( name );
+ if ( activationGroup != null ) {
+ clearAndCancelActivationGroup( activationGroup );
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.drools.common.AgendaI#clearActivationGroup(org.drools.spi.ActivationGroup)
+ */
+ public void clearAndCancelActivationGroup(final ActivationGroup activationGroup) {
+ final EventSupport eventsupport = (EventSupport) this.workingMemory;
+
+ for ( final Iterator it = activationGroup.iterator(); it.hasNext(); ) {
+ final ActivationGroupNode node = (ActivationGroupNode) it.next();
+ final Activation activation = node.getActivation();
+ activation.setActivationGroupNode( null );
+
+ if ( activation.isActivated() ) {
+ activation.setActivated( false );
+ activation.remove();
+
+ if ( activation.getActivationNode() != null ) {
+ final InternalRuleFlowGroup ruleFlowGroup = (InternalRuleFlowGroup) activation.getActivationNode().getParentContainer();
+ ruleFlowGroup.removeActivation( activation );
+ }
+
+ eventsupport.getAgendaEventSupport().fireActivationCancelled( activation,
+ this.workingMemory,
+ ActivationCancelledCause.CLEAR );
+ }
+ }
+ activationGroup.clear();
+ }
+
+ public void clearAndCancelRuleFlowGroup(final String name) {
+ final RuleFlowGroup ruleFlowGrlup = (RuleFlowGroup) this.ruleFlowGroups.get( name );
+ if ( ruleFlowGrlup != null ) {
+ clearAndCancelAndCancel( ruleFlowGrlup );
+ }
+ }
+
+ public void clearAndCancelAndCancel(final RuleFlowGroup ruleFlowGroup) {
+ final EventSupport eventsupport = (EventSupport) this.workingMemory;
+
+ for ( Iterator it = ruleFlowGroup.iterator(); it.hasNext(); ) {
+ ActivationNode node = (ActivationNode) it.next();
+ AgendaItem item = (AgendaItem) node.getActivation();
+ if ( item != null ) {
+ item.setActivated( false );
+ item.remove();
+
+ if ( item.getActivationGroupNode() != null ) {
+ item.getActivationGroupNode().getActivationGroup().removeActivation( item );
+ }
+ }
+
+ eventsupport.getAgendaEventSupport().fireActivationCancelled( item,
+ this.workingMemory,
+ ActivationCancelledCause.CLEAR );
+ }
+
+ ((InternalRuleFlowGroup) ruleFlowGroup).clear();
+
+ if ( ruleFlowGroup.isActive() && ruleFlowGroup.isAutoDeactivate() ) {
+ // deactivate callback
+ WorkingMemoryAction action = new DeactivateCallback( (InternalRuleFlowGroup) ruleFlowGroup );
+ this.workingMemory.queueWorkingMemoryAction( action );
+ }
+ }
+
+ /**
+ * Fire the next scheduled <code>Agenda</code> item, skipping items
+ * that are not allowed by the agenda filter.
+ *
+ * @return true if an activation was fired. false if no more activations
+ * to fire
+ *
+ * @throws ConsequenceException
+ * If an error occurs while firing an agenda item.
+ */
+ public boolean fireNextItem(final AgendaFilter filter) throws ConsequenceException {
+ boolean tryagain, result;
+ try {
+ do {
+ this.workingMemory.prepareToFireActivation();
+ tryagain = result = false;
+ final InternalAgendaGroup group = (InternalAgendaGroup) getNextFocus();
+ // if there is a group with focus
+ if ( group != null ) {
+ final AgendaItem item = (AgendaItem) group.getNext();
+ // if there is an item to fire from that group
+ if ( item != null ) {
+
+ //if the rule will be fired or not, it is necessary the routine bellow to clean up ruleflow activations
+ if ( item.getActivationNode() != null ) {
+ InternalRuleFlowGroup ruleFlowGroup = (InternalRuleFlowGroup) item.getActivationNode().getParentContainer();
+ // it is possible that the ruleflow group is no longer active if it was
+ // cleared during execution of this activation
+ ruleFlowGroup.removeActivation( item );
+ ruleFlowGroup.deactivateIfEmpty();
+ }
+
+ // if that item is allowed to fire
+ if ( filter == null || filter.accept( item ) ) {
+ // fire it
+ fireActivation( item );
+ result = true;
+ } else {
+ // otherwise cancel it and try the next
+
+ //necessary to perfom queued actions like signal to a next node in a ruleflow/jbpm process
+ this.workingMemory.executeQueuedActions();
+
+ final EventSupport eventsupport = (EventSupport) this.workingMemory;
+
+ eventsupport.getAgendaEventSupport().fireActivationCancelled( item,
+ this.workingMemory,
+ ActivationCancelledCause.FILTER );
+ tryagain = true;
+ }
+ }
+ }
+ } while ( tryagain );
+ } finally {
+ this.workingMemory.activationFired();
+ }
+ return result;
+ }
+
+ /**
+ * Fire this item.
+ *
+ * @param workingMemory
+ * The working memory context.
+ *
+ * @throws ConsequenceException
+ * If an error occurs while attempting to fire the consequence.
+ */
+ public synchronized void fireActivation(final Activation activation) throws ConsequenceException {
+ // We do this first as if a node modifies a fact that causes a recursion
+ // on an empty pattern
+ // we need to make sure it re-activates
+ this.workingMemory.startOperation();
+ try {
+ increaseDormantActivations();
+
+ final EventSupport eventsupport = (EventSupport) this.workingMemory;
+
+ eventsupport.getAgendaEventSupport().fireBeforeActivationFired( activation,
+ this.workingMemory );
+
+ if ( activation.getActivationGroupNode() != null ) {
+ // We know that this rule will cancel all other activations in the group
+ // so lets remove the information now, before the consequence fires
+ final ActivationGroup activationGroup = activation.getActivationGroupNode().getActivationGroup();
+ activationGroup.removeActivation( activation );
+ clearAndCancelActivationGroup( activationGroup );
+ }
+ activation.setActivated( false );
+
+ try {
+ this.knowledgeHelper.setActivation( activation );
+ activation.getRule().getConsequence().evaluate( this.knowledgeHelper,
+ this.workingMemory );
+ this.knowledgeHelper.cancelRemainingPreviousLogicalDependencies();
+ this.knowledgeHelper.reset();
+ } catch ( final Exception e ) {
+ if ( this.legacyConsequenceExceptionHandler != null ) {
+ this.legacyConsequenceExceptionHandler.handleException( activation,
+ this.workingMemory,
+ e );
+ } else if ( this.consequenceExceptionHandler != null ) {
+ this.consequenceExceptionHandler.handleException( activation,
+ new StatefulKnowledgeSessionImpl( (ReteooWorkingMemory) this.workingMemory ),
+ e );
+ } else {
+ throw new RuntimeException( e );
+ }
+ }
+
+ // if the tuple contains expired events
+ 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() ) {
+ // decrease the activation count for the event
+ handle.decreaseActivationsCount();
+ if ( handle.getActivationsCount() == 0 ) {
+ // and if no more activations, retract the handle
+ handle.getEntryPoint().retract( handle );
+ }
+ }
+ }
+ }
+
+ eventsupport.getAgendaEventSupport().fireAfterActivationFired( activation,
+ this.workingMemory );
+ } finally {
+ this.workingMemory.endOperation();
+ }
+ }
+
+
+ public void increaseActiveActivations() {
+ this.activeActivations++;
+ }
+
+ public void decreaseActiveActivations() {
+ this.activeActivations--;
+ }
+
+ public void increaseDormantActivations() {
+ this.activeActivations--;
+ this.dormantActivations++;
+ }
+
+ public void decreaseDormantActivations() {
+ this.dormantActivations--;
+ }
+
+ public int getActiveActivations() {
+ return this.activeActivations;
+ }
+
+ public int getDormantActivations() {
+ return this.dormantActivations;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public boolean isRuleActiveInRuleFlowGroup(String ruleflowGroupName,
+ String ruleName,
+ long processInstanceId) {
+
+ RuleFlowGroup systemRuleFlowGroup = this.getRuleFlowGroup( ruleflowGroupName );
+
+ for ( Iterator<ActivationNode> activations = systemRuleFlowGroup.iterator(); activations.hasNext(); ) {
+ Activation activation = activations.next().getActivation();
+ if ( ruleName.equals( activation.getRule().getName() ) ) {
+ 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(); ) {
+ 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;
+ }
+ }
+ }
+ return true;
+ }
+
+ public void addRuleFlowGroupListener(String ruleFlowGroup,
+ RuleFlowGroupListener listener) {
+ InternalRuleFlowGroup rfg = (InternalRuleFlowGroup) this.getRuleFlowGroup( ruleFlowGroup );
+ rfg.addRuleFlowGroupListener( listener );
+ }
+
+ public void removeRuleFlowGroupListener(String ruleFlowGroup,
+ RuleFlowGroupListener listener) {
+ InternalRuleFlowGroup rfg = (InternalRuleFlowGroup) this.getRuleFlowGroup( ruleFlowGroup );
+ rfg.removeRuleFlowGroupListener( listener );
+ }
+
+ public String getFocusName() {
+ return this.getFocus().getName();
+ }
+
+ public void fireUntilHalt() {
+ fireUntilHalt( null );
+ }
+
+ private AtomicBoolean missedNotifyAll = new AtomicBoolean(false);
+
+ public void fireUntilHalt(final AgendaFilter agendaFilter) {
+ this.halt.set( false );
+ while ( continueFiring( -1 ) ) {
+ boolean fired = fireNextItem( agendaFilter );
+ fired = fired || !((AbstractWorkingMemory) this.workingMemory).getActionQueue().isEmpty();
+ this.workingMemory.executeQueuedActions();
+ if ( !fired && !missedNotifyAll.get()) {
+ try {
+ synchronized ( this.halt ) {
+ this.halt.wait();
+ }
+ } catch ( InterruptedException e ) {
+ this.halt.set( true );
+ }
+ this.missedNotifyAll.set( false );
+ } else {
+ this.workingMemory.executeQueuedActions();
+ }
+ }
+ }
+
+ public int fireAllRules(AgendaFilter agendaFilter,
+ int fireLimit) {
+ this.halt.set( false );
+ int fireCount = 0;
+ while ( continueFiring( fireLimit ) && fireNextItem( agendaFilter ) ) {
+ fireCount++;
+ fireLimit = updateFireLimit( fireLimit );
+ this.workingMemory.executeQueuedActions();
+ }
+ if ( this.focusStack.size() == 1 && getMainAgendaGroup().isEmpty() ) {
+ // the root MAIN agenda group is empty, reset active to false, so it can receive more activations.
+ getMainAgendaGroup().setActive( false );
+ }
+ return fireCount;
+ }
+
+ private final boolean continueFiring(final int fireLimit) {
+ return (!halt.get()) && (fireLimit != 0);
+ }
+
+ private final int updateFireLimit(final int fireLimit) {
+ return fireLimit > 0 ? fireLimit - 1 : fireLimit;
+ }
+
+ public void notifyHalt() {
+ synchronized ( this.halt ) {
+ this.missedNotifyAll.set( true );
+ this.halt.notifyAll();
+ }
+ }
+
+ public void halt() {
+ this.halt.set( true );
+ notifyHalt();
+ }
+
+ public ConsequenceExceptionHandler getConsequenceExceptionHandler() {
+ return this.legacyConsequenceExceptionHandler;
+ }
+}
More information about the jboss-svn-commits
mailing list