提交 f2eb4b70 编写于 作者: T Tijs Rademakers

First version of crystalball added to Explorer

上级 ad69603a
......@@ -14,15 +14,15 @@ package org.activiti.crystalball.simulator;
*/
import org.activiti.engine.delegate.VariableScope;
import org.activiti.engine.impl.ProcessEngineImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.delegate.VariableScope;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class implements all methods for Simulation run
*
......@@ -37,7 +37,7 @@ public abstract class AbstractSimulationRun implements SimulationRun, Simulation
* Map for eventType -> event handlers to execute events on simulation engine
*/
protected Map<String, SimulationEventHandler> eventHandlerMap = new HashMap<String, SimulationEventHandler>();
protected ProcessEngineImpl processEngine;
protected ProcessEngine processEngine;
public AbstractSimulationRun(Map<String, SimulationEventHandler> eventHandlers) {
if (eventHandlers != null && !eventHandlers.isEmpty()) {
......
package org.activiti.crystalball.simulator;
import java.util.List;
/* 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
......@@ -27,6 +29,8 @@ public interface EventCalendar {
SimulationEvent removeFirstEvent();
void addEvent(SimulationEvent event);
List<SimulationEvent> getEvents();
void clear();
}
......@@ -14,11 +14,12 @@ package org.activiti.crystalball.simulator;
*/
import org.activiti.engine.delegate.VariableScope;
import org.activiti.engine.impl.ProcessEngineImpl;
import java.util.Map;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.delegate.VariableScope;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
/**
* This class provides simulation run for replay purposes
* replay uses real time and running engine to execute simulation events.
......@@ -29,11 +30,11 @@ public class ReplaySimulationRun extends AbstractSimulationRun {
private final EventCalendar eventCalendar;
public ReplaySimulationRun(ProcessEngineImpl processEngine, Map<String, SimulationEventHandler> customEventHandlerMap) {
public ReplaySimulationRun(ProcessEngine processEngine, Map<String, SimulationEventHandler> customEventHandlerMap) {
this(processEngine, new SimpleEventCalendar(processEngine.getProcessEngineConfiguration().getClock(), new SimulationEventComparator()), customEventHandlerMap);
}
public ReplaySimulationRun(ProcessEngineImpl processEngine, EventCalendar eventCalendar, Map<String, SimulationEventHandler> customEventHandlerMap) {
public ReplaySimulationRun(ProcessEngine processEngine, EventCalendar eventCalendar, Map<String, SimulationEventHandler> customEventHandlerMap) {
super(customEventHandlerMap);
this.processEngine = processEngine;
this.eventCalendar = eventCalendar;
......@@ -43,7 +44,8 @@ public class ReplaySimulationRun extends AbstractSimulationRun {
protected void initSimulationRunContext(VariableScope execution) {
SimulationRunContext.setEventCalendar(eventCalendar);
SimulationRunContext.setProcessEngine(processEngine);
SimulationRunContext.setSimulationRunId(processEngine.getProcessEngineConfiguration().getIdGenerator().getNextId());
ProcessEngineConfigurationImpl configuration = (ProcessEngineConfigurationImpl) processEngine.getProcessEngineConfiguration();
SimulationRunContext.setSimulationRunId(configuration.getIdGenerator().getNextId());
}
/**
......
......@@ -14,15 +14,16 @@ package org.activiti.crystalball.simulator;
*/
import org.activiti.engine.runtime.ClockReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.runtime.ClockReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author martin.grofcik
*/
......@@ -63,8 +64,9 @@ public class SimpleEventCalendar implements EventCalendar {
SimulationEvent minEvent = eventList.remove( minIndex );
if (minEvent.hasSimulationTime() && minEvent.getSimulationTime() < this.clockReader.getCurrentTime().getTime())
throw new RuntimeException("Unable to execute event from the past");
if (minEvent.hasSimulationTime() && minEvent.getSimulationTime() < this.clockReader.getCurrentTime().getTime()) {
throw new ActivitiException("Unable to execute event from the past");
}
if (eventList.isEmpty()) {
minIndex = NULL;
......@@ -80,6 +82,11 @@ public class SimpleEventCalendar implements EventCalendar {
}
return minEvent;
}
@Override
public List<SimulationEvent> getEvents() {
return eventList;
}
@Override
public void addEvent(SimulationEvent event) {
......
......@@ -12,16 +12,16 @@
*/
package org.activiti.crystalball.simulator;
import java.util.Stack;
import org.activiti.engine.HistoryService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.VariableScope;
import org.activiti.engine.impl.ProcessEngineImpl;
import org.activiti.engine.runtime.Clock;
import java.util.Stack;
/**
* Context in which simulation is run.
* It contains references to process engine, event calendar.
......@@ -33,7 +33,7 @@ public abstract class SimulationRunContext {
//
// Process engine on which simulation will be executed
//
protected static ThreadLocal<Stack<ProcessEngineImpl>> processEngineThreadLocal = new ThreadLocal<Stack<ProcessEngineImpl>>();
protected static ThreadLocal<Stack<ProcessEngine>> processEngineThreadLocal = new ThreadLocal<Stack<ProcessEngine>>();
//
// Simulation objects
......@@ -51,18 +51,18 @@ public abstract class SimulationRunContext {
protected static ThreadLocal<Stack<VariableScope>> executionThreadLocal = new ThreadLocal<Stack<VariableScope>>();
public static RuntimeService getRuntimeService() {
Stack<ProcessEngineImpl> stack = getStack(processEngineThreadLocal);
Stack<ProcessEngine> stack = getStack(processEngineThreadLocal);
if (stack.isEmpty()) {
return null;
}
return stack.peek().getRuntimeService();
}
public static void setProcessEngine(ProcessEngineImpl processEngine) {
public static void setProcessEngine(ProcessEngine processEngine) {
getStack(processEngineThreadLocal).push(processEngine);
}
public static ProcessEngineImpl getProcessEngine() {
public static ProcessEngine getProcessEngine() {
return getStack(processEngineThreadLocal).peek();
}
......@@ -71,7 +71,7 @@ public abstract class SimulationRunContext {
}
public static TaskService getTaskService() {
Stack<ProcessEngineImpl> stack = getStack(processEngineThreadLocal);
Stack<ProcessEngine> stack = getStack(processEngineThreadLocal);
if (stack.isEmpty()) {
return null;
}
......@@ -107,7 +107,7 @@ public abstract class SimulationRunContext {
}
public static HistoryService getHistoryService() {
Stack<ProcessEngineImpl> stack = getStack(processEngineThreadLocal);
Stack<ProcessEngine> stack = getStack(processEngineThreadLocal);
if (stack.isEmpty()) {
return null;
}
......@@ -116,7 +116,7 @@ public abstract class SimulationRunContext {
public static RepositoryService getRepositoryService() {
Stack<ProcessEngineImpl> stack = getStack(processEngineThreadLocal);
Stack<ProcessEngine> stack = getStack(processEngineThreadLocal);
if (stack.isEmpty()) {
return null;
}
......
......@@ -66,10 +66,10 @@ public class EventLogProcessInstanceCreateTransformer extends EventLog2Simulatio
simEventProperties.put(variablesKey, variableMap);
simEventProperties.put(PROCESS_INSTANCE_ID, processInstanceId);
return new SimulationEvent.Builder(simulationEventType).
priority((int) event.getLogNumber()).
properties(simEventProperties).
build();
return new SimulationEvent.Builder(simulationEventType)
.priority((int) event.getLogNumber())
.properties(simEventProperties)
.build();
}
return null;
}
......
......@@ -73,11 +73,10 @@ public class EventLogUserTaskCompleteTransformer extends EventLog2SimulationEven
properties.put(VARIABLES_LOCAL_SCOPE, localScope);
}
return
new SimulationEvent.Builder(this.simulationEventType).
priority((int) event.getLogNumber()).
properties(properties).
build();
return new SimulationEvent.Builder(this.simulationEventType)
.priority((int) event.getLogNumber())
.properties(properties)
.build();
}
return null;
}
......
......@@ -59,7 +59,7 @@ public class StartReplayLogEventHandler implements SimulationEventHandler {
public void handle(SimulationEvent event) {
// start process now
String processDefinitionId = (String) event.getProperty(processToStartIdKey);
String businessKey = (String) event.getProperty(this.businessKey);
String eventBusinessKey = (String) event.getProperty(this.businessKey);
Map<String, Object> variables = new HashMap<String, Object>();
Map<String, Object> processVariables = (Map<String, Object>) event.getProperty(variablesKey);
if (processVariables != null) {
......@@ -68,7 +68,13 @@ public class StartReplayLogEventHandler implements SimulationEventHandler {
variables.put(PROCESS_INSTANCE_ID, processInstanceId);
variables.put(SIMULATION_RUN_ID, SimulationRunContext.getSimulationRunId());
log.debug("Starting new processDefId[{}] businessKey[{}] with variables[{}]", processDefinitionId, businessKey, variables);
SimulationRunContext.getRuntimeService().startProcessInstanceById(processDefinitionId, businessKey, variables);
String startBusinessKey = null;
if (eventBusinessKey != null) {
startBusinessKey = eventBusinessKey;
} else {
startBusinessKey = this.businessKey;
}
log.debug("Starting new processDefId[{}] businessKey[{}] with variables[{}]", processDefinitionId, startBusinessKey, variables);
SimulationRunContext.getRuntimeService().startProcessInstanceById(processDefinitionId, startBusinessKey, variables);
}
}
......@@ -122,7 +122,7 @@ public class ReplayRunTest {
ProcessEngineConfigurationImpl configuration = new org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration();
configuration.
setHistory("full").
setDatabaseSchemaUpdate("create-drop").
setDatabaseSchemaUpdate("drop-create").
setJobExecutorActivate(false);
configuration.setCustomDefaultBpmnParseHandlers(Arrays.<BpmnParseHandler>asList(new AddListenerUserTaskParseHandler(TaskListener.EVENTNAME_CREATE, new UserTaskExecutionListener(USER_TASK_COMPLETED_EVENT_TYPE, USER_TASK_COMPLETED_EVENT_TYPE, listener.getSimulationEvents()))));
configuration.setEventListeners(Arrays.<ActivitiEventListener>asList(listener));
......
......@@ -144,6 +144,17 @@ public interface ManagementService {
*/
List<EventLogEntry> getEventLogEntries(Long startLogNr, Long pageSize);
/**
* [EXPERIMENTAL]
*
* Returns a list of event log entries for a specific process instance id.
* Note that the event logging must specifically must be enabled in the process engine configuration.
*
* Passing null as arguments will effectively fetch ALL event log entries.
* Be careful, as this list might be huge!
*/
List<EventLogEntry> getEventLogEntriesByProcessInstanceId(String processInstanceId);
/**
* Delete a EventLogEntry.
* Typically only used in testing, as deleting log entries defeats the whole purpose of keeping a log.
......
......@@ -12,10 +12,25 @@
*/
package org.activiti.engine.impl;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.ManagementService;
import org.activiti.engine.event.EventLogEntry;
import org.activiti.engine.impl.cmd.*;
import org.activiti.engine.impl.cmd.CancelJobCmd;
import org.activiti.engine.impl.cmd.CustomSqlExecution;
import org.activiti.engine.impl.cmd.DeleteEventLogEntry;
import org.activiti.engine.impl.cmd.ExecuteCustomSqlCmd;
import org.activiti.engine.impl.cmd.ExecuteJobsCmd;
import org.activiti.engine.impl.cmd.GetEventLogEntriesCmd;
import org.activiti.engine.impl.cmd.GetJobExceptionStacktraceCmd;
import org.activiti.engine.impl.cmd.GetPropertiesCmd;
import org.activiti.engine.impl.cmd.GetTableCountCmd;
import org.activiti.engine.impl.cmd.GetTableMetaDataCmd;
import org.activiti.engine.impl.cmd.GetTableNameCmd;
import org.activiti.engine.impl.cmd.SetJobRetriesCmd;
import org.activiti.engine.impl.db.DbSqlSession;
import org.activiti.engine.impl.db.DbSqlSessionFactory;
import org.activiti.engine.impl.interceptor.Command;
......@@ -25,10 +40,6 @@ import org.activiti.engine.management.TableMetaData;
import org.activiti.engine.management.TablePageQuery;
import org.activiti.engine.runtime.JobQuery;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
/**
* @author Tom Baeyens
......@@ -118,6 +129,11 @@ public class ManagementServiceImpl extends ServiceImpl implements ManagementServ
return commandExecutor.execute(new GetEventLogEntriesCmd(startLogNr, pageSize));
}
@Override
public List<EventLogEntry> getEventLogEntriesByProcessInstanceId(String processInstanceId) {
return commandExecutor.execute(new GetEventLogEntriesCmd(processInstanceId));
}
@Override
public void deleteEventLogEntry(long logNr) {
commandExecutor.execute(new DeleteEventLogEntry(logNr));
......
......@@ -11,6 +11,7 @@ import org.activiti.engine.impl.interceptor.CommandContext;
*/
public class GetEventLogEntriesCmd implements Command<List<EventLogEntry>> {
protected String processInstanceId = null;
protected Long startLogNr = null;
protected Long pageSize = null;
......@@ -18,6 +19,10 @@ public class GetEventLogEntriesCmd implements Command<List<EventLogEntry>> {
}
public GetEventLogEntriesCmd(String processInstanceId) {
this.processInstanceId = processInstanceId;
}
public GetEventLogEntriesCmd(Long startLogNr, Long pageSize) {
this.startLogNr = startLogNr;
this.pageSize = pageSize;
......@@ -25,12 +30,17 @@ public class GetEventLogEntriesCmd implements Command<List<EventLogEntry>> {
@Override
public List<EventLogEntry> execute(CommandContext commandContext) {
if (startLogNr == null) {
return commandContext.getEventLogEntryEntityManager().findAllEventLogEntries();
}
return commandContext.getEventLogEntryEntityManager().findEventLogEntries(
startLogNr,
pageSize != null ? pageSize : -1);
if (processInstanceId != null) {
return commandContext.getEventLogEntryEntityManager().findEventLogEntriesByProcessInstanceId(processInstanceId);
} else if (startLogNr != null) {
return commandContext.getEventLogEntryEntityManager().findEventLogEntries(
startLogNr,
pageSize != null ? pageSize : -1);
} else {
return commandContext.getEventLogEntryEntityManager().findAllEventLogEntries();
}
}
}
......@@ -91,6 +91,7 @@ public class DbSqlSessionFactory implements SessionFactory {
addDatabaseSpecificStatement("postgres", "insertEventLogEntry", "insertEventLogEntry_postgres");
addDatabaseSpecificStatement("postgres", "selectAllEventLogEntries", "selectAllEventLogEntries_postgres");
addDatabaseSpecificStatement("postgres", "selectEventLogEntries", "selectEventLogEntries_postgres");
addDatabaseSpecificStatement("postgres", "selectEventLogEntriesByProcessInstanceId", "selectEventLogEntriesByProcessInstanceId_postgres");
// oracle
databaseSpecificLimitBeforeStatements.put("oracle", "select * from ( select a.*, ROWNUM rnum from (");
......
......@@ -45,6 +45,13 @@ public class EventLogEntryEntityManager extends AbstractManager {
return getDbSqlSession().selectList("selectEventLogEntries", params);
}
@SuppressWarnings("unchecked")
public List<EventLogEntry> findEventLogEntriesByProcessInstanceId(String processInstanceId) {
Map<String, Object> params = new HashMap<String, Object>(2);
params.put("processInstanceId", processInstanceId);
return getDbSqlSession().selectList("selectEventLogEntriesByProcessInstanceId", params);
}
public void deleteEventLogEntry(long logNr) {
getDbSqlSession().getSqlSession().delete("deleteEventLogEntry", logNr);
}
......
......@@ -114,6 +114,17 @@
ORDER BY LOG_NR_
</select>
<select id="selectEventLogEntriesByProcessInstanceId" parameterType="org.activiti.engine.impl.db.ListQueryParameterObject" resultMap="eventLogEntryResultMap">
select * from ${prefix}ACT_EVT_LOG
WHERE PROC_INST_ID_ = #{parameter.processInstanceId}
ORDER BY LOG_NR_
</select>
<select id="selectEventLogEntriesByProcessInstanceId_postgres" parameterType="org.activiti.engine.impl.db.ListQueryParameterObject" resultMap="eventLogEntryResultMap_postgres">
select * from ${prefix}ACT_EVT_LOG
WHERE PROC_INST_ID_ = #{parameter.processInstanceId}
ORDER BY LOG_NR_
</select>
<!-- DELETE -->
<delete id="deleteEventLogEntry" parameterType="long">
......
......@@ -125,6 +125,10 @@
<groupId>org.activiti</groupId>
<artifactId>activiti-simple-workflow</artifactId>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-crystalball</artifactId>
</dependency>
<!-- Logging, using Log4j as SLF4J implementation -->
<dependency>
......
......@@ -18,6 +18,8 @@ import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.activiti.crystalball.simulator.SimulationDebugger;
import org.activiti.crystalball.simulator.SimulationEvent;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.explorer.identity.LoggedInUser;
......@@ -64,6 +66,11 @@ public class ExplorerApp extends Application implements HttpServletRequestListen
protected List<String> adminGroups;
protected List<String> userGroups;
protected String crystalBallCurrentDefinitionId = null;
protected String crystalBallCurrentInstanceId = null;
protected List<SimulationEvent> crystalBallSimulationEvents = null;
protected transient SimulationDebugger crystalBallSimulationDebugger = null;
public void init() {
setMainWindow(mainWindow);
mainWindow.showLoginPage();
......@@ -301,5 +308,37 @@ public class ExplorerApp extends Application implements HttpServletRequestListen
public void setSimpleWorkflowJsonConverter(SimpleWorkflowJsonConverter simpleWorkflowJsonConverter) {
this.simpleWorkflowJsonConverter = simpleWorkflowJsonConverter;
}
public String getCrystalBallCurrentDefinitionId() {
return crystalBallCurrentDefinitionId;
}
public void setCrystalBallCurrentDefinitionId(String crystalBallCurrentDefinitionId) {
this.crystalBallCurrentDefinitionId = crystalBallCurrentDefinitionId;
}
public String getCrystalBallCurrentInstanceId() {
return crystalBallCurrentInstanceId;
}
public void setCrystalBallCurrentInstanceId(String crystalBallCurrentInstanceId) {
this.crystalBallCurrentInstanceId = crystalBallCurrentInstanceId;
}
public List<SimulationEvent> getCrystalBallSimulationEvents() {
return crystalBallSimulationEvents;
}
public void setCrystalBallSimulationEvents(List<SimulationEvent> crystalBallSimulationEvents) {
this.crystalBallSimulationEvents = crystalBallSimulationEvents;
}
public SimulationDebugger getCrystalBallSimulationDebugger() {
return crystalBallSimulationDebugger;
}
public void setCrystalBallSimulationDebugger(SimulationDebugger crystalBallSimulationDebugger) {
this.crystalBallSimulationDebugger = crystalBallSimulationDebugger;
}
}
......@@ -257,6 +257,7 @@ public interface Messages {
String PROCESS_STARTED_NOTIFICATION = "process.started.notification";
String PROCESS_INSTANCE_STARTED_ON = "process.instance.started.on";
String PROCESS_INSTANCE_STARTED = "process.instance.started";
String PROCESS_INSTANCE_ENDED = "process.instance.ended";
String PROCESS_INSTANCE_HEADER_TASKS = "process.instance.header.tasks";
String PROCESS_INSTANCE_NO_TASKS = "process.instance.no.tasks";
String PROCESS_INSTANCE_HEADER_VARIABLES = "process.instance.header.variables";
......@@ -463,6 +464,12 @@ public interface Messages {
String EMAIL_RECEIVED_DATE = "email.received.date";
String EMAIL_HTML_CONTENT = "email.html.content";
String EMAIL_RECIPIENTS = "email.recipients";
// Crystalball
String CRYSTALBALL_BUTTON_REPLAY = "crystalball.button.replay";
String CRYSTALBALL_BUTTON_NEXTEVENT = "crystalball.button.nextevent";
String CRYSTALBALL_EVENT_TYPE = "crystalball.event.type";
String CRYSTALBALL_EVENT_EXECUTED = "crystalball.event.executed";
// Time formatting
String TIME_UNIT_MOMENTS = "time.unit.moments";
......
......@@ -12,16 +12,33 @@
*/
package org.activiti.explorer.ui.management.crystalball;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.activiti.crystalball.simulator.ReplaySimulationRun;
import org.activiti.crystalball.simulator.SimpleEventCalendar;
import org.activiti.crystalball.simulator.SimulationDebugger;
import org.activiti.crystalball.simulator.SimulationEvent;
import org.activiti.crystalball.simulator.SimulationEventComparator;
import org.activiti.crystalball.simulator.SimulationEventHandler;
import org.activiti.crystalball.simulator.SimulationRunContext;
import org.activiti.crystalball.simulator.delegate.event.Function;
import org.activiti.crystalball.simulator.delegate.event.impl.EventLogProcessInstanceCreateTransformer;
import org.activiti.crystalball.simulator.delegate.event.impl.EventLogTransformer;
import org.activiti.crystalball.simulator.delegate.event.impl.EventLogUserTaskCompleteTransformer;
import org.activiti.crystalball.simulator.impl.StartReplayLogEventHandler;
import org.activiti.crystalball.simulator.impl.replay.ReplayUserTaskCompleteEventHandler;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.event.EventLogEntry;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.el.NoExecutionVariableScope;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.explorer.ExplorerApp;
import org.activiti.explorer.I18nManager;
......@@ -51,10 +68,20 @@ public class EventOverviewPanel extends DetailPanel {
private static final long serialVersionUID = 1L;
// Process instance start event
private static final String PROCESS_INSTANCE_START_EVENT_TYPE = "PROCESS_INSTANCE_START";
private static final String PROCESS_DEFINITION_ID_KEY = "processDefinitionId";
private static final String VARIABLES_KEY = "variables";
// User task completed event
private static final String USER_TASK_COMPLETED_EVENT_TYPE = "USER_TASK_COMPLETED";
private static final String SIMULATION_BUSINESS_KEY = "testBusinessKey";
protected transient HistoryService historyService;
protected transient RepositoryService repositoryService;
protected transient RuntimeService runtimeService;
protected transient IdentityService identityService;
protected transient ManagementService managementService;
protected I18nManager i18nManager;
protected VariableRendererManager variableRendererManager;
......@@ -63,18 +90,24 @@ public class EventOverviewPanel extends DetailPanel {
protected Button replayButton;
protected Table instanceTable;
protected HorizontalLayout eventLayout;
protected Button stepButton;
protected Button showProcessInstanceButton;
protected Table eventTable;
protected Label noMembersTable;
protected List<ProcessDefinition> definitionList;
protected Map<String, ProcessDefinition> definitionMap = new HashMap<String, ProcessDefinition>();
protected List<HistoricProcessInstance> instanceList;
protected List<SimulationEvent> simulationEvents;
protected HistoricProcessInstance replayHistoricInstance;
protected SimulationDebugger simulationDebugger;
public EventOverviewPanel() {
this.runtimeService = ProcessEngines.getDefaultProcessEngine().getRuntimeService();
this.historyService = ProcessEngines.getDefaultProcessEngine().getHistoryService();
this.repositoryService = ProcessEngines.getDefaultProcessEngine().getRepositoryService();
this.identityService = ProcessEngines.getDefaultProcessEngine().getIdentityService();
this.managementService = ProcessEngines.getDefaultProcessEngine().getManagementService();
this.variableRendererManager = ExplorerApp.get().getVariableRendererManager();
this.definitionList = repositoryService.createProcessDefinitionQuery().orderByProcessDefinitionName().asc().list();
this.instanceList = historyService.createHistoricProcessInstanceQuery().orderByProcessInstanceStartTime().desc().list();
......@@ -82,6 +115,7 @@ public class EventOverviewPanel extends DetailPanel {
initializeDefinitionMap();
init();
initializeCurrentValues();
}
protected void initializeDefinitionMap() {
......@@ -90,6 +124,34 @@ public class EventOverviewPanel extends DetailPanel {
}
}
protected void initializeCurrentValues() {
if (ExplorerApp.get().getCrystalBallSimulationDebugger() != null) {
this.simulationDebugger = ExplorerApp.get().getCrystalBallSimulationDebugger();
this.simulationEvents = ExplorerApp.get().getCrystalBallSimulationEvents();
String selectedDefinitionId = ExplorerApp.get().getCrystalBallCurrentDefinitionId();
if (selectedDefinitionId != null) {
definitionSelect.setValue(selectedDefinitionId);
}
String selectedInstanceId = ExplorerApp.get().getCrystalBallCurrentInstanceId();
if (selectedInstanceId != null) {
instanceTable.setValue(selectedInstanceId);
}
List<HistoricProcessInstance> replayProcessInstanceList = historyService.createHistoricProcessInstanceQuery()
.processInstanceBusinessKey(SIMULATION_BUSINESS_KEY)
.orderByProcessInstanceStartTime()
.desc()
.list();
if (replayProcessInstanceList != null && replayProcessInstanceList.size() > 0) {
replayHistoricInstance = replayProcessInstanceList.get(0);
}
refreshEvents();
}
}
protected void init() {
setSizeFull();
addStyleName(Reindeer.PANEL_LIGHT);
......@@ -99,6 +161,15 @@ public class EventOverviewPanel extends DetailPanel {
}
protected void initProcessInstances() {
HorizontalLayout instancesHeader = new HorizontalLayout();
instancesHeader.setSpacing(false);
instancesHeader.setMargin(false);
instancesHeader.setWidth(100, UNITS_PERCENTAGE);
instancesHeader.addStyleName(ExplorerLayout.STYLE_DETAIL_BLOCK);
addDetailComponent(instancesHeader);
initProcessInstanceTitle(instancesHeader);
HorizontalLayout selectLayout = new HorizontalLayout();
selectLayout.setSpacing(true);
selectLayout.setMargin(true);
......@@ -118,14 +189,16 @@ public class EventOverviewPanel extends DetailPanel {
@Override
public void valueChange(ValueChangeEvent event) {
if (definitionSelect.getValue() != null) {
refreshInstances((String) definitionSelect.getValue());
String selectedDefinitionId = (String) definitionSelect.getValue();
ExplorerApp.get().setCrystalBallCurrentDefinitionId(selectedDefinitionId);
refreshInstances(selectedDefinitionId);
}
}
});
selectLayout.addComponent(definitionSelect);
replayButton = new Button("Replay");
replayButton = new Button(i18nManager.getMessage(Messages.CRYSTALBALL_BUTTON_REPLAY));
replayButton.setEnabled(false);
replayButton.addListener(new ClickListener() {
......@@ -133,7 +206,41 @@ public class EventOverviewPanel extends DetailPanel {
@Override
public void buttonClick(ClickEvent event) {
if (instanceTable.getValue() != null) {
String processInstanceId = (String) instanceTable.getValue();
ExplorerApp.get().setCrystalBallCurrentInstanceId(processInstanceId);
List<EventLogEntry> eventLogEntries = managementService.getEventLogEntriesByProcessInstanceId(processInstanceId);
if (eventLogEntries == null || eventLogEntries.size() == 0) return;
EventLogTransformer transformer = new EventLogTransformer(getTransformers());
simulationEvents = transformer.transform(eventLogEntries);
ExplorerApp.get().setCrystalBallSimulationEvents(simulationEvents);
SimpleEventCalendar eventCalendar = new SimpleEventCalendar(
ProcessEngines.getDefaultProcessEngine().getProcessEngineConfiguration().getClock(),
new SimulationEventComparator());
eventCalendar.addEvents(simulationEvents);
// replay process instance run
simulationDebugger = new ReplaySimulationRun(ProcessEngines.getDefaultProcessEngine(),
eventCalendar, getReplayHandlers(processInstanceId));
ExplorerApp.get().setCrystalBallSimulationDebugger(simulationDebugger);
simulationDebugger.init(new NoExecutionVariableScope());
simulationDebugger.step();
// replay process was started
List<HistoricProcessInstance> replayProcessInstanceList = historyService.createHistoricProcessInstanceQuery()
.processInstanceBusinessKey(SIMULATION_BUSINESS_KEY)
.orderByProcessInstanceStartTime()
.desc()
.list();
if (replayProcessInstanceList != null && replayProcessInstanceList.size() > 0) {
replayHistoricInstance = replayProcessInstanceList.get(0);
}
refreshEvents();
}
}
});
selectLayout.addComponent(replayButton);
......@@ -147,7 +254,7 @@ public class EventOverviewPanel extends DetailPanel {
}
protected void initProcessInstanceTitle(HorizontalLayout instancesHeader) {
Label titleHeader = new Label(i18nManager.getMessage(Messages.ADMIN_DEFINITIONS));
Label titleHeader = new Label(i18nManager.getMessage(Messages.PROCESS_INSTANCES));
titleHeader.addStyleName(ExplorerLayout.STYLE_H3);
instancesHeader.addComponent(titleHeader);
}
......@@ -171,7 +278,7 @@ public class EventOverviewPanel extends DetailPanel {
instanceTable.addContainerProperty("id", String.class, null, i18nManager.getMessage(Messages.PROCESS_INSTANCE_ID), null, Table.ALIGN_LEFT);
instanceTable.addContainerProperty("definitionName", String.class, null, i18nManager.getMessage(Messages.PROCESS_INSTANCE_NAME), null, Table.ALIGN_LEFT);
instanceTable.addContainerProperty("started", String.class, null, i18nManager.getMessage(Messages.PROCESS_INSTANCE_STARTED), null, Table.ALIGN_LEFT);
instanceTable.addContainerProperty("ended", String.class, null, i18nManager.getMessage(Messages.PROCESS_INSTANCE_STARTED), null, Table.ALIGN_LEFT);
instanceTable.addContainerProperty("ended", String.class, null, i18nManager.getMessage(Messages.PROCESS_INSTANCE_ENDED), null, Table.ALIGN_LEFT);
fillInstanceValues();
......@@ -224,12 +331,43 @@ public class EventOverviewPanel extends DetailPanel {
protected void initEvents() {
HorizontalLayout eventsHeader = new HorizontalLayout();
eventsHeader.setSpacing(true);
eventsHeader.setWidth(100, UNITS_PERCENTAGE);
eventsHeader.setWidth(80, UNITS_PERCENTAGE);
eventsHeader.addStyleName(ExplorerLayout.STYLE_DETAIL_BLOCK);
addDetailComponent(eventsHeader);
initEventTitle(eventsHeader);
stepButton = new Button(i18nManager.getMessage(Messages.CRYSTALBALL_BUTTON_NEXTEVENT));
stepButton.setEnabled(false);
stepButton.addListener(new ClickListener() {
private static final long serialVersionUID = 1L;
@Override
public void buttonClick(ClickEvent event) {
if (SimulationRunContext.getEventCalendar().getEvents().size() > 0) {
simulationDebugger.step();
refreshEvents();
}
}
});
eventsHeader.addComponent(stepButton);
eventsHeader.setComponentAlignment(stepButton, Alignment.MIDDLE_LEFT);
showProcessInstanceButton = new Button();
showProcessInstanceButton.addStyleName(Reindeer.BUTTON_LINK);
showProcessInstanceButton.addListener(new ClickListener() {
private static final long serialVersionUID = 1L;
public void buttonClick(ClickEvent event) {
if (replayHistoricInstance != null) {
ExplorerApp.get().getViewManager().showMyProcessInstancesPage(replayHistoricInstance.getId());
}
}
});
eventsHeader.addComponent(showProcessInstanceButton);
eventsHeader.setComponentAlignment(showProcessInstanceButton, Alignment.MIDDLE_LEFT);
eventLayout = new HorizontalLayout();
eventLayout.setWidth(100, UNITS_PERCENTAGE);
addDetailComponent(eventLayout);
......@@ -244,6 +382,7 @@ public class EventOverviewPanel extends DetailPanel {
protected void initEventsTable() {
eventTable = new Table();
eventTable.setVisible(false);
eventTable.setWidth(100, UNITS_PERCENTAGE);
eventTable.setHeight(250, UNITS_PIXELS);
......@@ -252,17 +391,51 @@ public class EventOverviewPanel extends DetailPanel {
eventTable.setSelectable(true);
eventTable.setSortDisabled(false);
eventTable.addContainerProperty("id", String.class, null, i18nManager.getMessage(Messages.PROCESS_INSTANCE_ID), null, Table.ALIGN_LEFT);
eventTable.addContainerProperty("name", String.class, null, i18nManager.getMessage(Messages.PROCESS_INSTANCE_NAME), null, Table.ALIGN_LEFT);
eventTable.addContainerProperty("nr of instances", String.class, null, i18nManager.getMessage(Messages.ADMIN_NR_INSTANCES), null, Table.ALIGN_LEFT);
/*for (ManagementProcessDefinition managementDefinition : runningDefinitions.values()) {
eventTable.addItem(new String[]{managementDefinition.processDefinition.getId(),
managementDefinition.processDefinition.getName(),
String.valueOf(managementDefinition.runningInstances.size())},
managementDefinition.processDefinition.getId());
}*/
eventTable.addContainerProperty("type", String.class, null, i18nManager.getMessage(Messages.CRYSTALBALL_EVENT_TYPE), null, Table.ALIGN_LEFT);
eventTable.addContainerProperty("executed", String.class, null, i18nManager.getMessage(Messages.CRYSTALBALL_EVENT_EXECUTED), null, Table.ALIGN_LEFT);
eventLayout.addComponent(eventTable);
}
protected void refreshEvents() {
stepButton.setEnabled(false);
showProcessInstanceButton.setVisible(false);
eventTable.removeAllItems();
fillEventValues();
}
protected void fillEventValues() {
for (SimulationEvent originalEvent : simulationEvents) {
boolean executed = true;
for (SimulationEvent event : SimulationRunContext.getEventCalendar().getEvents()) {
if (originalEvent.equals(event)) {
executed = false;
stepButton.setEnabled(true);
showProcessInstanceButton.setCaption(i18nManager.getMessage(
Messages.TASK_PART_OF_PROCESS, definitionMap.get(replayHistoricInstance.getProcessDefinitionId())));
showProcessInstanceButton.setVisible(true);
break;
}
}
Object itemId = eventTable.addItem();
eventTable.getItem(itemId).getItemProperty("type").setValue(originalEvent.getType());
eventTable.getItem(itemId).getItemProperty("executed").setValue(executed);
}
eventTable.setVisible(true);
}
protected List<Function<EventLogEntry, SimulationEvent>> getTransformers() {
List<Function<EventLogEntry, SimulationEvent>> transformers = new ArrayList<Function<EventLogEntry, SimulationEvent>>();
transformers.add(new EventLogProcessInstanceCreateTransformer(PROCESS_INSTANCE_START_EVENT_TYPE, PROCESS_DEFINITION_ID_KEY, SIMULATION_BUSINESS_KEY, VARIABLES_KEY));
transformers.add(new EventLogUserTaskCompleteTransformer(USER_TASK_COMPLETED_EVENT_TYPE));
return transformers;
}
protected Map<String, SimulationEventHandler> getReplayHandlers(String processInstanceId) {
Map<String, SimulationEventHandler> handlers = new HashMap<String, SimulationEventHandler>();
handlers.put(PROCESS_INSTANCE_START_EVENT_TYPE, new StartReplayLogEventHandler(processInstanceId, PROCESS_DEFINITION_ID_KEY, SIMULATION_BUSINESS_KEY, VARIABLES_KEY));
handlers.put(USER_TASK_COMPLETED_EVENT_TYPE, new ReplayUserTaskCompleteEventHandler());
return handlers;
}
}
......@@ -238,6 +238,7 @@ process.start.time = Started {0}
process.started.notification = Process {0} has been started
process.instance.started.on = Started {0}
process.instance.started = Started
process.instance.ended = Ended
process.instance.header.tasks = Tasks
process.instance.no.tasks=There are no tasks for this process instance.
process.instance.header.variables = Variables
......@@ -438,6 +439,12 @@ email.subject = Subject
email.sent.date = Date sent
email.received.date = Date received
#Crystalball
crystalball.button.replay=Replay
crystalball.button.nextevent=Execute next event
crystalball.event.type=Event type
crystalball.event.executed=Executed
# Time formatting
time.unit.moments=moments
time.unit.minute=one minute
......
......@@ -225,6 +225,11 @@
<artifactId>activiti-rest</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-crystalball</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-webapp-rest2</artifactId>
......@@ -699,6 +704,7 @@
<module>modules/activiti-cdi</module>
<module>modules/activiti-osgi</module>
<module>modules/activiti-ldap</module>
<module>modules/activiti-crystalball</module>
</modules>
<build>
<plugins>
......@@ -862,6 +868,7 @@
<module>modules/activiti-diagram-rest</module>
<module>modules/activiti-bpmn-layout</module>
<module>modules/activiti-simple-workflow</module>
<module>modules/activiti-crystalball</module>
</modules>
<properties>
<skipTests>true</skipTests>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册