package uk.ac.ed.inf.biopepa.ui.wizards.export; import java.util.LinkedList; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.jface.wizard.Wizard; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.dialogs.SaveAsDialog; import uk.ac.ed.inf.biopepa.core.sba.FileStringConsumer; import uk.ac.ed.inf.biopepa.core.sba.SBAModel; import uk.ac.ed.inf.biopepa.core.sba.export.BioNessieTraceLog; import uk.ac.ed.inf.biopepa.core.sba.export.ManyTraceLogger; import uk.ac.ed.inf.biopepa.core.sba.export.SimulationTracer; import uk.ac.ed.inf.biopepa.core.sba.export.SimulationTracer.NullTraceLog; import uk.ac.ed.inf.biopepa.core.sba.export.SimulationTracer.SimulationTraceLog; import uk.ac.ed.inf.biopepa.core.sba.export.TraviandoExport.TraviandoTraceLog; import uk.ac.ed.inf.biopepa.ui.interfaces.BioPEPAModel; import uk.ac.ed.inf.biopepa.ui.interfaces.IResourceProvider; import uk.ac.ed.inf.biopepa.ui.wizards.timeseries.PhasesPage; public class TraviandoExportWizard extends Wizard implements IResourceProvider { BioPEPAModel model; private ExportPage exportPage; private PhasesPage phasesPage; public TraviandoExportWizard(BioPEPAModel model) { if(model == null) throw new NullPointerException("Error; model does not exist."); this.model = model; setHelpAvailable(false); setWindowTitle("Export options for Bio-PEPA"); } private class ExportPage extends WizardPage { private Button firingsLimitCheck; private Text firingsLimitText; private FileSetter traviandoFileSetter; private FileSetter bioNessieFileSetter; private FileSetter sbrmlFileSetter; private Button timingLimitCheck; private Text timeLimitText; private Button displayCommentsButton; private Text modelCommentText; private Button displayGraph; private Text dataPointsText; private Text numberRunsText; protected ExportPage(String pageName) { super(pageName); this.setTitle("Simulation Trace"); this.setDescription("Set up a Simulation trace with possible export"); } private int textStyle = SWT.RIGHT | SWT.BORDER; private int labelStyle = SWT.SINGLE | SWT.LEFT; public void createControl(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); composite.setLayout(new GridLayout()); setControl(composite); /* Just a small label to say what to do */ Label tmpLabel = new Label(composite, labelStyle); tmpLabel.setText("Please set the time or firings limit for this trace"); tmpLabel.setLayoutData(createDefaultGridData()); // Create an inner composite for the labels and text fields Composite labelsComposite = new Composite(composite, SWT.NONE); GridLayout labelsCompLayout = new GridLayout(3, false); labelsComposite.setLayout(labelsCompLayout); Label firingLabel = new Label (labelsComposite, labelStyle); firingsLimitCheck = new Button (labelsComposite, SWT.CHECK); firingsLimitCheck.setSelection(false); firingsLimitCheck.addListener(SWT.Selection, checkBoxListener); firingLabel.setText("Number of firings limit"); firingsLimitText = new Text(labelsComposite, textStyle); firingsLimitText.setText("2000"); firingsLimitText.setLayoutData(newTextGridData()); firingsLimitText.addModifyListener(modifyListener); Label timeLimitLabel = new Label (labelsComposite, labelStyle); timingLimitCheck = new Button (labelsComposite, SWT.CHECK); timingLimitCheck.setSelection(true); timingLimitCheck.addListener(SWT.Selection, checkBoxListener); timeLimitText = new Text(labelsComposite, textStyle); timeLimitLabel.setText("Set the time limit for this trace"); timeLimitText.setText("20"); timeLimitText.setLayoutData(newTextGridData()); timeLimitText.addModifyListener(modifyListener); Composite fileSetterComposite = new Composite (composite, SWT.NONE); GridLayout filesCompLayout = new GridLayout(3, false); fileSetterComposite.setLayout(filesCompLayout); GridData fileSetterGridData = new GridData(); fileSetterGridData.grabExcessHorizontalSpace = true; fileSetterGridData.horizontalAlignment = GridData.FILL; fileSetterComposite.setLayoutData(fileSetterGridData); fileSetterGridData.minimumWidth = 100; traviandoFileSetter = new FileSetter(fileSetterComposite, "Traviando export file:", "xml"); bioNessieFileSetter = new FileSetter(fileSetterComposite, "BioNessie export file:", "bn"); sbrmlFileSetter = new FileSetter(fileSetterComposite, "SBRML results export file:", "sbrml"); displayCommentsButton = new Button (composite, SWT.CHECK); displayCommentsButton.setText("Output Comments"); displayCommentsButton.setSelection(false); Label explainComment = new Label (composite, labelStyle); explainComment.setText("Enter a comment for what the model" + " does(this isn't hugely important)"); modelCommentText = new Text (composite, SWT.LEFT | SWT.BORDER); modelCommentText.setText("Trace generated from BioPEPA Eclipse Plugin"); displayGraph = new Button (composite, SWT.CHECK); displayGraph.setText ("Show results graph"); displayGraph.setSelection(false); displayGraph.addListener(SWT.Selection, checkBoxListener); Label explainDataPoints = new Label (composite, labelStyle); explainDataPoints.setText( "Set the increment in data point size for the graph (default 1.0)"); // explainDataPoints.setEnabled(false); dataPointsText = new Text (composite, textStyle); dataPointsText.setText(""); dataPointsText.setLayoutData(newTextGridData()); dataPointsText.addModifyListener(modifyListener); Label explainNumberRuns = new Label (composite, labelStyle); explainNumberRuns.setText("The number of independent runs (default 1)"); numberRunsText = new Text (composite, textStyle); numberRunsText.setText(""); numberRunsText.setLayoutData(newTextGridData()); numberRunsText.addModifyListener(modifyListener); enableWidgets(); validate(); } private class FileSetter { private Label cfLabel; private IPath cfPath; private Button cfButton; // private String fileExtension; FileSetter (Composite parent, String exportName, String extension){ Label exportLabel = new Label (parent, labelStyle); exportLabel.setText(exportName); cfLabel = new Label (parent, labelStyle); cfLabel.setText("no file"); GridData labelGridData = new GridData(); labelGridData.grabExcessHorizontalSpace = true; labelGridData.horizontalAlignment = GridData.FILL; cfLabel.setLayoutData(labelGridData); GridData buttonGridData = new GridData (); buttonGridData.horizontalAlignment = GridData.FILL; buttonGridData.minimumWidth = 5; buttonGridData.grabExcessHorizontalSpace = true; cfButton = new Button (parent, SWT.PUSH); cfButton.setText("set file"); cfButton.setLayoutData(buttonGridData); // this.fileExtension = extension; class SetThisFile implements SelectionListener { private String extension; SetThisFile (String extension){ super(); this.extension = extension; } public void widgetDefaultSelected(SelectionEvent e) { return; } public void widgetSelected(SelectionEvent e) { SaveAsDialog saveAsDialog = new SaveAsDialog(getShell()); IPath path = model.getUnderlyingResource().getFullPath(); path = path.removeFileExtension(); if (!extension.isEmpty()){ path = path.addFileExtension(extension); } IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path); saveAsDialog.setOriginalFile(file); saveAsDialog.open(); path = saveAsDialog.getResult(); cfPath = path; cfLabel.setText(path.lastSegment()); cfButton.setText("change"); } } cfButton.addSelectionListener(new SetThisFile(extension)); } public IPath getFilePath(){ return cfPath; } } /* * A simple method to create a grid data object for * text object, since I think it is better to create a * new one for each text object such that any changes are * not then global. */ private GridData newTextGridData (){ GridData textGridData = new GridData (); textGridData.widthHint = 80; textGridData.horizontalAlignment = GridData.FILL; textGridData.grabExcessHorizontalSpace = true; return textGridData; } private ModifyListener modifyListener = new ModifyListener (){ public void modifyText(ModifyEvent arg0) { validate (); } }; private Listener checkBoxListener = new Listener() { public void handleEvent(Event event) { enableWidgets(); validate(); } }; private void enableWidgets(){ if (firingsLimitCheck.getSelection()){ firingsLimitText.setEnabled(true); } else { firingsLimitText.setEnabled(false); } if (timingLimitCheck.getSelection()){ timeLimitText.setEnabled(true); } else { timeLimitText.setEnabled(false); } if(displayGraph.getSelection()){ dataPointsText.setEnabled(true); } else { dataPointsText.setEnabled(false); } } /* private Listener commonListener = new Listener() { public void handleEvent(Event event) { validate(); } }; */ private void validate() { this.setPageComplete(false); this.setErrorMessage(null); String fText = firingsLimitText.getText().trim(); String tText = timeLimitText.getText().trim(); boolean firingsChecked = firingsLimitCheck.getSelection(); boolean timingsChecked = timingLimitCheck.getSelection(); if (firingsChecked){ try{ Integer.parseInt(fText); } catch (Exception e){ this.setPageComplete(false); this.setErrorMessage("Cannot parse firings limit"); return ; } } if (timingsChecked){ try{ Double.parseDouble(tText); } catch (Exception e){ this.setPageComplete(false); this.setErrorMessage("Cannot parse time limit"); return ; } } if(!firingsChecked && !timingsChecked){ this.setPageComplete(false); this.setErrorMessage("You must set one kind of limit"); return ; } if (displayGraph.getSelection()) { String text = dataPointsText.getText().trim(); if (!text.isEmpty()) { try { Double.parseDouble(text); } catch (Exception e) { this.setPageComplete(false); this.setErrorMessage("Cannot parse data points"); return; } } } String runsText = numberRunsText.getText().trim(); if (!runsText.isEmpty()){ try { Integer.parseInt(runsText); } catch (Exception e) { this.setPageComplete(false); this.setErrorMessage ("Cannot parse number of runs"); return ; } } this.setPageComplete(true); } public int getFiringsLimit() { if (firingsLimitCheck.getSelection()) { String text = firingsLimitText.getText().trim(); try { return Integer.parseInt(text); } catch (Exception e) { return 0; } } else { return Integer.MAX_VALUE; } } public double getTimeLimit() { if (timingLimitCheck.getSelection()) { String text = timeLimitText.getText().trim(); try { return Double.parseDouble(text); } catch (Exception e) { return 0; } } else { return Double.MAX_VALUE; } } public int getNumberRuns (){ String runsText = numberRunsText.getText().trim(); if (!runsText.isEmpty()){ try{ return Integer.parseInt(runsText); } catch (Exception e){ return 1; } } else { return 1; } } public IPath getTraviandoFilePath(){ return traviandoFileSetter.getFilePath(); } public IPath getBioNessieFilePath(){ return bioNessieFileSetter.getFilePath(); } public IPath getSBRMLFilePath (){ return sbrmlFileSetter.getFilePath(); } public boolean getDisplayComments(){ return displayCommentsButton.getSelection(); } public String getModelComment (){ if (modelCommentText == null){ return ""; } return modelCommentText.getText(); } public boolean getDisplayGraph(){ return displayGraph.getSelection(); } public double getDataPointSize() { if (displayGraph.getSelection()) { String text = dataPointsText.getText().trim(); if (text.isEmpty()) { return 1.0; } else { try { return Double.parseDouble(text); } catch (Exception e) { return 0; } } } else { return Double.MAX_VALUE; } } private GridData createDefaultGridData() { /* ...with grabbing horizontal space */ return new GridData(SWT.FILL, SWT.CENTER, true, false); } } public void addPages (){ exportPage = new ExportPage("Export a Traviando Trace"); addPage (exportPage); phasesPage = new PhasesPage (model); addPage (phasesPage); } /* * The code for creating trace loggers is a bit muddled due to * the fact that we must work if are creating a trace for * only traviando, only bioNessie or both or neither. * The thing to watch out here is that createTraviandoTraceLogger * does add the output file to the traceJob so only call this once * and only if you add the traviando trace logger produced to the * simulation tracer. */ public TraviandoTraceLog createTraviandoTraceLogger(int index, IPath traviandoFilePath, SimulationTraceJob traceJob){ IPath numberPath = traviandoFilePath.removeFileExtension(); if (index > 0){ numberPath = numberPath.addFileExtension(Integer.toString(index)); } numberPath = numberPath.addFileExtension("xml"); IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(numberPath); // Then we have to set up the string consumer which will // write out the traviando trace strings to the file in question String filePath = file.getLocation().toOSString(); FileStringConsumer fsc = new FileStringConsumer(filePath); // This allows us to set up the traviando trace logger TraviandoTraceLog travLog = new TraviandoTraceLog(fsc, model.getSBAModel()); // We are a complete consumer so the TraviandoTraceLog will // handle the opening and closing of the string consumer (file) travLog.setCompleteConsumer(true); String modelName = numberPath.removeFileExtension().lastSegment(); travLog.setModelName(modelName); travLog.setDisplayComments(exportPage.getDisplayComments()); travLog.setModelComment(exportPage.getModelComment()); // Finally we set the output file of the simulation trace job // so that it can refresh it once we are done. traceJob.addOutputFile(file); return travLog; } /* * See the above comment for createTraviandoTraceLogger but essentially * this adds the file to the trace job so that it can be refreshed, * hence only call this once and only if you really intend to create a * bionessie trace log (ie. only if you definitely add it to the * simulation tracer). */ public BioNessieTraceLog createBioNessieTraceLogger(int index, IPath bioNessieFilePath, SimulationTraceJob traceJob){ IPath numberPath = bioNessieFilePath.removeFileExtension(); if (index > 0){ numberPath = numberPath.addFileExtension(Integer.toString(index)); } numberPath = numberPath.addFileExtension("bn"); IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(numberPath); // Then we have to set up the string consumer which will // write out the traviando trace strings to the file in question String filePath = file.getLocation().toOSString(); FileStringConsumer fsc = new FileStringConsumer(filePath); // This allows us to set up the bionessie trace logger BioNessieTraceLog travLog = new BioNessieTraceLog(fsc, model.getSBAModel()); // We are a complete consumer so the BioNessieTraceLog will // handle the opening and closing of the string consumer (file) travLog.setCompleteConsumer(true); //String modelName = numberPath.removeFileExtension().lastSegment(); // Finally we set the output file of the simulation trace job // so that it can refresh it once we are done. traceJob.addOutputFile(file); return travLog; } @Override public boolean performFinish() { SBAModel sbaModel = model.getSBAModel(); IPath modelPath = model.getUnderlyingResource().getFullPath(); String modelName = modelPath.removeFileExtension().lastSegment(); SimulationTracer simTrace = new SimulationTracer(sbaModel); SimulationTraceJob traceJob = new SimulationTraceJob (modelName); int numberRuns = exportPage.getNumberRuns(); LinkedList<SimulationTraceLog> traceLoggers = new LinkedList<SimulationTraceLog>(); IPath traviandoFilePath = exportPage.getTraviandoFilePath(); IPath bioNessieFilePath = exportPage.getBioNessieFilePath(); for (int index = 0; index < numberRuns; index++){ // First of all if we want BOTH traces we have to create both // trace loggers and then combine them together into a single // trace loggers which does both if (traviandoFilePath != null && bioNessieFilePath != null ){ TraviandoTraceLog travLog; BioNessieTraceLog bioNessLog; travLog = createTraviandoTraceLogger(index, traviandoFilePath, traceJob); bioNessLog = createBioNessieTraceLogger(index, bioNessieFilePath, traceJob); ManyTraceLogger manyTraceLogger = new ManyTraceLogger(); manyTraceLogger.addSimulationTraceLogger(travLog); manyTraceLogger.addSimulationTraceLogger(bioNessLog); // Then we add the many trace logger as a logger to the // simulation itself. Note that we cannot add them both // separately as that would result in two separate simulation // runs, where instead we wish to have two trace outputs of // the same simulation trace. traceLoggers.add(manyTraceLogger); } else if (traviandoFilePath != null){ TraviandoTraceLog travLog; // So now we can assume that we ONLY want a traviando trace file // so simply create it and add it to the simulation tracer logs travLog = createTraviandoTraceLogger(index, traviandoFilePath, traceJob); traceLoggers.add(travLog); } else if (bioNessieFilePath != null){ BioNessieTraceLog bioNessLog; // Similarly if we get here we can assume that we ONLY want a bioNessie // trace and hence we only create that and add it to the simulation // trace loggers bioNessLog = createBioNessieTraceLogger(index, bioNessieFilePath, traceJob); traceLoggers.add(bioNessLog); } else { // Finally in here we want neither to be logged so we // create a null logger and add that. NullTraceLog traceLogger = new NullTraceLog (); traceLoggers.add(traceLogger); } } simTrace.setDataPointStep(exportPage.getDataPointSize()); simTrace.setFiringsLimit(exportPage.getFiringsLimit()); simTrace.setTimeLimit(exportPage.getTimeLimit()); // Now we set up any defined phases, if these aren't // defined then they should be null and the // simulation trace engine will take care of that and // create one large phase lasting the entire simulation. simTrace.setPhaseLines(phasesPage.getPhaseLines()); traceJob.setSimulationTraceLoggers(traceLoggers); traceJob.setDoGraph(exportPage.getDisplayGraph()); traceJob.setSimulationTracer(simTrace); traceJob.setSimulationTraceLoggers(traceLoggers); traceJob.setSbaModel(sbaModel); IPath sbrmlPath = exportPage.getSBRMLFilePath(); if (sbrmlPath != null){ IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(sbrmlPath); traceJob.setSbrmlFile(file); traceJob.setSbrmlPath(sbrmlPath); } traceJob.schedule(); return true; } public IResource getUnderlyingResource() { return model.getUnderlyingResource(); } }