package sushi.simulation; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; import sushi.bpmn.element.AbstractBPMNElement; import sushi.bpmn.element.BPMNAndGateway; import sushi.event.SushiEvent; import sushi.event.SushiEventType; import sushi.event.attribute.SushiAttribute; import sushi.eventhandling.Broker; /** * Represents the simulation of one process instance */ public class InstanceSimulator { public List<PathSimulator> pathSimulators; private Simulator simulator; private Map<BPMNAndGateway, List<AbstractBPMNElement>> andJoinsVisitedPredecessors; private Map<SushiAttribute, List<Serializable>> attributesAndValues; private List<SushiAttribute> differingAttributes; public InstanceSimulator(AbstractBPMNElement startElement, Simulator simulator, Map<SushiAttribute, List<Serializable>> attributesAndValues, Date currentSimulationDate, List<SushiAttribute> differingAttributes){ this.setSimulator(simulator); this.attributesAndValues = attributesAndValues; this.differingAttributes = differingAttributes; PathSimulator initialPathSimulator = new PathSimulator(startElement, this, currentSimulationDate); pathSimulators = new ArrayList<PathSimulator>(); pathSimulators.add(initialPathSimulator); andJoinsVisitedPredecessors = new HashMap<BPMNAndGateway, List<AbstractBPMNElement>>(); } /** * gets the earliest PathSimulator and starts it */ public void simulateStep(){ List<SushiEvent> newEvents = getEarliestSubSimulator().continueSimulation(); Random random = new Random(); int index; for(SushiEvent event : newEvents){ SushiEventType eventType = event.getEventType(); for(SushiAttribute attribute : eventType.getValueTypes()){ for(SushiAttribute key : attributesAndValues.keySet()){ if(attribute.equals(key)){ List<Serializable> values = attributesAndValues.get(key); index = random.nextInt(values.size()); event.getValues().put(attribute.getAttributeExpression(), values.get(index)); for(SushiAttribute differingAttribute : differingAttributes){ if(differingAttribute.equals(attribute)){ if(values.size() > 1){ attributesAndValues.get(key).remove(index); } break; } } break; } } } Broker.send(event); } if(pathSimulators.isEmpty()){ getSimulator().unsubscribe(this); } } public void unsubscribe(PathSimulator simulator) { pathSimulators.remove(simulator); } public Simulator getSimulator() { return simulator; } private void setSimulator(Simulator parentSimulator) { this.simulator = parentSimulator; } public PathSimulator getEarliestSubSimulator(){ PathSimulator earliestSubSimulator = pathSimulators.get(0); for(PathSimulator subSimulator : pathSimulators){ if(subSimulator.getCurrentSimulationDate().before(earliestSubSimulator.getCurrentSimulationDate())){ earliestSubSimulator = subSimulator; } } return earliestSubSimulator; } public Date getEarliestDate(){ return getEarliestSubSimulator().getCurrentSimulationDate(); } public void addJoinPredecessorToGateway(AbstractBPMNElement predecessor, BPMNAndGateway gateway){ if(andJoinsVisitedPredecessors.containsKey(gateway)){ andJoinsVisitedPredecessors.get(gateway).add(predecessor); } else{ List<AbstractBPMNElement> predecessorList = new ArrayList<AbstractBPMNElement>(); predecessorList.add(predecessor); andJoinsVisitedPredecessors.put(gateway, predecessorList); } } public Boolean allPredecessorsOfGatewayVisited(BPMNAndGateway gateway){ return andJoinsVisitedPredecessors.containsKey(gateway) && andJoinsVisitedPredecessors.get(gateway).containsAll(gateway.getPredecessors()); } public void resetGateway(BPMNAndGateway gateway){ for(AbstractBPMNElement predecessor : gateway.getPredecessors()){ andJoinsVisitedPredecessors.get(gateway).remove(predecessor); } } }