001: package biz.hammurapi.rules.jsr94;
002:
003: import java.util.ArrayList;
004: import java.util.Iterator;
005: import java.util.List;
006:
007: import javax.rules.Handle;
008: import javax.rules.InvalidRuleSessionException;
009: import javax.rules.ObjectFilter;
010: import javax.rules.RuleExecutionSetMetadata;
011: import javax.rules.RuleRuntime;
012: import javax.rules.RuleSessionCreateException;
013: import javax.rules.RuleSessionTypeUnsupportedException;
014: import javax.rules.StatefulRuleSession;
015: import javax.rules.StatelessRuleSession;
016:
017: import biz.hammurapi.config.Component;
018: import biz.hammurapi.config.ConfigurationException;
019: import biz.hammurapi.config.Context;
020: import biz.hammurapi.rules.CollectionManager;
021: import biz.hammurapi.rules.HandleManager;
022: import biz.hammurapi.rules.KnowledgeBase;
023: import biz.hammurapi.rules.KnowledgeCompactor;
024:
025: /**
026: * Rule session, a facade to internal components.
027: * @author Pavel Vlasov
028: * @revision $Revision$
029: */
030: class RuleSession implements StatefulRuleSession, StatelessRuleSession {
031:
032: /**
033: *
034: */
035: private static final long serialVersionUID = 5619441714641338077L;
036:
037: private HandleManager handleManager;
038: private KnowledgeBase knowledgeBase;
039: private CollectionManager collectionManager;
040: private ObjectFilter objectFilter;
041: private int sessionType;
042: private RuleExecutionSetMetadata metadata;
043: private Component container;
044:
045: private KnowledgeCompactor knowledgeCompactor;
046:
047: /**
048: * Wraps container into a session.
049: * Container shall contain at least the following entries:
050: * <code>/handle-manager</code> of type <code>HandleManager</code>,
051: * <code>/collection-manager</code> of type <code>CollectionManager</code>,
052: * <code>/rules</code> with <code>rule</code> subelements,
053: * <code>/name</code> (String),
054: * <code>/description</code> (String).
055: * @throws ConfigurationException
056: * @throws RuleSessionTypeUnsupportedException
057: */
058: public RuleSession(Context container, int sessionType, String uri)
059: throws RuleSessionCreateException,
060: RuleSessionTypeUnsupportedException {
061:
062: if (sessionType == RuleRuntime.STATEFUL_SESSION_TYPE
063: || sessionType == RuleRuntime.STATELESS_SESSION_TYPE) {
064: this .sessionType = sessionType;
065: } else {
066: throw new RuleSessionTypeUnsupportedException(
067: "Invalid session type: " + sessionType);
068: }
069:
070: handleManager = (HandleManager) container
071: .get("/handle-manager");
072: if (handleManager == null) {
073: throw new RuleSessionCreateException(
074: "Handle manager not found");
075: }
076:
077: objectFilter = (ObjectFilter) container.get("/object-filter");
078:
079: collectionManager = (CollectionManager) container
080: .get("/collection-manager");
081: if (collectionManager == null) {
082: throw new RuleSessionCreateException(
083: "Collection manager not found");
084: }
085:
086: knowledgeBase = (KnowledgeBase) container.get("/rules");
087: if (knowledgeBase == null) {
088: throw new RuleSessionCreateException(
089: "/rules element not found");
090: }
091:
092: knowledgeCompactor = (KnowledgeCompactor) container
093: .get("/knowledge-compactor");
094:
095: metadata = new biz.hammurapi.rules.jsr94.RuleExecutionSetMetadata(
096: uri, (String) container.get("/name"),
097: (String) container.get("/description"));
098:
099: if (container instanceof Component) {
100: this .container = (Component) container;
101: try {
102: this .container.start();
103: } catch (ConfigurationException e) {
104: throw new RuleSessionCreateException(
105: "Could not start container: " + e, e);
106: }
107: }
108: }
109:
110: /**
111: * This call is delegated to <code>handleManager</code>
112: */
113: public boolean containsObject(Handle handle) {
114: return handleManager.contains(handle);
115: }
116:
117: /**
118: * Adds object to handle manager and to knowledge base.
119: */
120: public Handle addObject(Object obj) {
121: Handle ret = handleManager.addObject(obj);
122: knowledgeBase.add(obj);
123: return ret;
124: }
125:
126: /**
127: * Invokes addObject() for each member of the list and returns collection of handles.
128: */
129: public List addObjects(List objs) {
130: List ret = new ArrayList();
131: Iterator it = objs.iterator();
132: while (it.hasNext()) {
133: ret.add(addObject(it.next()));
134: }
135: return ret;
136: }
137:
138: /**
139: * Invokes knowledge base's remove() for the old object, add() for the new object
140: * and rebinds the handle to the new object.
141: */
142: public void updateObject(Handle handle, Object obj) {
143: knowledgeBase.remove(handleManager.getObject(handle));
144: knowledgeBase.add(obj);
145: handleManager.rebind(handle, obj);
146: }
147:
148: /**
149: * Removes object from knowledge base. Knowledge base is
150: * responsible for removal of the object from the handle manager.
151: */
152: public void removeObject(Handle handle) {
153: knowledgeBase.remove(handleManager.getObject(handle));
154: }
155:
156: /**
157: * @return List of objects filtered by default object filter.
158: */
159: public List getObjects() {
160: return getObjects(objectFilter);
161: }
162:
163: /**
164: * @return List of handles.
165: */
166: public List getHandles() {
167: return new ArrayList(handleManager.getHandles());
168: }
169:
170: /**
171: * @return List of objects filtered by the <code>filter</code>
172: * @param Object filter, can be null.
173: */
174: public List getObjects(ObjectFilter filter) {
175: List ret = new ArrayList();
176:
177: Iterator hit = getHandles().iterator();
178: while (hit.hasNext()) {
179: Object obj = getObject((Handle) hit.next());
180: if (filter == null) {
181: ret.add(obj);
182: } else {
183: obj = filter.filter(obj);
184: if (obj != null) {
185: ret.add(obj);
186: }
187: }
188: }
189:
190: return knowledgeCompactor == null ? ret : knowledgeCompactor
191: .compact(ret);
192: }
193:
194: /**
195: * Delegates to knowledgeBase.executeRules(). Normally rules are executed automatically when objects
196: * are added or updated. Invocation of this method may be required in multithreaded inference scenario to make sure that
197: * all threads finished inference process.
198: */
199: public void executeRules() {
200: knowledgeBase.executeRules();
201: }
202:
203: /**
204: * Clears collection manager, handle manager and resets object filter.
205: */
206: public void reset() {
207: executeRules(); // Make sure that object queue is empty.
208: collectionManager.clear();
209: handleManager.clear();
210: if (objectFilter != null) {
211: objectFilter.reset();
212: }
213: knowledgeBase.reset();
214: }
215:
216: /**
217: * Returns object by handle.
218: */
219: public Object getObject(Handle handle) {
220: return handleManager.getObject(handle);
221: }
222:
223: /**
224: * Returns execution set metadata.
225: */
226: public RuleExecutionSetMetadata getRuleExecutionSetMetadata() {
227: return metadata;
228: }
229:
230: /**
231: * Stops container.
232: */
233: public void release() throws InvalidRuleSessionException {
234: if (container != null) {
235: try {
236: container.stop();
237: } catch (ConfigurationException e) {
238: throw new InvalidRuleSessionException(
239: "Could not stop container", e);
240: }
241: }
242: }
243:
244: /**
245: * Returns session type.
246: */
247: public int getType() {
248: return sessionType;
249: }
250:
251: // --- Stateless rule session methods ---
252:
253: /**
254: * Calls executeRules(object, null)
255: */
256: public List executeRules(List objects) {
257: return executeRules(objects, null);
258: }
259:
260: /**
261: * This method is a wrapper around stateful method.
262: * It adds all objects to the session, executes rules,
263: * returns objects and finally resets the session.
264: */
265: public List executeRules(List objects, ObjectFilter objectFilter) {
266: try {
267: Iterator it = objects.iterator();
268: while (it.hasNext()) {
269: addObject(it.next());
270: }
271: executeRules();
272: return getObjects(objectFilter);
273: } finally {
274: reset();
275: }
276: }
277: }
|