Source Code Cross Referenced for AbstractWorkingMemory.java in  » Rule-Engine » drolls-Rule-Engine » org » drools » common » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Rule Engine » drolls Rule Engine » org.drools.common 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package org.drools.common;
0002:
0003:        /*
0004:         * Copyright 2005 JBoss Inc
0005:         * 
0006:         * Licensed under the Apache License, Version 2.0 (the "License");
0007:         * you may not use this file except in compliance with the License.
0008:         * You may obtain a copy of the License at
0009:         * 
0010:         *      http://www.apache.org/licenses/LICENSE-2.0
0011:         * 
0012:         * Unless required by applicable law or agreed to in writing, software
0013:         * distributed under the License is distributed on an "AS IS" BASIS,
0014:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0015:         * See the License for the specific language governing permissions and
0016:         * limitations under the License.
0017:         */
0018:
0019:        import java.beans.PropertyChangeEvent;
0020:        import java.beans.PropertyChangeListener;
0021:        import java.io.Serializable;
0022:        import java.lang.reflect.InvocationTargetException;
0023:        import java.lang.reflect.Method;
0024:        import java.util.ArrayList;
0025:        import java.util.Collections;
0026:        import java.util.HashMap;
0027:        import java.util.Iterator;
0028:        import java.util.List;
0029:        import java.util.Map;
0030:        import java.util.Map.Entry;
0031:
0032:        import org.drools.Agenda;
0033:        import org.drools.FactException;
0034:        import org.drools.FactHandle;
0035:        import org.drools.ObjectFilter;
0036:        import org.drools.Otherwise;
0037:        import org.drools.QueryResults;
0038:        import org.drools.RuleBase;
0039:        import org.drools.RuleBaseConfiguration;
0040:        import org.drools.RuntimeDroolsException;
0041:        import org.drools.WorkingMemory;
0042:        import org.drools.RuleBaseConfiguration.AssertBehaviour;
0043:        import org.drools.RuleBaseConfiguration.LogicalOverride;
0044:        import org.drools.base.MapGlobalResolver;
0045:        import org.drools.base.ShadowProxy;
0046:        import org.drools.event.AgendaEventListener;
0047:        import org.drools.event.AgendaEventSupport;
0048:        import org.drools.event.RuleFlowEventListener;
0049:        import org.drools.event.RuleFlowEventSupport;
0050:        import org.drools.event.WorkingMemoryEventListener;
0051:        import org.drools.event.WorkingMemoryEventSupport;
0052:        import org.drools.reteoo.LIANodePropagation;
0053:        import org.drools.rule.Declaration;
0054:        import org.drools.rule.Rule;
0055:        import org.drools.ruleflow.common.core.Process;
0056:        import org.drools.ruleflow.common.instance.ProcessInstance;
0057:        import org.drools.ruleflow.core.RuleFlowProcess;
0058:        import org.drools.ruleflow.instance.RuleFlowProcessInstance;
0059:        import org.drools.ruleflow.instance.impl.RuleFlowProcessInstanceImpl;
0060:        import org.drools.spi.Activation;
0061:        import org.drools.spi.AgendaFilter;
0062:        import org.drools.spi.AgendaGroup;
0063:        import org.drools.spi.AsyncExceptionHandler;
0064:        import org.drools.spi.FactHandleFactory;
0065:        import org.drools.spi.GlobalResolver;
0066:        import org.drools.spi.PropagationContext;
0067:        import org.drools.util.JavaIteratorAdapter;
0068:        import org.drools.util.ObjectHashMap;
0069:        import org.drools.util.PrimitiveLongMap;
0070:        import org.drools.util.AbstractHashTable.HashTableIterator;
0071:        import org.drools.util.concurrent.locks.Lock;
0072:        import org.drools.util.concurrent.locks.ReentrantLock;
0073:
0074:        /**
0075:         * Implementation of <code>WorkingMemory</code>.
0076:         * 
0077:         * @author <a href="mailto:bob@werken.com">bob mcwhirter </a>
0078:         * @author <a href="mailto:mark.proctor@jboss.com">Mark Proctor</a>
0079:         * @author <a href="mailto:simon@redhillconsulting.com.au">Simon Harris </a>
0080:         */
0081:        public abstract class AbstractWorkingMemory implements 
0082:                InternalWorkingMemoryActions, EventSupport,
0083:                PropertyChangeListener {
0084:            // ------------------------------------------------------------
0085:            // Constants
0086:            // ------------------------------------------------------------
0087:            protected static final Class[] ADD_REMOVE_PROPERTY_CHANGE_LISTENER_ARG_TYPES = new Class[] { PropertyChangeListener.class };
0088:
0089:            // ------------------------------------------------------------
0090:            // Instance members
0091:            // ------------------------------------------------------------
0092:            protected final long id;
0093:
0094:            /** The arguments used when adding/removing a property change listener. */
0095:            protected final Object[] addRemovePropertyChangeListenerArgs = new Object[] { this  };
0096:
0097:            /** The actual memory for the <code>JoinNode</code>s. */
0098:            protected final PrimitiveLongMap nodeMemories = new PrimitiveLongMap(
0099:                    32, 8);
0100:            /** Object-to-handle mapping. */
0101:            private final ObjectHashMap assertMap;
0102:            private final ObjectHashMap identityMap;
0103:
0104:            protected Map queryResults = Collections.EMPTY_MAP;
0105:
0106:            /** Global values which are associated with this memory. */
0107:            protected GlobalResolver globalResolver;
0108:
0109:            protected static final Object NULL = new Serializable() {
0110:                private static final long serialVersionUID = 400L;
0111:            };
0112:
0113:            /** The eventSupport */
0114:            protected WorkingMemoryEventSupport workingMemoryEventSupport = new WorkingMemoryEventSupport();
0115:
0116:            protected AgendaEventSupport agendaEventSupport = new AgendaEventSupport();
0117:
0118:            protected RuleFlowEventSupport ruleFlowEventSupport = new RuleFlowEventSupport();
0119:
0120:            /** The <code>RuleBase</code> with which this memory is associated. */
0121:            protected transient InternalRuleBase ruleBase;
0122:
0123:            protected final FactHandleFactory handleFactory;
0124:
0125:            protected final TruthMaintenanceSystem tms;
0126:
0127:            /** Rule-firing agenda. */
0128:            protected DefaultAgenda agenda;
0129:
0130:            protected final List actionQueue = new ArrayList();
0131:
0132:            protected final ReentrantLock lock = new ReentrantLock();
0133:
0134:            protected final boolean discardOnLogicalOverride;
0135:
0136:            protected long propagationIdCounter;
0137:
0138:            private final boolean maintainTms;
0139:
0140:            private final boolean sequential;
0141:
0142:            private List liaPropagations = Collections.EMPTY_LIST;
0143:
0144:            /** Flag to determine if a rule is currently being fired. */
0145:            protected boolean firing;
0146:
0147:            protected boolean halt;
0148:
0149:            private int processCounter;
0150:
0151:            // ------------------------------------------------------------
0152:            // Constructors
0153:            // ------------------------------------------------------------
0154:
0155:            /**
0156:             * Construct.
0157:             * 
0158:             * @param ruleBase
0159:             *            The backing rule-base.
0160:             */
0161:            public AbstractWorkingMemory(final int id,
0162:                    final InternalRuleBase ruleBase,
0163:                    final FactHandleFactory handleFactory) {
0164:                this .id = id;
0165:                this .ruleBase = ruleBase;
0166:                this .handleFactory = handleFactory;
0167:                this .globalResolver = new MapGlobalResolver();
0168:                this .maintainTms = this .ruleBase.getConfiguration()
0169:                        .isMaintainTms();
0170:                this .sequential = this .ruleBase.getConfiguration()
0171:                        .isSequential();
0172:
0173:                if (this .maintainTms) {
0174:                    this .tms = new TruthMaintenanceSystem(this );
0175:                } else {
0176:                    this .tms = null;
0177:                }
0178:
0179:                this .assertMap = new ObjectHashMap();
0180:                final RuleBaseConfiguration conf = this .ruleBase
0181:                        .getConfiguration();
0182:
0183:                if (conf.getAssertBehaviour() == AssertBehaviour.IDENTITY) {
0184:                    this .assertMap
0185:                            .setComparator(new IdentityAssertMapComparator());
0186:                    this .identityMap = assertMap;
0187:                } else {
0188:                    this .assertMap
0189:                            .setComparator(new EqualityAssertMapComparator());
0190:                    this .identityMap = new ObjectHashMap();
0191:                    this .identityMap
0192:                            .setComparator(new IdentityAssertMapComparator());
0193:                }
0194:
0195:                // Only takes effect if are using idententity behaviour for assert        
0196:                if (conf.getLogicalOverride() == LogicalOverride.DISCARD) {
0197:                    this .discardOnLogicalOverride = true;
0198:                } else {
0199:                    this .discardOnLogicalOverride = false;
0200:                }
0201:            }
0202:
0203:            // ------------------------------------------------------------
0204:            // Instance methods
0205:            // ------------------------------------------------------------    
0206:
0207:            void setRuleBase(final InternalRuleBase ruleBase) {
0208:                this .ruleBase = ruleBase;
0209:            }
0210:
0211:            public void setWorkingMemoryEventSupport(
0212:                    WorkingMemoryEventSupport workingMemoryEventSupport) {
0213:                this .workingMemoryEventSupport = workingMemoryEventSupport;
0214:            }
0215:
0216:            public void setAgendaEventSupport(
0217:                    AgendaEventSupport agendaEventSupport) {
0218:                this .agendaEventSupport = agendaEventSupport;
0219:            }
0220:
0221:            public void setRuleFlowEventSupport(
0222:                    RuleFlowEventSupport ruleFlowEventSupport) {
0223:                this .ruleFlowEventSupport = ruleFlowEventSupport;
0224:            }
0225:
0226:            public boolean isSequential() {
0227:                return this .sequential;
0228:            }
0229:
0230:            public void addLIANodePropagation(
0231:                    LIANodePropagation liaNodePropagation) {
0232:                if (this .liaPropagations == Collections.EMPTY_LIST) {
0233:                    this .liaPropagations = new ArrayList();
0234:                }
0235:                this .liaPropagations.add(liaNodePropagation);
0236:            }
0237:
0238:            public void addEventListener(
0239:                    final WorkingMemoryEventListener listener) {
0240:                try {
0241:                    this .lock.lock();
0242:                    this .workingMemoryEventSupport.addEventListener(listener);
0243:                } finally {
0244:                    this .lock.unlock();
0245:                }
0246:            }
0247:
0248:            public void removeEventListener(
0249:                    final WorkingMemoryEventListener listener) {
0250:                try {
0251:                    this .lock.lock();
0252:                    this .workingMemoryEventSupport
0253:                            .removeEventListener(listener);
0254:                } finally {
0255:                    this .lock.unlock();
0256:                }
0257:            }
0258:
0259:            public List getWorkingMemoryEventListeners() {
0260:                try {
0261:                    this .lock.lock();
0262:                    return this .workingMemoryEventSupport.getEventListeners();
0263:                } finally {
0264:                    this .lock.unlock();
0265:                }
0266:            }
0267:
0268:            public void addEventListener(final AgendaEventListener listener) {
0269:                try {
0270:                    this .lock.lock();
0271:                    this .agendaEventSupport.addEventListener(listener);
0272:                } finally {
0273:                    this .lock.unlock();
0274:                }
0275:            }
0276:
0277:            public void removeEventListener(final AgendaEventListener listener) {
0278:                try {
0279:                    this .lock.lock();
0280:                    this .agendaEventSupport.removeEventListener(listener);
0281:                } finally {
0282:                    this .lock.unlock();
0283:                }
0284:            }
0285:
0286:            public List getAgendaEventListeners() {
0287:                try {
0288:                    this .lock.lock();
0289:                    return this .agendaEventSupport.getEventListeners();
0290:                } finally {
0291:                    this .lock.unlock();
0292:                }
0293:            }
0294:
0295:            public void addEventListener(final RuleFlowEventListener listener) {
0296:                try {
0297:                    this .lock.lock();
0298:                    this .ruleFlowEventSupport.addEventListener(listener);
0299:                } finally {
0300:                    this .lock.unlock();
0301:                }
0302:            }
0303:
0304:            public void removeEventListener(final RuleFlowEventListener listener) {
0305:                try {
0306:                    this .lock.lock();
0307:                    this .ruleFlowEventSupport.removeEventListener(listener);
0308:                } finally {
0309:                    this .lock.unlock();
0310:                }
0311:            }
0312:
0313:            public List getRuleFlowEventListeners() {
0314:                try {
0315:                    this .lock.lock();
0316:                    return this .ruleFlowEventSupport.getEventListeners();
0317:                } finally {
0318:                    this .lock.unlock();
0319:                }
0320:            }
0321:
0322:            public FactHandleFactory getFactHandleFactory() {
0323:                return this .handleFactory;
0324:            }
0325:
0326:            public void setGlobal(final String identifier, final Object value) {
0327:                // Cannot set null values
0328:                if (value == null) {
0329:                    return;
0330:                }
0331:
0332:                try {
0333:                    this .lock.lock();
0334:                    // Make sure the global has been declared in the RuleBase
0335:                    final Map globalDefintions = this .ruleBase.getGlobals();
0336:                    final Class type = (Class) globalDefintions.get(identifier);
0337:                    if ((type == null)) {
0338:                        throw new RuntimeException("Unexpected global ["
0339:                                + identifier + "]");
0340:                    } else if (!type.isInstance(value)) {
0341:                        throw new RuntimeException("Illegal class for global. "
0342:                                + "Expected [" + type.getName() + "], "
0343:                                + "found [" + value.getClass().getName() + "].");
0344:
0345:                    } else {
0346:                        this .globalResolver.setGlobal(identifier, value);
0347:                    }
0348:                } finally {
0349:                    this .lock.unlock();
0350:                }
0351:            }
0352:
0353:            public void setGlobalResolver(final GlobalResolver globalResolver) {
0354:                try {
0355:                    this .lock.lock();
0356:                    this .globalResolver = globalResolver;
0357:                } finally {
0358:                    this .lock.unlock();
0359:                }
0360:            }
0361:
0362:            public GlobalResolver getGlobalResolver() {
0363:                return this .globalResolver;
0364:            }
0365:
0366:            public long getId() {
0367:                return this .id;
0368:            }
0369:
0370:            public Object getGlobal(final String identifier) {
0371:                try {
0372:                    this .lock.lock();
0373:                    return this .globalResolver.resolveGlobal(identifier);
0374:                } finally {
0375:                    this .lock.unlock();
0376:                }
0377:            }
0378:
0379:            public Agenda getAgenda() {
0380:                return this .agenda;
0381:            }
0382:
0383:            public void clearAgenda() {
0384:                this .agenda.clearAgenda();
0385:            }
0386:
0387:            public void clearAgendaGroup(final String group) {
0388:                this .agenda.clearAgendaGroup(group);
0389:            }
0390:
0391:            public void clearActivationGroup(final String group) {
0392:                this .agenda.clearActivationGroup(group);
0393:            }
0394:
0395:            public void clearRuleFlowGroup(final String group) {
0396:                this .agenda.clearRuleFlowGroup(group);
0397:            }
0398:
0399:            public RuleBase getRuleBase() {
0400:                return this .ruleBase;
0401:            }
0402:
0403:            public void halt() {
0404:                this .halt = true;
0405:            }
0406:
0407:            public synchronized void fireAllRules() throws FactException {
0408:                fireAllRules(null, -1);
0409:            }
0410:
0411:            public synchronized void fireAllRules(int fireLimit)
0412:                    throws FactException {
0413:                fireAllRules(null, fireLimit);
0414:            }
0415:
0416:            public synchronized void fireAllRules(
0417:                    final AgendaFilter agendaFilter) throws FactException {
0418:                fireAllRules(agendaFilter, -1);
0419:            }
0420:
0421:            public synchronized void fireAllRules(
0422:                    final AgendaFilter agendaFilter, int fireLimit)
0423:                    throws FactException {
0424:                // If we're already firing a rule, then it'll pick up
0425:                // the firing for any other assertObject(..) that get
0426:                // nested inside, avoiding concurrent-modification
0427:                // exceptions, depending on code paths of the actions.          
0428:                this .halt = false;
0429:
0430:                if (isSequential()) {
0431:                    for (Iterator it = this .liaPropagations.iterator(); it
0432:                            .hasNext();) {
0433:                        ((LIANodePropagation) it.next()).doPropagation(this );
0434:                    }
0435:                }
0436:
0437:                if (!this .actionQueue.isEmpty()) {
0438:                    executeQueuedActions();
0439:                }
0440:
0441:                boolean noneFired = true;
0442:
0443:                if (!this .firing) {
0444:                    try {
0445:                        this .firing = true;
0446:
0447:                        while (continueFiring(fireLimit)
0448:                                && this .agenda.fireNextItem(agendaFilter)) {
0449:                            fireLimit = updateFireLimit(fireLimit);
0450:                            noneFired = false;
0451:                            if (!this .actionQueue.isEmpty()) {
0452:                                executeQueuedActions();
0453:                            }
0454:                        }
0455:                    } finally {
0456:                        this .firing = false;
0457:                        // @todo (mproctor) disabling Otherwise management for now, not happy with the current implementation
0458:                        //                if ( noneFired ) {
0459:                        //                    doOtherwise( agendaFilter,
0460:                        //                                 fireLimit );
0461:                        //                }
0462:
0463:                    }
0464:                }
0465:            }
0466:
0467:            private final boolean continueFiring(final int fireLimit) {
0468:                return (!halt) && (fireLimit != 0);
0469:            }
0470:
0471:            private final int updateFireLimit(final int fireLimit) {
0472:                return fireLimit > 0 ? fireLimit - 1 : fireLimit;
0473:            }
0474:
0475:            /**
0476:             * This does the "otherwise" phase of processing.
0477:             * If no items are fired, then it will assert a temporary "Otherwise"
0478:             * fact and allow any rules to fire to handle "otherwise" cases.
0479:             */
0480:            private void doOtherwise(final AgendaFilter agendaFilter,
0481:                    int fireLimit) {
0482:                final FactHandle handle = this .insert(new Otherwise());
0483:                if (!this .actionQueue.isEmpty()) {
0484:                    executeQueuedActions();
0485:                }
0486:
0487:                while (continueFiring(fireLimit)
0488:                        && this .agenda.fireNextItem(agendaFilter)) {
0489:                    fireLimit = updateFireLimit(fireLimit);
0490:                }
0491:
0492:                this .retract(handle);
0493:            }
0494:
0495:            //
0496:            //        MN: The following is the traditional fireAllRules (without otherwise).
0497:            //            Purely kept here as this implementation of otherwise is still experimental.    
0498:            //    
0499:            //    public synchronized void fireAllRules(final AgendaFilter agendaFilter) throws FactException {
0500:            //        // If we're already firing a rule, then it'll pick up
0501:            //        // the firing for any other assertObject(..) that get
0502:            //        // nested inside, avoiding concurrent-modification
0503:            //        // exceptions, depending on code paths of the actions.
0504:            //
0505:            //        if ( !this.factQueue.isEmpty() ) {
0506:            //            propagateQueuedActions();
0507:            //        }
0508:            //
0509:            //        if ( !this.firing ) {
0510:            //            try {
0511:            //                this.firing = true;
0512:            //
0513:            //                while ( this.agenda.fireNextItem( agendaFilter ) ) {
0514:            //                    ;
0515:            //                }
0516:            //            } finally {
0517:            //                this.firing = false;
0518:            //            }
0519:            //        }
0520:            //    }    
0521:
0522:            /**
0523:             * Returns the fact Object for the given <code>FactHandle</code>. It
0524:             * actually attemps to return the value from the handle, before retrieving
0525:             * it from objects map.
0526:             * 
0527:             * @see WorkingMemory
0528:             * 
0529:             * @param handle
0530:             *            The <code>FactHandle</code> reference for the
0531:             *            <code>Object</code> lookup
0532:             * 
0533:             */
0534:            public Object getObject(final FactHandle handle) {
0535:                try {
0536:                    this .lock.lock();
0537:
0538:                    // Make sure the FactHandle is from this WorkingMemory
0539:                    final InternalFactHandle internalHandle = (InternalFactHandle) this .assertMap
0540:                            .get(handle);
0541:                    if (internalHandle == null) {
0542:                        return null;
0543:                    }
0544:
0545:                    Object object = internalHandle.getObject();
0546:
0547:                    if (object != null && internalHandle.isShadowFact()) {
0548:                        object = ((ShadowProxy) object).getShadowedObject();
0549:                    }
0550:
0551:                    return object;
0552:                } finally {
0553:                    this .lock.unlock();
0554:                }
0555:
0556:            }
0557:
0558:            /**
0559:             * @see WorkingMemory
0560:             */
0561:            public FactHandle getFactHandle(final Object object) {
0562:                try {
0563:                    this .lock.lock();
0564:                    final FactHandle factHandle = (FactHandle) this .identityMap
0565:                            .get(object);
0566:
0567:                    return factHandle;
0568:                } finally {
0569:                    this .lock.unlock();
0570:                }
0571:            }
0572:
0573:            /** 
0574:             * This is an internal method, used to avoid java.util.Iterator adaptors
0575:             */
0576:            public ObjectHashMap getFactHandleMap() {
0577:                return this .assertMap;
0578:            }
0579:
0580:            /**
0581:             * This class is not thread safe, changes to the working memory during iteration may give unexpected results
0582:             */
0583:            public Iterator iterateObjects() {
0584:                HashTableIterator iterator = new HashTableIterator(
0585:                        this .assertMap);
0586:                iterator.reset();
0587:                return new JavaIteratorAdapter(iterator,
0588:                        JavaIteratorAdapter.OBJECT);
0589:            }
0590:
0591:            /**
0592:             * This class is not thread safe, changes to the working memory during iteration may give unexpected results
0593:             */
0594:            public Iterator iterateObjects(ObjectFilter filter) {
0595:                HashTableIterator iterator = new HashTableIterator(
0596:                        this .assertMap);
0597:                iterator.reset();
0598:                return new JavaIteratorAdapter(iterator,
0599:                        JavaIteratorAdapter.OBJECT, filter);
0600:            }
0601:
0602:            /**
0603:             * This class is not thread safe, changes to the working memory during iteration may give unexpected results
0604:             */
0605:            public Iterator iterateFactHandles() {
0606:                HashTableIterator iterator = new HashTableIterator(
0607:                        this .assertMap);
0608:                iterator.reset();
0609:                return new JavaIteratorAdapter(iterator,
0610:                        JavaIteratorAdapter.FACT_HANDLE);
0611:            }
0612:
0613:            /**
0614:             * This class is not thread safe, changes to the working memory during iteration may give unexpected results
0615:             */
0616:            public Iterator iterateFactHandles(ObjectFilter filter) {
0617:                HashTableIterator iterator = new HashTableIterator(
0618:                        this .assertMap);
0619:                iterator.reset();
0620:                return new JavaIteratorAdapter(iterator,
0621:                        JavaIteratorAdapter.FACT_HANDLE, filter);
0622:            }
0623:
0624:            public abstract QueryResults getQueryResults(String query);
0625:
0626:            public AgendaGroup getFocus() {
0627:                return this .agenda.getFocus();
0628:            }
0629:
0630:            public void setFocus(final String focus) {
0631:                this .agenda.setFocus(focus);
0632:            }
0633:
0634:            public void setFocus(final AgendaGroup focus) {
0635:                this .agenda.setFocus(focus);
0636:            }
0637:
0638:            public TruthMaintenanceSystem getTruthMaintenanceSystem() {
0639:                return this .tms;
0640:            }
0641:
0642:            /**
0643:             * @see WorkingMemory
0644:             */
0645:            public FactHandle insert(final Object object) throws FactException {
0646:                return insert(object, /* Not-Dynamic */
0647:                false, false, null, null);
0648:            }
0649:
0650:            /**
0651:             * @see WorkingMemory
0652:             */
0653:            public FactHandle insertLogical(final Object object)
0654:                    throws FactException {
0655:                return insert(object, /* Not-Dynamic */
0656:                false, true, null, null);
0657:            }
0658:
0659:            public FactHandle insert(final Object object, final boolean dynamic)
0660:                    throws FactException {
0661:                return insert(object, dynamic, false, null, null);
0662:            }
0663:
0664:            public FactHandle insertLogical(final Object object,
0665:                    final boolean dynamic) throws FactException {
0666:                return insert(object, dynamic, true, null, null);
0667:            }
0668:
0669:            public FactHandle insert(final Object object,
0670:                    final boolean dynamic, boolean logical, final Rule rule,
0671:                    final Activation activation) throws FactException {
0672:                if (object == null) {
0673:                    // you cannot assert a null object
0674:                    return null;
0675:                }
0676:
0677:                InternalFactHandle handle = null;
0678:
0679:                if (isSequential()) {
0680:                    handle = this .handleFactory.newFactHandle(object);
0681:                    addHandleToMaps(handle);
0682:                    insert(handle, object, rule, activation);
0683:                    return handle;
0684:                }
0685:
0686:                try {
0687:                    this .lock.lock();
0688:                    // check if the object already exists in the WM
0689:                    handle = (InternalFactHandle) this .assertMap.get(object);
0690:
0691:                    if (this .maintainTms) {
0692:
0693:                        EqualityKey key = null;
0694:
0695:                        if (handle == null) {
0696:                            // lets see if the object is already logical asserted
0697:                            key = this .tms.get(object);
0698:                        } else {
0699:                            // Object is already asserted, so check and possibly correct its
0700:                            // status and then return the handle
0701:                            key = handle.getEqualityKey();
0702:
0703:                            if (key.getStatus() == EqualityKey.STATED) {
0704:                                // return null as you cannot justify a stated object.
0705:                                return handle;
0706:                            }
0707:
0708:                            if (!logical) {
0709:                                // this object was previously justified, so we have to
0710:                                // override it to stated
0711:                                key.setStatus(EqualityKey.STATED);
0712:                                this .tms.removeLogicalDependencies(handle);
0713:                            } else {
0714:                                // this was object is already justified, so just add new
0715:                                // logical dependency
0716:                                this .tms.addLogicalDependency(handle,
0717:                                        activation, activation
0718:                                                .getPropagationContext(), rule);
0719:                            }
0720:
0721:                            return handle;
0722:                        }
0723:
0724:                        // At this point we know the handle is null
0725:                        if (key == null) {
0726:                            // key is also null, so treat as a totally new stated/logical
0727:                            // assert
0728:                            handle = this .handleFactory.newFactHandle(object);
0729:                            addHandleToMaps(handle);
0730:
0731:                            key = new EqualityKey(handle);
0732:                            handle.setEqualityKey(key);
0733:                            this .tms.put(key);
0734:                            if (!logical) {
0735:                                key.setStatus(EqualityKey.STATED);
0736:                            } else {
0737:                                key.setStatus(EqualityKey.JUSTIFIED);
0738:                                this .tms.addLogicalDependency(handle,
0739:                                        activation, activation
0740:                                                .getPropagationContext(), rule);
0741:                            }
0742:                        } else if (!logical) {
0743:                            if (key.getStatus() == EqualityKey.JUSTIFIED) {
0744:                                // Its previous justified, so switch to stated and remove
0745:                                // logical dependencies
0746:                                final InternalFactHandle justifiedHandle = key
0747:                                        .getFactHandle();
0748:                                this .tms
0749:                                        .removeLogicalDependencies(justifiedHandle);
0750:
0751:                                if (this .discardOnLogicalOverride) {
0752:                                    // override, setting to new instance, and return
0753:                                    // existing handle
0754:                                    key.setStatus(EqualityKey.STATED);
0755:                                    handle = key.getFactHandle();
0756:
0757:                                    if (this .ruleBase.getConfiguration()
0758:                                            .getAssertBehaviour() == AssertBehaviour.IDENTITY) {
0759:                                        // as assertMap may be using an "identity" equality comparator,
0760:                                        // we need to remove the handle from the map, before replacing the object
0761:                                        // and then re-add the handle. Otherwise we may end up with a leak.
0762:                                        this .assertMap.remove(handle);
0763:                                        Object oldObject = handle.getObject();
0764:                                        if (oldObject instanceof  ShadowProxy) {
0765:                                            ((ShadowProxy) oldObject)
0766:                                                    .setShadowedObject(object);
0767:                                        } else {
0768:                                            handle.setObject(object);
0769:                                        }
0770:                                        this .assertMap.put(handle, handle,
0771:                                                false);
0772:                                    } else {
0773:                                        Object oldObject = handle.getObject();
0774:                                        if (oldObject instanceof  ShadowProxy) {
0775:                                            ((ShadowProxy) oldObject)
0776:                                                    .setShadowedObject(object);
0777:                                        } else {
0778:                                            handle.setObject(object);
0779:                                        }
0780:                                    }
0781:                                    return handle;
0782:                                } else {
0783:                                    // override, then instantiate new handle for assertion
0784:                                    key.setStatus(EqualityKey.STATED);
0785:                                    handle = this .handleFactory
0786:                                            .newFactHandle(object);
0787:                                    handle.setEqualityKey(key);
0788:                                    key.addFactHandle(handle);
0789:                                    addHandleToMaps(handle);
0790:
0791:                                }
0792:
0793:                            } else {
0794:                                handle = this .handleFactory
0795:                                        .newFactHandle(object);
0796:                                addHandleToMaps(handle);
0797:                                key.addFactHandle(handle);
0798:                                handle.setEqualityKey(key);
0799:
0800:                            }
0801:
0802:                        } else {
0803:                            if (key.getStatus() == EqualityKey.JUSTIFIED) {
0804:                                // only add as logical dependency if this wasn't previously
0805:                                // stated
0806:                                this .tms.addLogicalDependency(key
0807:                                        .getFactHandle(), activation,
0808:                                        activation.getPropagationContext(),
0809:                                        rule);
0810:                                return key.getFactHandle();
0811:                            } else {
0812:                                // You cannot justify a previously stated equality equal
0813:                                // object, so return null
0814:                                return null;
0815:                            }
0816:                        }
0817:
0818:                    } else {
0819:                        if (handle != null) {
0820:                            return handle;
0821:                        }
0822:                        handle = this .handleFactory.newFactHandle(object);
0823:                        addHandleToMaps(handle);
0824:
0825:                    }
0826:
0827:                    if (dynamic) {
0828:                        addPropertyChangeListener(object);
0829:                    }
0830:
0831:                    insert(handle, object, rule, activation);
0832:
0833:                } finally {
0834:                    this .lock.unlock();
0835:                }
0836:                return handle;
0837:            }
0838:
0839:            private void insert(InternalFactHandle handle, Object object,
0840:                    Rule rule, Activation activation) {
0841:                this .ruleBase.executeQueuedActions();
0842:
0843:                if (activation != null) {
0844:                    // release resources so that they can be GC'ed
0845:                    activation.getPropagationContext().releaseResources();
0846:                }
0847:                final PropagationContext propagationContext = new PropagationContextImpl(
0848:                        this .propagationIdCounter++,
0849:                        PropagationContext.ASSERTION, rule, activation,
0850:                        this .agenda.getActiveActivations(), this .agenda
0851:                                .getDormantActivations());
0852:
0853:                doInsert(handle, object, propagationContext);
0854:
0855:                this .workingMemoryEventSupport.fireObjectInserted(
0856:                        propagationContext, handle, object, this );
0857:
0858:                if (!this .actionQueue.isEmpty()) {
0859:                    executeQueuedActions();
0860:                }
0861:            }
0862:
0863:            protected void addPropertyChangeListener(final Object object) {
0864:                try {
0865:                    final Method method = object
0866:                            .getClass()
0867:                            .getMethod(
0868:                                    "addPropertyChangeListener",
0869:                                    AbstractWorkingMemory.ADD_REMOVE_PROPERTY_CHANGE_LISTENER_ARG_TYPES);
0870:
0871:                    method.invoke(object,
0872:                            this .addRemovePropertyChangeListenerArgs);
0873:                } catch (final NoSuchMethodException e) {
0874:                    System.err
0875:                            .println("Warning: Method addPropertyChangeListener not found"
0876:                                    + " on the class "
0877:                                    + object.getClass()
0878:                                    + " so Drools will be unable to process JavaBean"
0879:                                    + " PropertyChangeEvents on the asserted Object");
0880:                } catch (final IllegalArgumentException e) {
0881:                    System.err
0882:                            .println("Warning: The addPropertyChangeListener method"
0883:                                    + " on the class "
0884:                                    + object.getClass()
0885:                                    + " does not take"
0886:                                    + " a simple PropertyChangeListener argument"
0887:                                    + " so Drools will be unable to process JavaBean"
0888:                                    + " PropertyChangeEvents on the asserted Object");
0889:                } catch (final IllegalAccessException e) {
0890:                    System.err
0891:                            .println("Warning: The addPropertyChangeListener method"
0892:                                    + " on the class "
0893:                                    + object.getClass()
0894:                                    + " is not public"
0895:                                    + " so Drools will be unable to process JavaBean"
0896:                                    + " PropertyChangeEvents on the asserted Object");
0897:                } catch (final InvocationTargetException e) {
0898:                    System.err
0899:                            .println("Warning: The addPropertyChangeListener method"
0900:                                    + " on the class "
0901:                                    + object.getClass()
0902:                                    + " threw an InvocationTargetException"
0903:                                    + " so Drools will be unable to process JavaBean"
0904:                                    + " PropertyChangeEvents on the asserted Object: "
0905:                                    + e.getMessage());
0906:                } catch (final SecurityException e) {
0907:                    System.err
0908:                            .println("Warning: The SecurityManager controlling the class "
0909:                                    + object.getClass()
0910:                                    + " did not allow the lookup of a"
0911:                                    + " addPropertyChangeListener method"
0912:                                    + " so Drools will be unable to process JavaBean"
0913:                                    + " PropertyChangeEvents on the asserted Object: "
0914:                                    + e.getMessage());
0915:                }
0916:            }
0917:
0918:            public abstract void doInsert(InternalFactHandle factHandle,
0919:                    Object object, PropagationContext propagationContext)
0920:                    throws FactException;
0921:
0922:            protected void removePropertyChangeListener(final FactHandle handle) {
0923:                Object object = null;
0924:                try {
0925:                    object = getObject(handle);
0926:
0927:                    if (object != null) {
0928:                        final Method mehod = object
0929:                                .getClass()
0930:                                .getMethod(
0931:                                        "removePropertyChangeListener",
0932:                                        AbstractWorkingMemory.ADD_REMOVE_PROPERTY_CHANGE_LISTENER_ARG_TYPES);
0933:
0934:                        mehod.invoke(object,
0935:                                this .addRemovePropertyChangeListenerArgs);
0936:                    }
0937:                } catch (final NoSuchMethodException e) {
0938:                    // The removePropertyChangeListener method on the class
0939:                    // was not found so Drools will be unable to
0940:                    // stop processing JavaBean PropertyChangeEvents
0941:                    // on the retracted Object
0942:                } catch (final IllegalArgumentException e) {
0943:                    throw new RuntimeDroolsException(
0944:                            "Warning: The removePropertyChangeListener method on the class "
0945:                                    + object.getClass()
0946:                                    + " does not take a simple PropertyChangeListener argument so Drools will be unable to stop processing JavaBean"
0947:                                    + " PropertyChangeEvents on the retracted Object");
0948:                } catch (final IllegalAccessException e) {
0949:                    throw new RuntimeDroolsException(
0950:                            "Warning: The removePropertyChangeListener method on the class "
0951:                                    + object.getClass()
0952:                                    + " is not public so Drools will be unable to stop processing JavaBean PropertyChangeEvents on the retracted Object");
0953:                } catch (final InvocationTargetException e) {
0954:                    throw new RuntimeDroolsException(
0955:                            "Warning: The removePropertyChangeL istener method on the class "
0956:                                    + object.getClass()
0957:                                    + " threw an InvocationTargetException so Drools will be unable to stop processing JavaBean"
0958:                                    + " PropertyChangeEvents on the retracted Object: "
0959:                                    + e.getMessage());
0960:                } catch (final SecurityException e) {
0961:                    throw new RuntimeDroolsException(
0962:                            "Warning: The SecurityManager controlling the class "
0963:                                    + object.getClass()
0964:                                    + " did not allow the lookup of a removePropertyChangeListener method so Drools will be unable to stop processing JavaBean"
0965:                                    + " PropertyChangeEvents on the retracted Object: "
0966:                                    + e.getMessage());
0967:                }
0968:            }
0969:
0970:            public void retract(final FactHandle handle) throws FactException {
0971:                retract(handle, true, true, null, null);
0972:            }
0973:
0974:            public abstract void doRetract(InternalFactHandle factHandle,
0975:                    PropagationContext propagationContext);
0976:
0977:            /**
0978:             * @see WorkingMemory
0979:             */
0980:            public void retract(final FactHandle factHandle,
0981:                    final boolean removeLogical, final boolean updateEqualsMap,
0982:                    final Rule rule, final Activation activation)
0983:                    throws FactException {
0984:                try {
0985:                    this .lock.lock();
0986:                    this .ruleBase.executeQueuedActions();
0987:
0988:                    final InternalFactHandle handle = (InternalFactHandle) factHandle;
0989:                    if (handle.getId() == -1) {
0990:                        // can't retract an already retracted handle
0991:                        return;
0992:                    }
0993:                    removePropertyChangeListener(handle);
0994:
0995:                    if (activation != null) {
0996:                        // release resources so that they can be GC'ed
0997:                        activation.getPropagationContext().releaseResources();
0998:                    }
0999:                    final PropagationContext propagationContext = new PropagationContextImpl(
1000:                            this .propagationIdCounter++,
1001:                            PropagationContext.RETRACTION, rule, activation,
1002:                            this .agenda.getActiveActivations(), this .agenda
1003:                                    .getDormantActivations());
1004:
1005:                    doRetract(handle, propagationContext);
1006:
1007:                    if (this .maintainTms) {
1008:                        // Update the equality key, which maintains a list of stated
1009:                        // FactHandles
1010:                        final EqualityKey key = handle.getEqualityKey();
1011:
1012:                        // Its justified so attempt to remove any logical dependencies for
1013:                        // the handle
1014:                        if (key.getStatus() == EqualityKey.JUSTIFIED) {
1015:                            this .tms.removeLogicalDependencies(handle);
1016:                        }
1017:
1018:                        key.removeFactHandle(handle);
1019:                        handle.setEqualityKey(null);
1020:
1021:                        // If the equality key is now empty, then remove it
1022:                        if (key.isEmpty()) {
1023:                            this .tms.remove(key);
1024:                        }
1025:                    }
1026:
1027:                    final Object object = handle.getObject();
1028:
1029:                    this .workingMemoryEventSupport.fireObjectRetracted(
1030:                            propagationContext, handle, object, this );
1031:
1032:                    removeHandleFromMaps(handle);
1033:
1034:                    this .handleFactory.destroyFactHandle(handle);
1035:
1036:                    if (!this .actionQueue.isEmpty()) {
1037:                        executeQueuedActions();
1038:                    }
1039:                } finally {
1040:                    this .lock.unlock();
1041:                }
1042:            }
1043:
1044:            private void addHandleToMaps(InternalFactHandle handle) {
1045:                this .assertMap.put(handle, handle, false);
1046:                if (this .ruleBase.getConfiguration().getAssertBehaviour() == AssertBehaviour.EQUALITY) {
1047:                    this .identityMap.put(handle, handle, false);
1048:                }
1049:            }
1050:
1051:            private void removeHandleFromMaps(final InternalFactHandle handle) {
1052:                this .assertMap.remove(handle);
1053:                if (this .ruleBase.getConfiguration().getAssertBehaviour() == AssertBehaviour.EQUALITY) {
1054:                    this .identityMap.remove(handle);
1055:                }
1056:            }
1057:
1058:            public void modifyRetract(final FactHandle factHandle) {
1059:                modifyRetract(factHandle, null, null);
1060:            }
1061:
1062:            public void modifyRetract(final FactHandle factHandle,
1063:                    final Rule rule, final Activation activation) {
1064:                try {
1065:                    this .lock.lock();
1066:                    this .ruleBase.executeQueuedActions();
1067:
1068:                    // only needed if we maintain tms, but either way we must get it before we do the retract
1069:                    int status = -1;
1070:                    if (this .maintainTms) {
1071:                        status = ((InternalFactHandle) factHandle)
1072:                                .getEqualityKey().getStatus();
1073:                    }
1074:                    final InternalFactHandle handle = (InternalFactHandle) factHandle;
1075:                    //final Object originalObject = (handle.isShadowFact()) ? ((ShadowProxy) handle.getObject()).getShadowedObject() : handle.getObject();
1076:
1077:                    if (handle.getId() == -1) {
1078:                        // the handle is invalid, most likely already  retracted, so return
1079:                        return;
1080:                    }
1081:
1082:                    if (activation != null) {
1083:                        // release resources so that they can be GC'ed
1084:                        activation.getPropagationContext().releaseResources();
1085:                    }
1086:                    // Nowretract any trace  of the original fact
1087:                    final PropagationContext propagationContext = new PropagationContextImpl(
1088:                            this .propagationIdCounter++,
1089:                            PropagationContext.MODIFICATION, rule, activation,
1090:                            this .agenda.getActiveActivations(), this .agenda
1091:                                    .getDormantActivations());
1092:                    doRetract(handle, propagationContext);
1093:
1094:                    if (this .maintainTms) {
1095:
1096:                        // the hashCode and equality has changed, so we must update the EqualityKey
1097:                        EqualityKey key = handle.getEqualityKey();
1098:                        key.removeFactHandle(handle);
1099:
1100:                        // If the equality key is now empty, then remove it
1101:                        if (key.isEmpty()) {
1102:                            this .tms.remove(key);
1103:                        }
1104:                    }
1105:                } finally {
1106:                    this .lock.unlock();
1107:                }
1108:            }
1109:
1110:            public void modifyInsert(final FactHandle factHandle,
1111:                    final Object object) {
1112:                modifyInsert(factHandle, object, null, null);
1113:            }
1114:
1115:            public void modifyInsert(final FactHandle factHandle,
1116:                    final Object object, final Rule rule,
1117:                    final Activation activation) {
1118:                try {
1119:                    this .lock.lock();
1120:                    this .ruleBase.executeQueuedActions();
1121:
1122:                    final InternalFactHandle handle = (InternalFactHandle) factHandle;
1123:                    final Object originalObject = (handle.isShadowFact()) ? ((ShadowProxy) handle
1124:                            .getObject()).getShadowedObject()
1125:                            : handle.getObject();
1126:
1127:                    if (this .maintainTms) {
1128:                        EqualityKey key = handle.getEqualityKey();
1129:
1130:                        // now use an  existing  EqualityKey, if it exists, else create a new one
1131:                        key = this .tms.get(object);
1132:                        if (key == null) {
1133:                            key = new EqualityKey(handle, 0);
1134:                            this .tms.put(key);
1135:                        } else {
1136:                            key.addFactHandle(handle);
1137:                        }
1138:
1139:                        handle.setEqualityKey(key);
1140:                    }
1141:
1142:                    this .handleFactory.increaseFactHandleRecency(handle);
1143:
1144:                    if (activation != null) {
1145:                        // release resources so that they can be GC'ed
1146:                        activation.getPropagationContext().releaseResources();
1147:                    }
1148:                    // Nowretract any trace  of the original fact
1149:                    final PropagationContext propagationContext = new PropagationContextImpl(
1150:                            this .propagationIdCounter++,
1151:                            PropagationContext.MODIFICATION, rule, activation,
1152:                            this .agenda.getActiveActivations(), this .agenda
1153:                                    .getDormantActivations());
1154:
1155:                    doInsert(handle, object, propagationContext);
1156:
1157:                    this .workingMemoryEventSupport.fireObjectUpdated(
1158:                            propagationContext, factHandle, originalObject,
1159:                            object, this );
1160:
1161:                    propagationContext.clearRetractedTuples();
1162:
1163:                    if (!this .actionQueue.isEmpty()) {
1164:                        executeQueuedActions();
1165:                    }
1166:                } finally {
1167:                    this .lock.unlock();
1168:                }
1169:            }
1170:
1171:            public void update(final FactHandle handle, final Object object)
1172:                    throws FactException {
1173:                update(handle, object, null, null);
1174:            }
1175:
1176:            /**
1177:             * modify is implemented as half way retract / assert due to the truth
1178:             * maintenance issues.
1179:             * 
1180:             * @see WorkingMemory
1181:             */
1182:            public void update(final FactHandle factHandle,
1183:                    final Object object, final Rule rule,
1184:                    final Activation activation) throws FactException {
1185:                try {
1186:                    this .lock.lock();
1187:                    this .ruleBase.executeQueuedActions();
1188:
1189:                    // only needed if we maintain tms, but either way we must get it before we do the retract
1190:                    int status = -1;
1191:                    if (this .maintainTms) {
1192:                        status = ((InternalFactHandle) factHandle)
1193:                                .getEqualityKey().getStatus();
1194:                    }
1195:                    final InternalFactHandle handle = (InternalFactHandle) factHandle;
1196:                    final Object originalObject = (handle.isShadowFact()) ? ((ShadowProxy) handle
1197:                            .getObject()).getShadowedObject()
1198:                            : handle.getObject();
1199:
1200:                    if (handle.getId() == -1 || object == null) {
1201:                        // the handle is invalid, most likely already  retracted, so return
1202:                        // and we cannot assert a null object
1203:                        return;
1204:                    }
1205:
1206:                    if (activation != null) {
1207:                        // release resources so that they can be GC'ed
1208:                        activation.getPropagationContext().releaseResources();
1209:                    }
1210:                    // Nowretract any trace  of the original fact
1211:                    final PropagationContext propagationContext = new PropagationContextImpl(
1212:                            this .propagationIdCounter++,
1213:                            PropagationContext.MODIFICATION, rule, activation,
1214:                            this .agenda.getActiveActivations(), this .agenda
1215:                                    .getDormantActivations());
1216:                    doRetract(handle, propagationContext);
1217:
1218:                    if ((originalObject != object)
1219:                            || (this .ruleBase.getConfiguration()
1220:                                    .getAssertBehaviour() != AssertBehaviour.IDENTITY)) {
1221:                        removeHandleFromMaps(handle);
1222:
1223:                        // set anyway, so that it updates the hashCodes
1224:                        handle.setObject(object);
1225:                        addHandleToMaps(handle);
1226:                    }
1227:
1228:                    if (this .maintainTms) {
1229:
1230:                        // the hashCode and equality has changed, so we must update the EqualityKey
1231:                        EqualityKey key = handle.getEqualityKey();
1232:                        key.removeFactHandle(handle);
1233:
1234:                        // If the equality key is now empty, then remove it
1235:                        if (key.isEmpty()) {
1236:                            this .tms.remove(key);
1237:                        }
1238:
1239:                        // now use an  existing  EqualityKey, if it exists, else create a new one
1240:                        key = this .tms.get(object);
1241:                        if (key == null) {
1242:                            key = new EqualityKey(handle, status);
1243:                            this .tms.put(key);
1244:                        } else {
1245:                            key.addFactHandle(handle);
1246:                        }
1247:
1248:                        handle.setEqualityKey(key);
1249:                    }
1250:
1251:                    this .handleFactory.increaseFactHandleRecency(handle);
1252:
1253:                    doInsert(handle, object, propagationContext);
1254:
1255:                    this .workingMemoryEventSupport.fireObjectUpdated(
1256:                            propagationContext, factHandle, originalObject,
1257:                            object, this );
1258:
1259:                    propagationContext.clearRetractedTuples();
1260:
1261:                    if (!this .actionQueue.isEmpty()) {
1262:                        executeQueuedActions();
1263:                    }
1264:                } finally {
1265:                    this .lock.unlock();
1266:                }
1267:            }
1268:
1269:            public void executeQueuedActions() {
1270:                while (!actionQueue.isEmpty()) {
1271:                    final WorkingMemoryAction action = (WorkingMemoryAction) actionQueue
1272:                            .get(0);
1273:                    actionQueue.remove(0);
1274:                    action.execute(this );
1275:                }
1276:                //        for ( final Iterator it = this.actionQueue.iterator(); it.hasNext(); ) {
1277:                //            final WorkingMemoryAction action = (WorkingMemoryAction) it.next();
1278:                //            it.remove();
1279:                //            action.execute( this );
1280:                //        }
1281:            }
1282:
1283:            public void queueWorkingMemoryAction(
1284:                    final WorkingMemoryAction action) {
1285:                this .actionQueue.add(action);
1286:            }
1287:
1288:            public void removeLogicalDependencies(final Activation activation,
1289:                    final PropagationContext context, final Rule rule)
1290:                    throws FactException {
1291:                if (this .maintainTms) {
1292:                    this .tms.removeLogicalDependencies(activation, context,
1293:                            rule);
1294:                }
1295:            }
1296:
1297:            /**
1298:             * Retrieve the <code>JoinMemory</code> for a particular
1299:             * <code>JoinNode</code>.
1300:             * 
1301:             * @param node
1302:             *            The <code>JoinNode</code> key.
1303:             * 
1304:             * @return The node's memory.
1305:             */
1306:            public Object getNodeMemory(final NodeMemory node) {
1307:                Object memory = this .nodeMemories.get(node.getId());
1308:
1309:                if (memory == null) {
1310:                    memory = node
1311:                            .createMemory(this .ruleBase.getConfiguration());
1312:
1313:                    this .nodeMemories.put(node.getId(), memory);
1314:                }
1315:
1316:                return memory;
1317:            }
1318:
1319:            public void clearNodeMemory(final NodeMemory node) {
1320:                this .nodeMemories.remove(node.getId());
1321:            }
1322:
1323:            public WorkingMemoryEventSupport getWorkingMemoryEventSupport() {
1324:                return this .workingMemoryEventSupport;
1325:            }
1326:
1327:            public AgendaEventSupport getAgendaEventSupport() {
1328:                return this .agendaEventSupport;
1329:            }
1330:
1331:            public RuleFlowEventSupport getRuleFlowEventSupport() {
1332:                return this .ruleFlowEventSupport;
1333:            }
1334:
1335:            /**
1336:             * Sets the AsyncExceptionHandler to handle exceptions thrown by the Agenda
1337:             * Scheduler used for duration rules.
1338:             * 
1339:             * @param handler
1340:             */
1341:            public void setAsyncExceptionHandler(
1342:                    final AsyncExceptionHandler handler) {
1343:                // this.agenda.setAsyncExceptionHandler( handler );
1344:            }
1345:
1346:            /*
1347:             * public void dumpMemory() { Iterator it = this.joinMemories.keySet(
1348:             * ).iterator( ); while ( it.hasNext( ) ) { ((JoinMemory)
1349:             * this.joinMemories.get( it.next( ) )).dump( ); } }
1350:             */
1351:
1352:            public void propertyChange(final PropertyChangeEvent event) {
1353:                final Object object = event.getSource();
1354:
1355:                try {
1356:                    update(getFactHandle(object), object);
1357:                } catch (final FactException e) {
1358:                    throw new RuntimeException(e.getMessage());
1359:                }
1360:            }
1361:
1362:            public long getNextPropagationIdCounter() {
1363:                return this .propagationIdCounter++;
1364:            }
1365:
1366:            public Lock getLock() {
1367:                return this .lock;
1368:            }
1369:
1370:            public class RuleFlowDeactivateEvent {
1371:
1372:                public void propagate() {
1373:
1374:                }
1375:            }
1376:
1377:            public ProcessInstance startProcess(final String processId) {
1378:                final Process process = ((InternalRuleBase) getRuleBase())
1379:                        .getProcess(processId);
1380:                if (process == null) {
1381:                    throw new IllegalArgumentException("Unknown process ID: "
1382:                            + processId);
1383:                }
1384:                if (process instanceof  RuleFlowProcess) {
1385:                    final RuleFlowProcessInstance processInstance = new RuleFlowProcessInstanceImpl();
1386:                    processInstance.setWorkingMemory(this );
1387:                    processInstance.setProcess(process);
1388:                    processInstance.setId(++processCounter);
1389:                    processInstance.start();
1390:
1391:                    getRuleFlowEventSupport().fireRuleFlowProcessStarted(
1392:                            processInstance, this );
1393:
1394:                    return processInstance;
1395:                } else {
1396:                    throw new IllegalArgumentException("Unknown process type: "
1397:                            + process.getClass());
1398:                }
1399:            }
1400:
1401:            public List iterateObjectsToList() {
1402:                List result = new ArrayList();
1403:                Iterator iterator = iterateObjects();
1404:                for (; iterator.hasNext();) {
1405:                    result.add(iterator.next());
1406:                }
1407:                return result;
1408:            }
1409:
1410:            public Entry[] getActivationParameters(long activationId) {
1411:                Activation[] activations = getAgenda().getActivations();
1412:                for (int i = 0; i < activations.length; i++) {
1413:                    if (activations[i].getActivationNumber() == activationId) {
1414:                        Map params = getActivationParameters(activations[i]);
1415:                        return (Entry[]) params.entrySet().toArray(
1416:                                new Entry[params.size()]);
1417:                    }
1418:                }
1419:                return new Entry[0];
1420:            }
1421:
1422:            /**
1423:             * Helper method 
1424:             */
1425:            public Map getActivationParameters(Activation activation) {
1426:                Map result = new HashMap();
1427:                Declaration[] declarations = activation.getRule()
1428:                        .getDeclarations();
1429:                for (int i = 0; i < declarations.length; i++) {
1430:                    FactHandle handle = activation.getTuple().get(
1431:                            declarations[i]);
1432:                    if (handle instanceof  InternalFactHandle) {
1433:                        result.put(declarations[i].getIdentifier(),
1434:                                declarations[i].getValue(this ,
1435:                                        ((InternalFactHandle) handle)
1436:                                                .getObject()));
1437:                    }
1438:                }
1439:                return result;
1440:            }
1441:
1442:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.