// the rule base is null if the loading was cancelled
if (ruleBase == null)
return;
} catch (Exception e) {
throw new InferenceException("Could not load rulebase: " + e.getMessage(), e);
}
/*
* We use a StatefulSession, because we may add additional facts
* after the initial insertion.
*
* But creating a StatefulSession adds a reference to the RuleBase,
* which can cause memory leaks. This is so that if the
* RuleBase has changed rules, they can be updated in the working
* memory. As a result, we have to call dispose() on the
* StatefulSession once we are finished with it.
*/
final StatefulSession workingMemory = ruleBase.newStatefulSession();
monitor.worked(5);
monitor.subTask("Inserting initial model");
final Map<EObject,FactHandle> factMemory = new HashMap<EObject,FactHandle>();
// automatically insert new objects based on a given object
workingMemory.addEventListener( new WorkingMemoryEventListener() {
/**
* When we insert a new element, we automatically insert
* all of its children elements.
*
* This is also the method that does all of the work
* when we insert in the root InternetApplication - it constructs
* the entire working memory model.
*/
@Override
public void objectInserted(ObjectInsertedEvent obj) {
// increment a progress monitor
if (getSubprogressMonitor() != null) {
getSubprogressMonitor().worked(1);
/*
if (obj.getObject() instanceof EObject) {
getSubprogressMonitor().subTask("Inserting " + ((EObject) obj.getObject()).eClass().getName());
}
*/
}
if (obj.getObject() instanceof EObject) {
// get all objects within
TreeIterator<EObject> it = ((EObject) obj.getObject()).eAllContents();
while (it.hasNext()) {
// need to cancel
if (monitor.isCanceled())
return;
EObject o = it.next();
factMemory.put(o, workingMemory.insert( o ));
// this solves problems where inserting something into the containment feature
// of a property which then needs to be accessed (e.g. onAccess, onEdit)
// does not correctly update the parent object for new results
if (o.eContainer() != null && factMemory.containsKey(o.eContainer())) {
workingMemory.update(factMemory.get(o.eContainer()), o.eContainer());
}
}
}
}
@Override
public void objectRetracted(ObjectRetractedEvent x) {
// TODO Auto-generated method stub
}
@Override
public void objectUpdated(ObjectUpdatedEvent x) {
// TODO Auto-generated method stub
}
});
// set up the sub progress monitor
subProgressMonitor = new InfiniteSubProgressMonitor(monitor, 45);
// to save memory, we only create the handler here, in this scope
final ICreateElements handler = handlerFactory.createHandler(model);
// allow for rules to override execution
final OverridableCreateElementsHelper overridableHandler =
new OverridableCreateElementsHelper(handler);
// need to set up these variables before we insert the model,
// otherwise the agenda cannot be built (as the rule heads use
// {@link #getHelperFunctions()}).
queue = new DroolsInsertionQueue(trackInsertions);
workingMemory.setGlobal("handler", overridableHandler);
workingMemory.setGlobal("queue", queue);
workingMemory.setGlobal("functions", getHelperFunctions());
//go !
workingMemory.insert( model );
if (monitor.isCanceled()) {
return;
}
subProgressMonitor.done();
subProgressMonitor = null;
monitor.subTask("Inferring new model elements");
/*
* This simply adds the Rule source for inserted elements
* (where possible).
*/
if (logRuleSource) {
workingMemory.addEventListener(new DefaultWorkingMemoryEventListener() {
@Override
public void objectInserted(ObjectInsertedEvent event) {
if (event.getObject() instanceof GeneratedElement) {
GeneratedElement e = (GeneratedElement) event.getObject();
try {
handler.setGeneratedRule(e, event.getPropagationContext().getRuleOrigin().getName());
} catch (InferenceException e1) {
throw new RuntimeException(e1.getMessage(), e1);
}
}
}
});
}
subProgressMonitor = new InfiniteSubProgressMonitor(monitor, 50);
subProgressMonitor.beginTask("Inferring elements iteratively", INSERTION_ITERATION_LIMIT);
for (int k = 0; k < INSERTION_ITERATION_LIMIT; k++) {
// check for monitor cancel
if (monitor.isCanceled()) {
return;
}
// actually do the work
workingMemory.fireAllRules();
// once the rules have been completed,
// insert in the new elements
// but first reset the queue
DroolsInsertionQueue oldQueue = queue;
queue = new DroolsInsertionQueue(trackInsertions);
if (trackInsertions) {
queue.addPreviousInsertions(oldQueue);
}
workingMemory.setGlobal("queue", queue );
// apply the new objects
oldQueue.apply(workingMemory, k, log);
// increment the log
log.increment("step " + k, oldQueue.size());
queueElementsAdded.put(k, oldQueue.size());
subProgressMonitor.worked(1);
}
// are there any elements left in the queue?
// if so, this might be an infinite loop
if (!queue.isEmpty()) {
throw new InferenceException("Expected an empty queue at the end of k iterations, but had: " + queue);
}
// finish the log
try {
log.save();
} catch (IOException e) {
throw new InferenceException(e);
}
// force the dispose of the working memory;
// all of our rules have been fired, all of the working
// memory has been saved to an EObject, so we should be