/* * Copyright 2012 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jbpm.process.instance.event.listeners; import java.util.Collection; import java.util.concurrent.ConcurrentHashMap; import org.kie.api.event.process.ProcessCompletedEvent; import org.kie.api.event.process.ProcessEventListener; import org.kie.api.event.process.ProcessNodeLeftEvent; import org.kie.api.event.process.ProcessNodeTriggeredEvent; import org.kie.api.event.process.ProcessStartedEvent; import org.kie.api.event.process.ProcessVariableChangedEvent; import org.kie.api.runtime.KieRuntime; import org.kie.api.runtime.ObjectFilter; import org.kie.api.runtime.process.WorkflowProcessInstance; import org.kie.api.runtime.rule.FactHandle; /** * Process event listener that is responsible for managing process instance as fact * so rules can reason over it. It ensure that process instance is inserted as soon as it starts * and gets retracted as soon as process instance completes. In addition it updates process instance * whenever process variable is updated. * */ public class RuleAwareProcessEventLister implements ProcessEventListener { private ConcurrentHashMap<Long, FactHandle> store = new ConcurrentHashMap<Long, FactHandle>(); public void beforeProcessStarted(ProcessStartedEvent event) { FactHandle handle = event.getKieRuntime().insert(event.getProcessInstance()); store.put(event.getProcessInstance().getId(), handle); } public void afterProcessStarted(ProcessStartedEvent event) { // do nothing } public void beforeProcessCompleted(ProcessCompletedEvent event) { // do nothing } public void afterProcessCompleted(ProcessCompletedEvent event) { FactHandle handle = getProcessInstanceFactHandle(event.getProcessInstance().getId(), event.getKieRuntime()); if (handle != null) { event.getKieRuntime().delete(handle); } } public void beforeNodeTriggered(ProcessNodeTriggeredEvent event) { // do nothing } public void afterNodeTriggered(ProcessNodeTriggeredEvent event) { // do nothing } public void beforeNodeLeft(ProcessNodeLeftEvent event) { // do nothing } public void afterNodeLeft(ProcessNodeLeftEvent event) { // do nothing } public void beforeVariableChanged(ProcessVariableChangedEvent event) { // do nothing } public void afterVariableChanged(ProcessVariableChangedEvent event) { FactHandle handle = getProcessInstanceFactHandle(event.getProcessInstance().getId(), event.getKieRuntime()); if (handle != null) { event.getKieRuntime().update(handle, event.getProcessInstance()); } else { handle = event.getKieRuntime().insert(event.getProcessInstance()); store.put(event.getProcessInstance().getId(), handle); } } protected FactHandle getProcessInstanceFactHandle(final Long processInstanceId, KieRuntime kruntime) { if (store.containsKey(processInstanceId)) { return store.get(processInstanceId); } //else try to search for it in the working memory Collection<FactHandle> factHandles = kruntime.getFactHandles(new ObjectFilter() { public boolean accept(Object object) { if (WorkflowProcessInstance.class.isAssignableFrom(object.getClass())) { if (((WorkflowProcessInstance) object).getId() == processInstanceId) { return true; } } return false; } }); if (factHandles != null && factHandles.size() > 0) { FactHandle handle = factHandles.iterator().next(); // put it into store for faster access store.put(processInstanceId, handle); return handle; } return null; } }