package org.activiti.crystalball.simulator;
/* 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.
*/
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
*
* @author martin.grofcik
*/
public abstract class AbstractSimulationRun implements SimulationRun, SimulationDebugger {
private static Logger log = LoggerFactory.getLogger(AbstractSimulationRun.class);
protected String id;
/**
* Map for eventType -> event handlers to execute events on simulation engine
*/
protected Map<String, SimulationEventHandler> eventHandlerMap = new HashMap<String, SimulationEventHandler>();
protected ProcessEngine processEngine;
public AbstractSimulationRun(Map<String, SimulationEventHandler> eventHandlers) {
if (eventHandlers != null && !eventHandlers.isEmpty()) {
this.eventHandlerMap.putAll(eventHandlers);
}
}
@Override
public void execute(VariableScope execution) throws Exception {
init(execution);
runContinue();
close();
}
protected SimulationEvent removeSimulationEvent() {
SimulationEvent event = SimulationRunContext.getEventCalendar().removeFirstEvent();
if (event != null && event.hasSimulationTime())
this.processEngine.getProcessEngineConfiguration().getClock().setCurrentTime(new Date(event.getSimulationTime()));
return event;
}
@Override
public void init(VariableScope execution) {
initSimulationRunContext(execution);
initHandlers();
}
@Override
public void step() {
SimulationEvent event = removeSimulationEvent();
if (!simulationEnd( event)) {
log.debug("executing simulation event {}", event );
executeEvent(event);
log.debug("simulation event {event} execution done", event);
} else {
log.info("Simulation run has ended.");
}
}
@Override
public void runContinue() {
SimulationEvent event = removeSimulationEvent();
while (!simulationEnd(event)) {
executeEvent(event);
event = removeSimulationEvent();
}
}
@Override
public void runTo(long simulationTime) {
SimulationEvent breakEvent = new SimulationEvent.Builder(SimulationEvent.TYPE_BREAK_SIMULATION).
simulationTime(simulationTime).
priority(SimulationEvent.PRIORITY_SYSTEM).build();
EventCalendar calendar = SimulationRunContext.getEventCalendar();
calendar.addEvent(breakEvent);
runContinue();
}
@Override
public void runTo(String simulationEventType) {
EventCalendar eventCalendar = SimulationRunContext.getEventCalendar();
SimulationEvent event = eventCalendar.peekFirstEvent();
while (!simulationEventType.equals(event.getType()) && !simulationEnd(event)) {
step();
event = eventCalendar.peekFirstEvent();
}
}
/**
* close simulation run
*/
@Override
public abstract void close();
protected abstract void initSimulationRunContext(VariableScope execution);
protected void initHandlers() {
for( SimulationEventHandler handler : eventHandlerMap.values()) {
handler.init();
}
}
protected abstract boolean simulationEnd(SimulationEvent event);
protected void executeEvent(SimulationEvent event) {
// set simulation time to the next event for process engine too
log.debug("Simulation time:" + this.processEngine.getProcessEngineConfiguration().getClock().getCurrentTime());
SimulationEventHandler handler = eventHandlerMap.get( event.getType() );
if ( handler != null) {
log.debug("Handling event of type[{}]", event.getType());
handler.handle( event);
} else {
log.warn("Event type[{}] does not have any handler assigned.", event.getType());
}
}
}