Source Code Cross Referenced for QueueingRulesContainer.java in  » Rule-Engine » hammurapi-rules » biz » hammurapi » rules » 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 » hammurapi rules » biz.hammurapi.rules 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * hammurapi-rules @mesopotamia.version@
003:         * Hammurapi rules engine. 
004:         * Copyright (C) 2005  Hammurapi Group
005:         *
006:         * This program is free software; you can redistribute it and/or
007:         * modify it under the terms of the GNU Lesser General Public
008:         * License as published by the Free Software Foundation; either
009:         * version 2 of the License, or (at your option) any later version.
010:         *
011:         * This program is distributed in the hope that it will be useful,
012:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014:         * Lesser General Public License for more details.
015:         *
016:         * You should have received a copy of the GNU Lesser General Public
017:         * License along with this library; if not, write to the Free Software
018:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
019:         *
020:         * URL: http://http://www.hammurapi.biz
021:         * e-Mail: support@hammurapi.biz
022:         */
023:        package biz.hammurapi.rules;
024:
025:        import java.lang.ref.Reference;
026:        import java.lang.ref.WeakReference;
027:        import java.lang.reflect.Constructor;
028:        import java.lang.reflect.InvocationTargetException;
029:        import java.util.ArrayList;
030:        import java.util.Collection;
031:        import java.util.Iterator;
032:        import java.util.Map;
033:        import java.util.WeakHashMap;
034:
035:        import org.w3c.dom.Element;
036:        import org.w3c.dom.Node;
037:
038:        import biz.hammurapi.config.ConfigurationException;
039:        import biz.hammurapi.config.Context;
040:        import biz.hammurapi.dispatch.DispatchException;
041:        import biz.hammurapi.dispatch.QueuingDispatcher;
042:        import biz.hammurapi.util.Worker;
043:
044:        /**
045:         * This rules container uses QueuingDispatcher and negation semantics for remove().
046:         * It can also leverage worker (thread pool) provided in <code>worker-ref</code> attribute
047:         * for multithreaded inference.
048:         * This container also uses loop detection. 
049:         * @author Pavel Vlasov
050:         * @revision $Revision$
051:         */
052:        public class QueueingRulesContainer extends RulesContainerBase {
053:
054:            private FactDispatcher dispatcher;
055:            private FactDispatcher removeDispatcher;
056:            private CollectionManager collectionManager;
057:            private HandleManager handleManager;
058:            private boolean doTracing;
059:
060:            public QueueingRulesContainer() {
061:                super ();
062:                doTracing = this  instanceof  ActionTracer;
063:            }
064:
065:            /**
066:             * Adds object to handle manager and dispatches to rules.
067:             * If the object is instance of Negator the it is presented to collection manager.
068:             */
069:            public void add(Object obj) {
070:                // Remove negators negated by this and then don't dispatch this if it is 
071:                // negated.
072:                if (negators != null) {
073:                    synchronized (negators) {
074:                        // Remove negators negated by obj.
075:                        if (obj instanceof  Negator) {
076:                            Iterator it = negators.iterator();
077:                            while (it.hasNext()) {
078:                                if (Conclusion.object2Negator(it.next(),
079:                                        (Negator) obj)) {
080:                                    it.remove();
081:                                }
082:                            }
083:                        }
084:
085:                        // Do not dispatch object if it is negated
086:                        Iterator it = negators.iterator();
087:                        while (it.hasNext()) {
088:                            if (Conclusion.object2Negator(obj, (Negator) it
089:                                    .next())) {
090:                                return;
091:                            }
092:                        }
093:
094:                    }
095:                }
096:                dispatcher.dispatch(obj);
097:            }
098:
099:            /**
100:             * Consumes DispatchException.
101:             * This implementation just prints stack trace.
102:             * Override if needed.
103:             * @param exception
104:             */
105:            protected void onDispatchException(DispatchException exception) {
106:                exception.printStackTrace();
107:            }
108:
109:            private Map recentFacts = new WeakHashMap();
110:
111:            /**
112:             * Checks recent conclusions and derivation depth to discard conclusions which came through dispatching too many times
113:             * or conclusions with too big depth.  
114:             * @param object
115:             * @return true if there is no loop
116:             */
117:            protected boolean checkLoop(Object object) {
118:                if (object instanceof  Conclusion) {
119:                    Conclusion cb = (Conclusion) object;
120:
121:                    synchronized (recentFacts) {
122:                        Reference prevRef = (Reference) recentFacts.get(object);
123:                        Conclusion prev = prevRef == null ? null
124:                                : (Conclusion) prevRef.get();
125:
126:                        if (prev == null) {
127:                            recentFacts.put(object, new WeakReference(object));
128:                        } else {
129:                            /**
130:                             * If conclusion recently passed dispatching then it is discarded, but
131:                             * derivations are merged if new conclusion is not derived from existing equal conclusion.
132:                             * This statement prevents logical loops like Parent -> Child -> Parent
133:                             */
134:                            if (prev != cb && !cb.isDerivedFrom(prev)) {
135:                                cb.mergeDerivations(prev);
136:                            }
137:
138:                            return false;
139:                        }
140:                    }
141:
142:                    /**
143:                     * If depth of the conclusion in more than 3 times number of handlers then such conclusion is
144:                     * discarded because most probably there is a logical loop. 
145:                     */
146:                    if (cb.getDepth() > dispatcher.size() * 3) {
147:                        onDiscardedConclusion((Conclusion) object);
148:                        return false;
149:                    }
150:                }
151:
152:                return true;
153:            }
154:
155:            /**
156:             * Conclusions discarded because their derivation depth is too big are passed to this method.
157:             * The method does nothing. Override as needed.
158:             * @param conclusion
159:             */
160:            protected void onDiscardedConclusion(Conclusion conclusion) {
161:                // Nothing - override if needed.
162:            }
163:
164:            /**
165:             * Removes object from handle manager and recent facts. Then creates a negator, negates facts in collection manager and 
166:             * then dispatches the object to remove methods.
167:             * Subclasses implementing ActionTracing undo actions instead of using a negator.
168:             */
169:            public void remove(Object obj) {
170:                if (doTracing) {
171:                    Collection objectActions = getObjectActions(obj);
172:                    if (objectActions != null) {
173:                        Iterator it = objectActions.iterator();
174:                        while (it.hasNext()) {
175:                            ((Action) it.next()).undo();
176:                        }
177:                    }
178:                } else {
179:                    processNegator(newNegator(obj));
180:                }
181:                removeDispatcher.dispatch(obj);
182:            }
183:
184:            /**
185:             * Returns actions performed when object was added to the database.
186:             * This method must be overriden by subclasses which implement ActionTracer.
187:             * @param obj
188:             * @return
189:             */
190:            protected Collection getObjectActions(Object obj) {
191:                throw new UnsupportedOperationException(
192:                        "Subclasses which implement ActionTracer must override this method");
193:            }
194:
195:            /**
196:             * Instantiates new negator.
197:             * @param obj
198:             * @return
199:             */
200:            protected Negator newNegator(Object obj) {
201:                try {
202:                    return (Negator) (negatorConstructor == null ? new EqualityNegator(
203:                            obj)
204:                            : negatorConstructor
205:                                    .newInstance(new Object[] { obj }));
206:                } catch (InstantiationException e) {
207:                    throw new RuntimeException(
208:                            "Could not instantiate negator: " + e, e);
209:                } catch (IllegalAccessException e) {
210:                    throw new RuntimeException(
211:                            "Could not instantiate negator: " + e, e);
212:                } catch (InvocationTargetException e) {
213:                    throw new RuntimeException(
214:                            "Could not instantiate negator: " + e, e);
215:                }
216:            }
217:
218:            private void processNegator(Negator negator) {
219:                // Remove from negators
220:                if (negators != null) {
221:                    synchronized (negators) {
222:                        Iterator it = negators.iterator();
223:                        while (it.hasNext()) {
224:                            if (Conclusion.object2Negator(it.next(), negator)) {
225:                                it.remove();
226:                            }
227:                        }
228:                    }
229:                }
230:
231:                synchronized (recentFacts) {
232:                    Iterator it = recentFacts.keySet().iterator();
233:                    while (it.hasNext()) {
234:                        if (Conclusion.object2Negator(it.next(), negator)) {
235:                            it.remove();
236:                        }
237:                    }
238:                }
239:                handleManager.isNegatedBy(negator);
240:                collectionManager.isNegatedBy(negator);
241:                dispatcher.isNegatedBy(negator);
242:                removeDispatcher.isNegatedBy(negator);
243:            }
244:
245:            /**
246:             * Invokes dispatcher's join() to wait until all 
247:             * jobs are finished.
248:             */
249:            public void executeRules() {
250:                try {
251:                    dispatcher.join();
252:                    removeDispatcher.join();
253:                } catch (InterruptedException e) {
254:                    throw new RulesRuntimeException("Wait interrupted: " + e, e);
255:                }
256:            }
257:
258:            private String workerRef;
259:
260:            /**
261:             * If this it true then negators posted to the bus are put to a collection and all new facts are checked
262:             * against negators before being posted.
263:             */
264:            private Collection negators;
265:
266:            private Constructor negatorConstructor;
267:
268:            public void configure(Node configNode, Context context)
269:                    throws ConfigurationException {
270:                super .configure(configNode, context);
271:                Element ce = (Element) configNode;
272:                if (ce.hasAttribute("worker-ref")) {
273:                    workerRef = ce.getAttribute("worker-ref");
274:                }
275:
276:                if (ce.hasAttribute("retain-negators")
277:                        && "yes".equals(ce.getAttribute("retain-negators"))) {
278:                    negators = new ArrayList();
279:                }
280:
281:                if (ce.hasAttribute("negator-class")) {
282:                    try {
283:                        Class negatorClass = Class.forName(ce
284:                                .getAttribute("negator-class"));
285:                        negatorConstructor = negatorClass
286:                                .getConstructor(new Class[] { Object.class });
287:                    } catch (ClassNotFoundException e) {
288:                        throw new ConfigurationException(
289:                                "Negator class not found: " + e, e);
290:                    } catch (SecurityException e) {
291:                        throw new ConfigurationException(
292:                                "Cannot access negator constructor: " + e, e);
293:                    } catch (NoSuchMethodException e) {
294:                        throw new ConfigurationException(
295:                                "Negator constructor not found: " + e, e);
296:                    }
297:                }
298:            }
299:
300:            private class FactDispatcher extends QueuingDispatcher implements 
301:                    Negatable {
302:
303:                /**
304:                 * @param targets
305:                 * @param worker
306:                 */
307:                public FactDispatcher(Collection targets, Worker worker) {
308:                    super (targets, worker);
309:                }
310:
311:                /**
312:                 * Removes negated object from queue
313:                 */
314:                public boolean isNegatedBy(Negator negator) {
315:                    synchronized (queue) {
316:                        Iterator it = queue.iterator();
317:                        while (it.hasNext()) {
318:                            Object job = it.next();
319:                            if (job instanceof  DispatchJob
320:                                    && Conclusion.object2Negator(
321:                                            ((DispatchJob) job).getPayload(),
322:                                            negator)) {
323:                                it.remove();
324:                                ((DispatchJob) job).done();
325:                            }
326:                        }
327:                    }
328:                    return false;
329:                }
330:
331:            }
332:
333:            public void start() throws ConfigurationException {
334:                super .start();
335:                collectionManager = (CollectionManager) get("/collection-manager");
336:                handleManager = (HandleManager) get("/handle-manager");
337:                Worker worker = (Worker) (workerRef == null ? null
338:                        : get(workerRef));
339:
340:                dispatcher = new FactDispatcher(getComponents(), worker) {
341:
342:                    public void dispatch(final Object obj) {
343:                        if (obj instanceof  DispatchException) {
344:                            onDispatchException((DispatchException) obj);
345:                        } else if (checkLoop(obj)) {
346:                            // Negate collections if negator
347:                            if (obj instanceof  Negator) {
348:                                // Post negation job to queue. 
349:                                postJobToQueue(new Runnable() {
350:
351:                                    public void run() {
352:                                        processNegator((Negator) obj);
353:                                    }
354:
355:                                });
356:                            }
357:
358:                            // Add only public facts to the handle manager.
359:                            if (!(obj instanceof  Fact && ((Fact) obj)
360:                                    .isPrivate())) {
361:                                handleManager.addObject(obj);
362:                            }
363:                            super .dispatch(obj);
364:                        }
365:                    }
366:                };
367:                Collection removeHandlers = new ArrayList();
368:                Iterator it = getComponents().iterator();
369:                while (it.hasNext()) {
370:                    AbstractRule rule = (AbstractRule) it.next();
371:                    removeHandlers.addAll(rule.getRemoveHandlers());
372:                }
373:
374:                removeDispatcher = new FactDispatcher(removeHandlers, worker);
375:            }
376:
377:            public void stop() throws ConfigurationException {
378:                try {
379:                    dispatcher.stop();
380:                } catch (InterruptedException e) {
381:                    throw new ConfigurationException(
382:                            "Could not stop dispatcher: " + e, e);
383:                }
384:                try {
385:                    removeDispatcher.stop();
386:                } catch (InterruptedException e) {
387:                    throw new ConfigurationException(
388:                            "Could not stop remove dispatcher: " + e, e);
389:                }
390:                super .stop();
391:            }
392:
393:            public void reset() {
394:                Iterator it = getComponents().iterator();
395:                while (it.hasNext()) {
396:                    ((AbstractRule) it.next()).reset();
397:                }
398:            }
399:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.