Source Code Cross Referenced for RuleTerminalNode.java in  » Rule-Engine » drolls-Rule-Engine » org » drools » reteoo » 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.reteoo 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package org.drools.reteoo;
002:
003:        /*
004:         * Copyright 2005 JBoss Inc
005:         * 
006:         * Licensed under the Apache License, Version 2.0 (the "License");
007:         * you may not use this file except in compliance with the License.
008:         * You may obtain a copy of the License at
009:         * 
010:         *      http://www.apache.org/licenses/LICENSE-2.0
011:         * 
012:         * Unless required by applicable law or agreed to in writing, software
013:         * distributed under the License is distributed on an "AS IS" BASIS,
014:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015:         * See the License for the specific language governing permissions and
016:         * limitations under the License.
017:         */
018:
019:        import java.io.Serializable;
020:
021:        import org.drools.common.EventSupport;
022:        import org.drools.RuleBaseConfiguration;
023:        import org.drools.common.BinaryHeapQueueAgendaGroup;
024:        import org.drools.common.AgendaItem;
025:        import org.drools.common.BaseNode;
026:        import org.drools.common.InternalAgenda;
027:        import org.drools.common.InternalAgendaGroup;
028:        import org.drools.common.InternalFactHandle;
029:        import org.drools.common.InternalRuleFlowGroup;
030:        import org.drools.common.InternalWorkingMemory;
031:        import org.drools.common.LogicalDependency;
032:        import org.drools.common.NodeMemory;
033:        import org.drools.common.PropagationContextImpl;
034:        import org.drools.common.ScheduledAgendaItem;
035:        import org.drools.rule.GroupElement;
036:        import org.drools.rule.Rule;
037:        import org.drools.spi.Activation;
038:        import org.drools.spi.ActivationGroup;
039:        import org.drools.spi.AgendaGroup;
040:        import org.drools.spi.Duration;
041:        import org.drools.spi.PropagationContext;
042:        import org.drools.spi.RuleFlowGroup;
043:        import org.drools.util.Iterator;
044:        import org.drools.util.LinkedList;
045:        import org.drools.util.TupleHashTable;
046:
047:        /**
048:         * Leaf Rete-OO node responsible for enacting <code>Action</code> s on a
049:         * matched <code>Rule</code>.
050:         * 
051:         * @see org.drools.rule.Rule
052:         * 
053:         * @author <a href="mailto:bob@eng.werken.com">bob mcwhirter </a>
054:         */
055:        public final class RuleTerminalNode extends BaseNode implements 
056:                TupleSinkNode, NodeMemory, TerminalNode {
057:            // ------------------------------------------------------------
058:            // Instance members
059:            // ------------------------------------------------------------
060:
061:            private int sequence;
062:
063:            /**
064:             * 
065:             */
066:            private static final long serialVersionUID = 400L;
067:            /** The rule to invoke upon match. */
068:            private final Rule rule;
069:            /** 
070:             * the subrule reference is needed to resolve declarations
071:             * because declarations may have different offsets in each subrule
072:             */
073:            private final GroupElement subrule;
074:            private final TupleSource tupleSource;
075:
076:            private TupleSinkNode previousTupleSinkNode;
077:            private TupleSinkNode nextTupleSinkNode;
078:
079:            // ------------------------------------------------------------
080:            // Constructors
081:            // ------------------------------------------------------------
082:
083:            /**
084:             * Construct.
085:             * 
086:             * @param inputSource
087:             *            The parent tuple source.
088:             * @param rule
089:             *            The rule.
090:             */
091:            public RuleTerminalNode(final int id, final TupleSource source,
092:                    final Rule rule, final GroupElement subrule) {
093:                super (id);
094:                this .rule = rule;
095:                this .tupleSource = source;
096:                this .subrule = subrule;
097:            }
098:
099:            // ------------------------------------------------------------
100:            // Instance methods
101:            // ------------------------------------------------------------
102:
103:            /**
104:             * Retrieve the <code>Action</code> associated with this node.
105:             * 
106:             * @return The <code>Action</code> associated with this node.
107:             */
108:            public Rule getRule() {
109:                return this .rule;
110:            }
111:
112:            public void setSequence(int seq) {
113:                this .sequence = seq;
114:            }
115:
116:            public int getSequence() {
117:                return this .sequence;
118:            }
119:
120:            // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
121:            // org.drools.impl.TupleSink
122:            // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
123:
124:            public void assertTuple(final ReteTuple tuple,
125:                    final PropagationContext context,
126:                    final InternalWorkingMemory workingMemory) {
127:                assertTuple(tuple, context, workingMemory, true);
128:
129:            }
130:
131:            /**
132:             * Assert a new <code>Tuple</code>.
133:             * 
134:             * @param tuple
135:             *            The <code>Tuple</code> being asserted.
136:             * @param workingMemory
137:             *            The working memory seesion.
138:             * @throws AssertionException
139:             *             If an error occurs while asserting.
140:             */
141:            public void assertTuple(final ReteTuple tuple,
142:                    final PropagationContext context,
143:                    final InternalWorkingMemory workingMemory,
144:                    final boolean fireActivationCreated) {
145:
146:                //check if the rule is effective
147:                if (!this .rule.isEffective()) {
148:                    return;
149:                }
150:
151:                // if the current Rule is no-loop and the origin rule is the same and its the same set of facts (tuple) then return
152:                if (context.getType() == PropagationContext.MODIFICATION) {
153:                    if (this .rule.isNoLoop()
154:                            && this .rule.equals(context.getRuleOrigin())
155:                            && context.getActivationOrigin().getTuple().equals(
156:                                    tuple)) {
157:                        return;
158:                    }
159:                } else if (this .rule.isNoLoop()
160:                        && this .rule.equals(context.getRuleOrigin())) {
161:                    return;
162:                }
163:
164:                //we only have to clone the head fact to make sure the graph is not affected during consequence reads after a modify
165:                final ReteTuple cloned = new ReteTuple(tuple);
166:
167:                final InternalAgenda agenda = (InternalAgenda) workingMemory
168:                        .getAgenda();
169:
170:                final Duration dur = this .rule.getDuration();
171:
172:                if (dur != null && dur.getDuration(tuple) > 0) {
173:                    final ScheduledAgendaItem item = new ScheduledAgendaItem(
174:                            context.getPropagationNumber(), cloned, agenda,
175:                            context, this .rule, this .subrule);
176:                    final TerminalNodeMemory memory = (TerminalNodeMemory) workingMemory
177:                            .getNodeMemory(this );
178:                    if (this .rule.getActivationGroup() != null) {
179:                        // Lazy cache activationGroup
180:                        if (memory.getActivationGroup() == null) {
181:                            memory.setActivationGroup(workingMemory.getAgenda()
182:                                    .getActivationGroup(
183:                                            this .rule.getActivationGroup()));
184:                        }
185:                        memory.getActivationGroup().addActivation(item);
186:                    }
187:
188:                    agenda.scheduleItem(item);
189:                    tuple.setActivation(item);
190:
191:                    if (!workingMemory.isSequential()) {
192:                        memory.getTupleMemory().add(tuple);
193:                    }
194:
195:                    item.setActivated(true);
196:                    ((EventSupport) workingMemory).getAgendaEventSupport()
197:                            .fireActivationCreated(item, workingMemory);
198:                } else {
199:                    // -----------------
200:                    // Lazy instantiation and addition to the Agenda of AgendGroup
201:                    // implementations
202:                    // ----------------
203:                    final TerminalNodeMemory memory = (TerminalNodeMemory) workingMemory
204:                            .getNodeMemory(this );
205:                    InternalAgendaGroup agendaGroup = memory.getAgendaGroup();
206:                    if (agendaGroup == null) {
207:                        // @todo: this logic really should be encapsulated inside the Agenda
208:                        if (this .rule.getAgendaGroup() == null
209:                                || this .rule.getAgendaGroup().equals("")
210:                                || this .rule.getAgendaGroup().equals(
211:                                        AgendaGroup.MAIN)) {
212:                            // Is the Rule AgendaGroup undefined? If it is use MAIN,
213:                            // which is added to the Agenda by default
214:                            agendaGroup = (InternalAgendaGroup) agenda
215:                                    .getAgendaGroup(AgendaGroup.MAIN);
216:                        } else {
217:                            // AgendaGroup is defined, so try and get the AgendaGroup
218:                            // from the Agenda
219:                            agendaGroup = (InternalAgendaGroup) agenda
220:                                    .getAgendaGroup(this .rule.getAgendaGroup());
221:                        }
222:
223:                        memory.setAgendaGroup(agendaGroup);
224:                    }
225:
226:                    // set the focus if rule autoFocus is true
227:                    if (this .rule.getAutoFocus()) {
228:                        agenda.setFocus(agendaGroup);
229:                    }
230:
231:                    final AgendaItem item = new AgendaItem(context
232:                            .getPropagationNumber(), cloned, rule.getSalience()
233:                            .getValue(tuple, workingMemory), context,
234:                            this .rule, this .subrule);
235:
236:                    if (workingMemory.isSequential()) {
237:                        item.setSequenence(this .sequence);
238:                    }
239:
240:                    if (this .rule.getActivationGroup() != null) {
241:                        // Lazy cache activationGroup
242:                        if (memory.getActivationGroup() == null) {
243:                            memory.setActivationGroup(workingMemory.getAgenda()
244:                                    .getActivationGroup(
245:                                            this .rule.getActivationGroup()));
246:                        }
247:                        memory.getActivationGroup().addActivation(item);
248:                    }
249:
250:                    item.setAgendaGroup(agendaGroup);
251:                    if (this .rule.getRuleFlowGroup() == null) {
252:                        // No RuleFlowNode so add  it directly to  the Agenda
253:
254:                        // do not add the activation if the rule is "lock-on-active" and the AgendaGroup is active
255:                        // we must check the context to determine if its a new tuple or an exist re-activated tuple as part of the retract                
256:                        if (context.getType() == PropagationContext.MODIFICATION) {
257:                            if (this .rule.isLockOnActive()
258:                                    && agendaGroup.isActive()) {
259:                                Activation justifier = context
260:                                        .removeRetractedTuple(this .rule, tuple);
261:                                if (justifier == null) {
262:                                    // This rule is locked and active, do not allow new tuples to activate 
263:                                    return;
264:                                } else if (this .rule.hasLogicalDependency()) {
265:                                    copyLogicalDependencies(context,
266:                                            workingMemory, item, justifier);
267:                                }
268:                            } else if (this .rule.hasLogicalDependency()) {
269:                                Activation justifier = context
270:                                        .removeRetractedTuple(this .rule, tuple);
271:                                copyLogicalDependencies(context, workingMemory,
272:                                        item, justifier);
273:                            }
274:                        } else if (this .rule.isLockOnActive()
275:                                && agendaGroup.isActive()) {
276:                            return;
277:                        }
278:
279:                        agendaGroup.add(item);
280:                    } else {
281:                        //There is  a RuleFlowNode so add it there, instead  of the Agenda
282:                        RuleFlowGroup rfg = memory.getRuleFlowGroup();
283:                        // Lazy cache ruleFlowGroup
284:                        if (rfg == null) {
285:                            rfg = workingMemory.getAgenda().getRuleFlowGroup(
286:                                    this .rule.getRuleFlowGroup());
287:                            memory.setRuleFlowGroup(rfg);
288:                        }
289:
290:                        // do not add the activation if the rule is "lock-on-active" and the RuleFlowGroup is active
291:                        // we must check the context to determine if its a new tuple or an exist re-activated tuple as part of the retract                
292:                        if (context.getType() == PropagationContext.MODIFICATION) {
293:                            if (this .rule.isLockOnActive() && rfg.isActive()) {
294:                                Activation justifier = context
295:                                        .removeRetractedTuple(this .rule, tuple);
296:                                if (justifier == null) {
297:                                    // This rule is locked and active, do not allow new tuples to activate 
298:                                    return;
299:                                } else if (this .rule.hasLogicalDependency()) {
300:                                    copyLogicalDependencies(context,
301:                                            workingMemory, item, justifier);
302:                                }
303:                            } else if (this .rule.hasLogicalDependency()) {
304:                                Activation justifier = context
305:                                        .removeRetractedTuple(this .rule, tuple);
306:                                copyLogicalDependencies(context, workingMemory,
307:                                        item, justifier);
308:                            }
309:                        } else if (this .rule.isLockOnActive() && rfg.isActive()) {
310:                            return;
311:                        }
312:
313:                        ((InternalRuleFlowGroup) memory.getRuleFlowGroup())
314:                                .addActivation(item);
315:
316:                    }
317:
318:                    tuple.setActivation(item);
319:                    memory.getTupleMemory().add(tuple);
320:
321:                    item.setActivated(true);
322:
323:                    // We only want to fire an event on a truly new Activation and not on an Activation as a result of a modify
324:                    if (fireActivationCreated) {
325:                        ((EventSupport) workingMemory).getAgendaEventSupport()
326:                                .fireActivationCreated(item, workingMemory);
327:                    }
328:                }
329:
330:                agenda.increaseActiveActivations();
331:            }
332:
333:            private void copyLogicalDependencies(
334:                    final PropagationContext context,
335:                    final InternalWorkingMemory workingMemory,
336:                    final AgendaItem item, Activation justifier) {
337:                if (justifier != null) {
338:                    final LinkedList list = justifier.getLogicalDependencies();
339:                    if (list != null && !list.isEmpty()) {
340:                        for (LogicalDependency node = (LogicalDependency) list
341:                                .getFirst(); node != null; node = (LogicalDependency) node
342:                                .getNext()) {
343:                            final InternalFactHandle handle = (InternalFactHandle) node
344:                                    .getFactHandle();
345:                            workingMemory.getTruthMaintenanceSystem()
346:                                    .addLogicalDependency(handle, item,
347:                                            context, this .rule);
348:                        }
349:                    }
350:                }
351:            }
352:
353:            public void retractTuple(final ReteTuple leftTuple,
354:                    final PropagationContext context,
355:                    final InternalWorkingMemory workingMemory) {
356:                final TerminalNodeMemory memory = (TerminalNodeMemory) workingMemory
357:                        .getNodeMemory(this );
358:                final ReteTuple tuple = memory.getTupleMemory().remove(
359:                        leftTuple);
360:                if (tuple == null) {
361:                    // tuple should only be null if it was asserted and reached a no-loop causing it to exit early
362:                    // before being added to the node memory and an activation created and attached
363:                    return;
364:                }
365:
366:                final Activation activation = tuple.getActivation();
367:                if (activation.getLogicalDependencies() != null
368:                        && !activation.getLogicalDependencies().isEmpty()) {
369:                    context.addRetractedTuple(this .rule, activation);
370:                }
371:
372:                if (activation.isActivated()) {
373:                    if (context.getType() == PropagationContext.MODIFICATION) {
374:                        // during a modify if we have either isLockOnActive or the activation has logical dependencies
375:                        // then we need to track retractions, so we know which are exising activations and which are truly new
376:                        if (this .rule.isLockOnActive()) {
377:                            context.addRetractedTuple(this .rule, activation);
378:                        }
379:                    }
380:
381:                    activation.remove();
382:
383:                    if (activation.getActivationGroupNode() != null) {
384:                        activation.getActivationGroupNode()
385:                                .getActivationGroup().removeActivation(
386:                                        activation);
387:                    }
388:
389:                    if (activation.getRuleFlowGroupNode() != null) {
390:                        final InternalRuleFlowGroup ruleFlowGroup = activation
391:                                .getRuleFlowGroupNode().getRuleFlowGroup();
392:                        ruleFlowGroup.removeActivation(activation);
393:                    }
394:
395:                    ((EventSupport) workingMemory).getAgendaEventSupport()
396:                            .fireActivationCancelled(activation, workingMemory);
397:                    ((InternalAgenda) workingMemory.getAgenda())
398:                            .decreaseActiveActivations();
399:                } else {
400:                    ((InternalAgenda) workingMemory.getAgenda())
401:                            .decreaseDormantActivations();
402:                }
403:
404:                workingMemory.removeLogicalDependencies(activation, context,
405:                        this .rule);
406:            }
407:
408:            public String toString() {
409:                return "[RuleTerminalNode: rule=" + this .rule.getName() + "]";
410:            }
411:
412:            public void ruleAttached() {
413:                // TODO Auto-generated method stub
414:
415:            }
416:
417:            public void attach() {
418:                this .tupleSource.addTupleSink(this );
419:            }
420:
421:            public void attach(final InternalWorkingMemory[] workingMemories) {
422:                attach();
423:
424:                for (int i = 0, length = workingMemories.length; i < length; i++) {
425:                    final InternalWorkingMemory workingMemory = workingMemories[i];
426:                    final PropagationContext propagationContext = new PropagationContextImpl(
427:                            workingMemory.getNextPropagationIdCounter(),
428:                            PropagationContext.RULE_ADDITION, null, null);
429:                    this .tupleSource.updateSink(this , propagationContext,
430:                            workingMemory);
431:                }
432:            }
433:
434:            public void remove(final BaseNode node,
435:                    final InternalWorkingMemory[] workingMemories) {
436:                for (int i = 0, length = workingMemories.length; i < length; i++) {
437:                    final InternalWorkingMemory workingMemory = workingMemories[i];
438:
439:                    final TerminalNodeMemory memory = (TerminalNodeMemory) workingMemory
440:                            .getNodeMemory(this );
441:                    final Iterator it = memory.getTupleMemory().iterator();
442:                    for (ReteTuple tuple = (ReteTuple) it.next(); tuple != null; tuple = (ReteTuple) it
443:                            .next()) {
444:                        final Activation activation = tuple.getActivation();
445:
446:                        if (activation.isActivated()) {
447:                            activation.remove();
448:                            ((EventSupport) workingMemory)
449:                                    .getAgendaEventSupport()
450:                                    .fireActivationCancelled(activation,
451:                                            workingMemory);
452:                        }
453:
454:                        final PropagationContext propagationContext = new PropagationContextImpl(
455:                                workingMemory.getNextPropagationIdCounter(),
456:                                PropagationContext.RULE_REMOVAL, null, null);
457:                        workingMemory.getTruthMaintenanceSystem()
458:                                .removeLogicalDependencies(activation,
459:                                        propagationContext, this .rule);
460:                    }
461:
462:                    workingMemory.executeQueuedActions();
463:                    workingMemory.clearNodeMemory(this );
464:                }
465:
466:                removeShare();
467:
468:                this .tupleSource.remove(this , workingMemories);
469:            }
470:
471:            public Object createMemory(final RuleBaseConfiguration config) {
472:                return new TerminalNodeMemory();
473:            }
474:
475:            /**
476:             * Returns the next node
477:             * @return
478:             *      The next TupleSinkNode
479:             */
480:            public TupleSinkNode getNextTupleSinkNode() {
481:                return this .nextTupleSinkNode;
482:            }
483:
484:            /**
485:             * Sets the next node 
486:             * @param next
487:             *      The next TupleSinkNode
488:             */
489:            public void setNextTupleSinkNode(final TupleSinkNode next) {
490:                this .nextTupleSinkNode = next;
491:            }
492:
493:            /**
494:             * Returns the previous node
495:             * @return
496:             *      The previous TupleSinkNode
497:             */
498:            public TupleSinkNode getPreviousTupleSinkNode() {
499:                return this .previousTupleSinkNode;
500:            }
501:
502:            /**
503:             * Sets the previous node 
504:             * @param previous
505:             *      The previous TupleSinkNode
506:             */
507:            public void setPreviousTupleSinkNode(final TupleSinkNode previous) {
508:                this .previousTupleSinkNode = previous;
509:            }
510:
511:            public int hashCode() {
512:                return this .rule.hashCode();
513:            }
514:
515:            public boolean equals(final Object object) {
516:                if (object == this ) {
517:                    return true;
518:                }
519:
520:                if (object == null || !(object instanceof  RuleTerminalNode)) {
521:                    return false;
522:                }
523:
524:                final RuleTerminalNode other = (RuleTerminalNode) object;
525:                return this .rule.equals(other.rule);
526:            }
527:
528:            class TerminalNodeMemory implements  Serializable {
529:                private static final long serialVersionUID = 400L;
530:
531:                private InternalAgendaGroup agendaGroup;
532:
533:                private ActivationGroup activationGroup;
534:
535:                private RuleFlowGroup ruleFlowGroup;
536:
537:                private TupleHashTable tupleMemory;
538:
539:                public TerminalNodeMemory() {
540:                    this .tupleMemory = new TupleHashTable();
541:                }
542:
543:                public InternalAgendaGroup getAgendaGroup() {
544:                    return this .agendaGroup;
545:                }
546:
547:                public void setAgendaGroup(final InternalAgendaGroup agendaGroup) {
548:                    this .agendaGroup = agendaGroup;
549:                }
550:
551:                public ActivationGroup getActivationGroup() {
552:                    return this .activationGroup;
553:                }
554:
555:                public void setActivationGroup(
556:                        final ActivationGroup activationGroup) {
557:                    this .activationGroup = activationGroup;
558:                }
559:
560:                public TupleHashTable getTupleMemory() {
561:                    return this .tupleMemory;
562:                }
563:
564:                public RuleFlowGroup getRuleFlowGroup() {
565:                    return this .ruleFlowGroup;
566:                }
567:
568:                public void setRuleFlowGroup(final RuleFlowGroup ruleFlowGroup) {
569:                    this.ruleFlowGroup = ruleFlowGroup;
570:                }
571:            }
572:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.