📄 leapsworkingmemory.java
字号:
*/
private final void invalidateActivation( final LeapsTuple tuple ) {
final Activation activation = tuple.getActivation( );
if (!tuple.isReadyForActivation( ) && !tuple.isActivationNull( )) {
// invalidate agenda agendaItem
if (activation.isActivated( )) {
activation.remove( );
getAgendaEventSupport( ).fireActivationCancelled( activation );
}
//
tuple.setActivation( null );
}
if (activation != null) {
// remove logical dependency
this.tms.removeLogicalDependencies( activation,
tuple.getContext( ),
tuple.getLeapsRule( ).getRule( ) );
// remove from rule / activaitons map
FastMap activations = (FastMap) this.rulesActivationsMap.get( activation.getRule( ) );
if (activations != null) {
activations.remove( activation );
}
}
}
/**
* modify is implemented as half way retract / assert due to the truth maintenance issues.
*
* @see WorkingMemory
*/
public void modifyObject( final FactHandle factHandle,
final Object object,
final Rule rule,
final Activation activation ) throws FactException {
this.getLock( ).lock( );
try {
final PropagationContext propagationContext = new PropagationContextImpl( this.propagationIdCounter++,
PropagationContext.MODIFICATION,
rule,
activation );
final int status = ( (InternalFactHandle) factHandle ).getEqualityKey( )
.getStatus( );
final Object originalObject = this.assertMap.remove( factHandle );
if (originalObject == null) {
throw new NoSuchFactObjectException( factHandle );
}
//
// do subset of retractObject( )
//
final InternalFactHandle handle = (InternalFactHandle) factHandle;
if (handle.getId( ) == -1) {
// can't retract an already retracted handle
return;
}
removePropertyChangeListener( handle );
doRetract( handle, propagationContext );
// Update the equality key, which maintains a list of stated
// FactHandles
final EqualityKey key = handle.getEqualityKey( );
key.removeFactHandle( handle );
handle.setEqualityKey( null );
// If the equality key is now empty, then remove it
if (key.isEmpty( )) {
this.tms.remove( key );
}
// produces NPE otherwise
this.handleFactory.destroyFactHandle( handle );
//
// and now assert
//
/* check to see if this is a logically asserted object */
this.assertObject( object, false, ( status == EqualityKey.STATED ) ? false
: true, rule, activation );
this.workingMemoryEventSupport.fireObjectModified( propagationContext,
handle,
handle.getObject( ),
object );
if (!this.factQueue.isEmpty( )) {
propagateQueuedActions( );
}
}
finally {
this.getLock( ).unlock( );
}
}
/**
* ************* leaps section *********************
*/
private long idLastFireAllAt = -1;
/**
* algorithm stack.
*/
private final TokenStack mainStack = new TokenStack( );
/**
* generates or just return List of internal factTables that correspond a
* class can be used to generate factTables
*
* @return
*/
protected final List getFactTablesList( final Class c ) {
final ArrayList list = new ArrayList( );
// interfaces
final Class[] interfaces = c.getInterfaces( );
for (int i = 0; i < interfaces.length; i++) {
list.add( this.getFactTable( interfaces[i] ) );
}
// classes
Class bufClass = c;
while (bufClass != null) {
//
list.add( this.getFactTable( bufClass ) );
// and get the next class on the list
bufClass = bufClass.getSuperclass( );
}
return list;
}
/**
* adds new leaps token on main stack
*
* @param fact handle
* @param token
*/
protected final void pushTokenOnStack(final InternalFactHandle factHandle,
final Token token) {
this.mainStack.push( token );
}
/**
* removes leaps token on main stack
*
* @param fact handle
*/
protected final void removeTokenFromStack( final LeapsFactHandle factHandle ) {
this.mainStack.remove( factHandle.getId( ) );
}
/**
* gets leaps token from top of stack
*
* @param fact handle
*/
protected final Token peekTokenOnTop() {
return (Token) this.mainStack.peek( );
}
/**
* get leaps fact table of specific type (class)
*
* @param type
* of objects
* @return fact table of requested class type
*/
protected FactTable getFactTable( final Class c ) {
FactTable table;
if (this.factTables.containsKey( c )) {
table = (FactTable) this.factTables.get( c );
}
else {
table = new FactTable( DefaultConflictResolver.getInstance( ) );
this.factTables.put( c, table );
// review existing rules and assign to the fact table if needed
for (final Iterator iter = this.leapsRulesToHandlesMap.keySet( ).iterator( ); iter.hasNext( );) {
final LeapsRule leapsRule = (LeapsRule) iter.next( );
if (leapsRule.getNumberOfColumns( ) > 0) {
final List rulesHandles = (List) this.leapsRulesToHandlesMap.get( leapsRule );
for (final Iterator handles = rulesHandles.iterator( ); handles.hasNext( );) {
final LeapsRuleHandle handle = (LeapsRuleHandle) handles.next( );
if (leapsRule.getColumnClassObjectTypeAtPosition( handle.getDominantPosition( ) )
.isAssignableFrom( c )) {
table.addRule( this, handle );
}
}
}
}
}
return table;
}
/**
* Add Leaps wrapped rules into the working memory
*
* @param rules
*/
protected void addLeapsRules(final List rules) {
this.getLock().lock();
try {
ArrayList ruleHandlesList;
LeapsRule rule;
LeapsRuleHandle ruleHandle;
for ( final Iterator it = rules.iterator(); it.hasNext(); ) {
rule = (LeapsRule) it.next();
// some times rules do not have "normal" constraints and only
// not and exists
if ( rule.getNumberOfColumns() > 0 ) {
ruleHandlesList = new ArrayList( );
for (int i = 0; i < rule.getNumberOfColumns( ); i++) {
ruleHandle = new LeapsRuleHandle( ( (LeapsFactHandleFactory) this.handleFactory ).getNextId( ),
rule,
i );
//
this.getFactTable( rule.getColumnClassObjectTypeAtPosition( i ) )
.addRule( this, ruleHandle );
//
ruleHandlesList.add( ruleHandle );
}
this.leapsRulesToHandlesMap.put( rule, ruleHandlesList );
} else {
// to pick up rules that do not require columns, only not
// and exists
final PropagationContextImpl context = new PropagationContextImpl( nextPropagationIdCounter( ),
PropagationContext.ASSERTION,
null,
null );
TokenEvaluator.processAfterAllPositiveConstraintOk( new LeapsTuple( new LeapsFactHandle[0],
rule,
context ),
rule,
this );
}
}
} finally {
this.getLock().unlock();
}
}
protected void removeRule(final List rules) {
this.getLock().lock();
try {
ArrayList ruleHandlesList;
LeapsRule leapsRule;
LeapsRuleHandle ruleHandle;
for ( final Iterator it = rules.iterator(); it.hasNext(); ) {
leapsRule = (LeapsRule) it.next();
// some times rules do not have "normal" constraints and only
// not and exists
if ( leapsRule.getNumberOfColumns() > 0 ) {
ruleHandlesList = (ArrayList) this.leapsRulesToHandlesMap.remove( leapsRule );
for ( int i = 0; i < ruleHandlesList.size(); i++ ) {
ruleHandle = (LeapsRuleHandle) ruleHandlesList.get( i );
//
this.getFactTable( leapsRule.getColumnClassObjectTypeAtPosition( i ) ).removeRule( this, ruleHandle );
}
}
//
}
final Rule rule = ((LeapsRule) rules.get( 0 )).getRule();
final FastMap activations = (FastMap) this.rulesActivationsMap.remove( rule );
if ( activations != null ) {
for ( final Iterator activationsIt = activations.keySet( ).iterator(); activationsIt.hasNext(); ) {
final Activation activation = (Activation) activationsIt.next();
((LeapsTuple) activation.getTuple()).setActivation( null );
this.tms.removeLogicalDependencies( activation,
activation.getPropagationContext(),
rule );
}
}
propagateQueuedActions();
} finally {
this.getLock().unlock();
}
}
/**
* main loop
*
*/
public final synchronized void fireAllRules(final AgendaFilter agendaFilter) throws FactException {
// If we're already firing a rule, then it'll pick up
// the firing for any other assertObject(..) that get
// nested inside, avoiding concurrent-modification
// exceptions, depending on code paths of the actions.
if ( !this.firing ) {
try {
this.firing = true;
boolean nothingToProcess = false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -