package biz.hammurapi.rules.jsr94;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.rules.Handle;
import javax.rules.InvalidRuleSessionException;
import javax.rules.ObjectFilter;
import javax.rules.RuleExecutionSetMetadata;
import javax.rules.RuleRuntime;
import javax.rules.RuleSessionCreateException;
import javax.rules.RuleSessionTypeUnsupportedException;
import javax.rules.StatefulRuleSession;
import javax.rules.StatelessRuleSession;
import biz.hammurapi.config.Component;
import biz.hammurapi.config.ConfigurationException;
import biz.hammurapi.config.Context;
import biz.hammurapi.rules.CollectionManager;
import biz.hammurapi.rules.HandleManager;
import biz.hammurapi.rules.KnowledgeBase;
import biz.hammurapi.rules.KnowledgeCompactor;
/**
* Rule session, a facade to internal components.
* @author Pavel Vlasov
* @revision $Revision$
*/
class RuleSession implements StatefulRuleSession, StatelessRuleSession {
/**
*
*/
private static final long serialVersionUID = 5619441714641338077L;
private HandleManager handleManager;
private KnowledgeBase knowledgeBase;
private CollectionManager collectionManager;
private ObjectFilter objectFilter;
private int sessionType;
private RuleExecutionSetMetadata metadata;
private Component container;
private KnowledgeCompactor knowledgeCompactor;
/**
* Wraps container into a session.
* Container shall contain at least the following entries:
* <code>/handle-manager</code> of type <code>HandleManager</code>,
* <code>/collection-manager</code> of type <code>CollectionManager</code>,
* <code>/rules</code> with <code>rule</code> subelements,
* <code>/name</code> (String),
* <code>/description</code> (String).
* @throws ConfigurationException
* @throws RuleSessionTypeUnsupportedException
*/
public RuleSession(Context container, int sessionType, String uri) throws RuleSessionCreateException, RuleSessionTypeUnsupportedException {
if (sessionType==RuleRuntime.STATEFUL_SESSION_TYPE || sessionType==RuleRuntime.STATELESS_SESSION_TYPE) {
this.sessionType=sessionType;
} else {
throw new RuleSessionTypeUnsupportedException("Invalid session type: "+sessionType);
}
handleManager=(HandleManager) container.get("/handle-manager");
if (handleManager==null) {
throw new RuleSessionCreateException("Handle manager not found");
}
objectFilter=(ObjectFilter) container.get("/object-filter");
collectionManager=(CollectionManager) container.get("/collection-manager");
if (collectionManager==null) {
throw new RuleSessionCreateException("Collection manager not found");
}
knowledgeBase=(KnowledgeBase) container.get("/rules");
if (knowledgeBase==null) {
throw new RuleSessionCreateException("/rules element not found");
}
knowledgeCompactor=(KnowledgeCompactor) container.get("/knowledge-compactor");
metadata=new biz.hammurapi.rules.jsr94.RuleExecutionSetMetadata(uri, (String) container.get("/name"), (String) container.get("/description"));
if (container instanceof Component) {
this.container = (Component) container;
try {
this.container.start();
} catch (ConfigurationException e) {
throw new RuleSessionCreateException("Could not start container: "+e, e);
}
}
}
/**
* This call is delegated to <code>handleManager</code>
*/
public boolean containsObject(Handle handle) {
return handleManager.contains(handle);
}
/**
* Adds object to handle manager and to knowledge base.
*/
public Handle addObject(Object obj) {
Handle ret = handleManager.addObject(obj);
knowledgeBase.add(obj);
return ret;
}
/**
* Invokes addObject() for each member of the list and returns collection of handles.
*/
public List addObjects(List objs) {
List ret=new ArrayList();
Iterator it=objs.iterator();
while (it.hasNext()) {
ret.add(addObject(it.next()));
}
return ret;
}
/**
* Invokes knowledge base's remove() for the old object, add() for the new object
* and rebinds the handle to the new object.
*/
public void updateObject(Handle handle, Object obj) {
knowledgeBase.remove(handleManager.getObject(handle));
knowledgeBase.add(obj);
handleManager.rebind(handle, obj);
}
/**
* Removes object from knowledge base. Knowledge base is
* responsible for removal of the object from the handle manager.
*/
public void removeObject(Handle handle) {
knowledgeBase.remove(handleManager.getObject(handle));
}
/**
* @return List of objects filtered by default object filter.
*/
public List getObjects() {
return getObjects(objectFilter);
}
/**
* @return List of handles.
*/
public List getHandles() {
return new ArrayList(handleManager.getHandles());
}
/**
* @return List of objects filtered by the <code>filter</code>
* @param Object filter, can be null.
*/
public List getObjects(ObjectFilter filter) {
List ret = new ArrayList();
Iterator hit=getHandles().iterator();
while (hit.hasNext()) {
Object obj=getObject((Handle) hit.next());
if (filter==null) {
ret.add(obj);
} else {
obj = filter.filter(obj);
if (obj!=null) {
ret.add(obj);
}
}
}
return knowledgeCompactor==null ? ret : knowledgeCompactor.compact(ret);
}
/**
* Delegates to knowledgeBase.executeRules(). Normally rules are executed automatically when objects
* are added or updated. Invocation of this method may be required in multithreaded inference scenario to make sure that
* all threads finished inference process.
*/
public void executeRules() {
knowledgeBase.executeRules();
}
/**
* Clears collection manager, handle manager and resets object filter.
*/
public void reset() {
executeRules(); // Make sure that object queue is empty.
collectionManager.clear();
handleManager.clear();
if (objectFilter!=null) {
objectFilter.reset();
}
knowledgeBase.reset();
}
/**
* Returns object by handle.
*/
public Object getObject(Handle handle) {
return handleManager.getObject(handle);
}
/**
* Returns execution set metadata.
*/
public RuleExecutionSetMetadata getRuleExecutionSetMetadata() {
return metadata;
}
/**
* Stops container.
*/
public void release() throws InvalidRuleSessionException {
if (container!=null) {
try {
container.stop();
} catch (ConfigurationException e) {
throw new InvalidRuleSessionException("Could not stop container", e);
}
}
}
/**
* Returns session type.
*/
public int getType() {
return sessionType;
}
// --- Stateless rule session methods ---
/**
* Calls executeRules(object, null)
*/
public List executeRules(List objects) {
return executeRules(objects, null);
}
/**
* This method is a wrapper around stateful method.
* It adds all objects to the session, executes rules,
* returns objects and finally resets the session.
*/
public List executeRules(List objects, ObjectFilter objectFilter) {
try {
Iterator it=objects.iterator();
while (it.hasNext()) {
addObject(it.next());
}
executeRules();
return getObjects(objectFilter);
} finally {
reset();
}
}
}
|