package com.joss.common.drools.jpa; import java.util.Date; import java.util.List; import javax.persistence.EntityManager; import org.drools.WorkingMemory; import org.drools.WorkingMemoryEventManager; import org.drools.audit.WorkingMemoryLogger; import org.drools.audit.event.LogEvent; import org.drools.audit.event.RuleFlowLogEvent; import org.drools.audit.event.RuleFlowNodeLogEvent; import org.drools.command.impl.CommandBasedStatefulKnowledgeSession; import org.drools.command.impl.KnowledgeCommandContext; import org.drools.event.AgendaEventListener; import org.drools.event.KnowledgeRuntimeEventManager; import org.drools.event.RuleBaseEventListener; import org.drools.event.RuleFlowEventListener; import org.drools.event.WorkingMemoryEventListener; import org.drools.impl.StatefulKnowledgeSessionImpl; import org.drools.impl.StatelessKnowledgeSessionImpl; import org.drools.runtime.Environment; import org.drools.runtime.EnvironmentName; import org.drools.runtime.KnowledgeRuntime; import org.springframework.util.Assert; import com.joss.common.domain.drools.NodeInstanceLog; import com.joss.common.domain.drools.ProcessInstanceLog; /** * Enables history log via JPA. * * @author jserdaru * */ public class JPAWorkingMemoryDbLogger extends WorkingMemoryLogger { protected Environment env; public JPAWorkingMemoryDbLogger() { } public JPAWorkingMemoryDbLogger(final WorkingMemory workingMemory) { // Hack since superclass doesn't support setters. attachTo(workingMemory); env = workingMemory.getEnvironment(); } public JPAWorkingMemoryDbLogger( final KnowledgeRuntimeEventManager session) { // Hack since superclass doesn't support setters. attachTo(session); if (session instanceof KnowledgeRuntime) { env = ((KnowledgeRuntime) session).getEnvironment(); } else { throw new IllegalArgumentException( "Not supported session in logger: " + session.getClass()); } } private void attachTo( final WorkingMemoryEventManager workingMemoryEventManager) { workingMemoryEventManager .addEventListener((WorkingMemoryEventListener) this); workingMemoryEventManager .addEventListener((AgendaEventListener) this); workingMemoryEventManager .addEventListener((RuleFlowEventListener) this); workingMemoryEventManager .addEventListener((RuleBaseEventListener) this); } private void attachTo(final KnowledgeRuntimeEventManager session) { if (session instanceof StatefulKnowledgeSessionImpl) { WorkingMemoryEventManager eventManager = ((StatefulKnowledgeSessionImpl) session).session; eventManager .addEventListener((WorkingMemoryEventListener) this); eventManager.addEventListener((AgendaEventListener) this); eventManager.addEventListener((RuleFlowEventListener) this); eventManager.addEventListener((RuleBaseEventListener) this); } else if (session instanceof StatelessKnowledgeSessionImpl) { // ((StatelessKnowledgeSessionImpl) // session).workingMemoryEventSupport.addEventListener( this ); // ((StatelessKnowledgeSessionImpl) // session).agendaEventSupport.addEventListener( this ); // ((StatelessKnowledgeSessionImpl) // session).ruleFlowEventSupport.addEventListener( this ); // ((StatelessKnowledgeSessionImpl) // session).getRuleBase().addEventListener( this ); } else if (session instanceof CommandBasedStatefulKnowledgeSession) { WorkingMemoryEventManager eventManager = ((StatefulKnowledgeSessionImpl) ((KnowledgeCommandContext) ((CommandBasedStatefulKnowledgeSession) session) .getCommandService().getContext()) .getStatefulKnowledgesession()).session; eventManager .addEventListener((WorkingMemoryEventListener) this); eventManager.addEventListener((AgendaEventListener) this); eventManager.addEventListener((RuleFlowEventListener) this); eventManager.addEventListener((RuleBaseEventListener) this); } else { throw new IllegalArgumentException( "Not supported session in logger: " + session.getClass()); } } public void logEventCreated(LogEvent logEvent) { switch (logEvent.getType()) { case LogEvent.BEFORE_RULEFLOW_CREATED: RuleFlowLogEvent processEvent = (RuleFlowLogEvent) logEvent; addProcessLog(processEvent.getProcessInstanceId(), processEvent.getProcessId()); break; case LogEvent.AFTER_RULEFLOW_COMPLETED: processEvent = (RuleFlowLogEvent) logEvent; updateProcessLog(processEvent.getProcessInstanceId()); break; case LogEvent.BEFORE_RULEFLOW_NODE_TRIGGERED: RuleFlowNodeLogEvent nodeEvent = (RuleFlowNodeLogEvent) logEvent; addNodeEnterLog(nodeEvent.getProcessInstanceId(), nodeEvent.getProcessId(), nodeEvent .getNodeInstanceId(), nodeEvent .getNodeId()); break; case LogEvent.BEFORE_RULEFLOW_NODE_EXITED: nodeEvent = (RuleFlowNodeLogEvent) logEvent; addNodeExitLog(nodeEvent.getProcessInstanceId(), nodeEvent.getProcessId(), nodeEvent .getNodeInstanceId(), nodeEvent .getNodeId()); break; default: // ignore all other events } } private void addProcessLog(long processInstanceId, String processId) { ProcessInstanceLog log = new ProcessInstanceLog( processInstanceId, processId); getEntityManager().persist(log); } @SuppressWarnings("unchecked") private void updateProcessLog(long processInstanceId) { List result = getEntityManager() .createQuery( "from ProcessInstanceLog as log where log.processInstanceId = ? and log.end is null") .setParameter(1, processInstanceId).getResultList(); if (result != null && result.size() != 0) { ProcessInstanceLog log = result.get(result.size() - 1); log.setEnd(new Date()); getEntityManager().merge(log); } } private void addNodeEnterLog(long processInstanceId, String processId, String nodeInstanceId, String nodeId) { NodeInstanceLog log = new NodeInstanceLog( NodeInstanceLog.TYPE_ENTER, processInstanceId, processId, nodeInstanceId, nodeId); // EntityManager em = (EntityManager) env // .get(EnvironmentName.ENTITY_MANAGER); getEntityManager().persist(log); } private void addNodeExitLog(long processInstanceId, String processId, String nodeInstanceId, String nodeId) { NodeInstanceLog log = new NodeInstanceLog( NodeInstanceLog.TYPE_EXIT, processInstanceId, processId, nodeInstanceId, nodeId); // EntityManager em = (EntityManager) env // .get(EnvironmentName.ENTITY_MANAGER); getEntityManager().persist(log); } public void dispose() { } protected EntityManager getEntityManager() { EntityManager em = (EntityManager) env .get(EnvironmentName.ENTITY_MANAGER); Assert .notNull(em, "No entity manager available to log process flow instances"); return em; } }