package sushi.application.pages.simulator; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.form.AjaxButton; import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn; import org.apache.wicket.extensions.markup.html.repeater.data.table.HeadersToolbar; import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn; import org.apache.wicket.extensions.markup.html.repeater.tree.table.TreeColumn; import org.apache.wicket.extensions.markup.html.tabs.AbstractTab; import org.apache.wicket.extensions.markup.html.tabs.ITab; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.markup.repeater.Item; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import de.agilecoders.wicket.markup.html.bootstrap.tabs.Collapsible; import sushi.application.components.form.BlockingAjaxButton; import sushi.application.components.table.SelectEntryPanel; import sushi.application.components.tree.SushiLabelTreeTable; import sushi.application.pages.AbstractSushiPage; import sushi.application.pages.input.bpmn.BPMNProcessUploadPanel; import sushi.application.pages.simulator.model.SimulationTreeTableElement; import sushi.application.pages.simulator.model.SimulationTreeTableExpansion; import sushi.application.pages.simulator.model.SimulationTreeTableExpansionModel; import sushi.application.pages.simulator.model.SimulationTreeTableProvider; import sushi.bpmn.decomposition.XORComponent; import sushi.bpmn.element.AbstractBPMNElement; import sushi.bpmn.element.AbstractBPMNGateway; import sushi.bpmn.element.BPMNProcess; import sushi.bpmn.element.BPMNXORGateway; import sushi.bpmn.monitoringpoint.MonitoringPoint; import sushi.event.SushiEventType; import sushi.event.attribute.SushiAttribute; import sushi.process.SushiProcess; import sushi.simulation.DerivationType; import sushi.simulation.SimulationUtils; import sushi.simulation.Simulator; import sushi.util.SetUtil; import sushi.util.Tuple; /** * Panel representing the content panel for the first tab. */ public class BPMNSimulationPanel extends SimulationPanel { private static final long serialVersionUID = -7896431319431474548L; // private AbstractSushiPage abstractSushiPage; // private TextField<String> instanceNumberInput; // private TextField<String> daysNumberInput; // private Form<Void> layoutForm; private BPMNProcessUploadPanel processUploadPanel; private SimulationTreeTableProvider<Object> treeTableProvider; private SushiLabelTreeTable<SimulationTreeTableElement<Object>, String> treeTable; private BPMNSimUnexpectedEventPanel unexpectedEventPanel; public BPMNSimulationPanel(String id, final AbstractSushiPage abstractSushiPage) { super(id, abstractSushiPage); layoutForm = new Form("outerLayoutForm"); processUploadPanel = new BPMNProcessUploadPanel("bpmnProcessUploadPanel", abstractSushiPage); layoutForm.add(processUploadPanel); treeTableProvider = new SimulationTreeTableProvider<Object>(); createTreeTable(layoutForm); addTabs(); instanceNumberInput = new TextField<String>("instanceNumberInput", Model.of("")); layoutForm.add(instanceNumberInput); daysNumberInput = new TextField<String>("daysNumberInput", Model.of("")); layoutForm.add(daysNumberInput); AjaxButton simulateButton = new BlockingAjaxButton("simulateButton", layoutForm) { private static final long serialVersionUID = 1L; @Override public void onSubmit(AjaxRequestTarget target, Form form) { super.onSubmit(target, form); String instanceNumber = instanceNumberInput.getValue(); int numberOfInstances; if(instanceNumber != null && !instanceNumber.isEmpty()){ numberOfInstances = Integer.parseInt(instanceNumberInput.getValue()); } else { numberOfInstances = 1; } SushiProcess process = SushiProcess.findByName(processUploadPanel.getSelectedProcessName()).get(0); BPMNProcess model = process.getBpmnProcess(); if(model == null){ //TODO: warning window System.out.println("no model found"); } else{ if(!treeTableProvider.hasEmptyFields()){ Map<SushiAttribute, List<Serializable>> attributeValues = treeTableProvider.getAttributeValuesFromModel(); Map<AbstractBPMNElement, String> elementDurationStrings = treeTableProvider.getBPMNElementWithDuration(); Map<AbstractBPMNElement, DerivationType> elementDerivationTypes = treeTableProvider.getBPMNElementWithDerivationType(); Map<AbstractBPMNElement, String> elementDerivations = treeTableProvider.getBPMNElementWithDerivation(); Map<BPMNXORGateway, List<Tuple<AbstractBPMNElement, String>>> xorSplitsWithSuccessorProbabilityStrings = treeTableProvider.getXorSuccessorsWithProbability(); Map<BPMNXORGateway, List<Tuple<AbstractBPMNElement, Integer>>> xorSplitsWithSuccessorProbabilities = SimulationUtils.convertProbabilityStrings(xorSplitsWithSuccessorProbabilityStrings); Simulator simulator = new Simulator(process, model, attributeValues, elementDurationStrings, elementDerivations, elementDerivationTypes, xorSplitsWithSuccessorProbabilities); simulator.simulate(numberOfInstances); } else { abstractSushiPage.getFeedbackPanel().error("Please fill all attribute fields."); target.add(abstractSushiPage.getFeedbackPanel()); } } } }; layoutForm.add(simulateButton); add(layoutForm); processUploadPanel.setSimulationPanel(this); } public void updateMonitoringPoints(AjaxRequestTarget target) { //TODO: Werteeingaben für EventTypes der Monitoringpoints ermöglichen BPMNProcess bpmnProcess = processUploadPanel.getProcessModel(); List<AbstractBPMNElement> elementsWithMonitorinPoints = bpmnProcess.getBPMNElementsWithOutSequenceFlows(); SimulationTreeTableElement<Object> taskTreeTableElement; SimulationTreeTableElement<Object> monitoringPointTreeTableElement; SimulationTreeTableElement<Object> eventTypeTreeTableElement; SimulationTreeTableElement<Object> attributeTreeTableElement; treeTableProvider.deleteAllEntries(); for(AbstractBPMNElement bpmnElement : elementsWithMonitorinPoints){ taskTreeTableElement = new SimulationTreeTableElement<Object>(treeTableProvider.getNextID(), bpmnElement); treeTableProvider.addTreeTableElement(taskTreeTableElement); for(MonitoringPoint monitoringPoint : bpmnElement.getMonitoringPoints()){ if(monitoringPoint.getEventType() != null){ monitoringPointTreeTableElement = new SimulationTreeTableElement<Object>(treeTableProvider.getNextID(), monitoringPoint); treeTableProvider.addTreeTableElementWithParent(monitoringPointTreeTableElement, taskTreeTableElement); eventTypeTreeTableElement = new SimulationTreeTableElement<Object>(treeTableProvider.getNextID(), monitoringPoint.getEventType()); treeTableProvider.addTreeTableElementWithParent(eventTypeTreeTableElement, monitoringPointTreeTableElement); for(SushiAttribute attribute : monitoringPoint.getEventType().getValueTypes()){ attributeTreeTableElement = new SimulationTreeTableElement<Object>(treeTableProvider.getNextID(), attribute); treeTableProvider.addTreeTableElementWithParent(attributeTreeTableElement, eventTypeTreeTableElement); } } else { treeTableProvider.deleteAllEntries(); abstractSushiPage.getFeedbackPanel().error("Monitoring point with no matching event type!"); if(target != null){ target.add(treeTable); } return; } } } treeTableProvider.setCorrelationAttributes(processUploadPanel.getProcess().getCorrelationAttributes()); if(target != null){ target.add(abstractSushiPage.getFeedbackPanel()); } } private void createTreeTable(Form<Void> layoutForm) { List<IColumn<SimulationTreeTableElement<Object>, String>> columns = createColumns(); treeTable = new SushiLabelTreeTable<SimulationTreeTableElement<Object>, String>( "monitoringPointTree", columns, treeTableProvider, Integer.MAX_VALUE, new SimulationTreeTableExpansionModel<Object>()); treeTable.setOutputMarkupId(true); treeTable.getTable().addTopToolbar(new HeadersToolbar<String>(treeTable.getTable(), treeTableProvider)); SimulationTreeTableExpansion.get().expandAll(); layoutForm.add(treeTable); } private List<IColumn<SimulationTreeTableElement<Object>, String>> createColumns() { List<IColumn<SimulationTreeTableElement<Object>, String>> columns = new ArrayList<IColumn<SimulationTreeTableElement<Object>, String>>(); columns.add(new PropertyColumn<SimulationTreeTableElement<Object>, String>(Model.of("ID"), "ID")); columns.add(new TreeColumn<SimulationTreeTableElement<Object>, String>(Model.of("Sequence"), "content")); columns.add(new AbstractColumn(new Model("Probability")) { @Override public void populateItem(Item cellItem, String componentId, IModel rowModel) { int entryId = ((SimulationTreeTableElement<Object>) rowModel.getObject()).getID(); Object content = ((SimulationTreeTableElement<Object>) rowModel.getObject()).getContent(); if(content instanceof AbstractBPMNElement && SetUtil.containsXorSplit(((AbstractBPMNElement) content).getPredecessors())){ ProbabilityEntryPanel probabilityEntryPanel = new ProbabilityEntryPanel(componentId, entryId, treeTableProvider); cellItem.add(probabilityEntryPanel); probabilityEntryPanel.setTable(treeTable); } else{ cellItem.add(new EmptyPanel(componentId, entryId, treeTableProvider)); } } }); columns.add(new AbstractColumn(new Model("Value")) { @Override public void populateItem(Item cellItem, String componentId, IModel rowModel) { int entryId = ((SimulationTreeTableElement<Object>) rowModel.getObject()).getID(); if(((SimulationTreeTableElement<Object>) rowModel.getObject()).editableColumnsVisible()){ TextFieldEntryPanel textFieldEntryPanel = new TextFieldEntryPanel(componentId, entryId, treeTableProvider); cellItem.add(textFieldEntryPanel); textFieldEntryPanel.setTable(treeTable); } else{ cellItem.add(new EmptyPanel(componentId, entryId, treeTableProvider)); } } }); columns.add(new AbstractColumn(new Model("Derivation-Type")) { @Override public void populateItem(Item cellItem, String componentId, IModel rowModel) { int entryId = ((SimulationTreeTableElement<Object>) rowModel.getObject()).getID(); if(((SimulationTreeTableElement<Object>) rowModel.getObject()).getContent() instanceof AbstractBPMNElement){ DerivationTypeDropDownChoicePanel derivationChoicePanel = new DerivationTypeDropDownChoicePanel(componentId, entryId, treeTableProvider); cellItem.add(derivationChoicePanel); derivationChoicePanel.setTable(treeTable); } else{ cellItem.add(new EmptyPanel(componentId, entryId, treeTableProvider)); } } }); columns.add(new AbstractColumn(new Model("Duration")) { @Override public void populateItem(Item cellItem, String componentId, IModel rowModel) { int entryId = ((SimulationTreeTableElement<Object>) rowModel.getObject()).getID(); if(((SimulationTreeTableElement<Object>) rowModel.getObject()).getContent() instanceof AbstractBPMNElement){ DurationEntryPanel durationEntryPanel = new DurationEntryPanel(componentId, entryId, treeTableProvider); cellItem.add(durationEntryPanel); durationEntryPanel.setTable(treeTable); } else{ cellItem.add(new EmptyPanel(componentId, entryId, treeTableProvider)); } } }); return columns; } public Component getMonitoringPointTable() { return treeTable; } @Override protected void addUnexpectedEventPanel(List<ITab> tabs) { tabs.add(new AbstractTab(new Model<String>("Unexpected Events (instance-dependent)")) { public Panel getPanel(String panelId) { unexpectedEventPanel = new BPMNSimUnexpectedEventPanel(panelId, simulationPanel); return unexpectedEventPanel; } }); } };