/*
* #%~
* RT Trace Viewer Plugin
* %%
* Copyright (C) 2008 - 2014 Overture
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #~%
*/
package org.overture.ide.plugins.rttraceviewer.view;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IPathEditorInput;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.EditorPart;
import org.eclipse.ui.part.FileEditorInput;
import org.overture.ide.core.utility.FileUtility;
import org.overture.ide.plugins.rttraceviewer.IRealTimeTaceViewer;
import org.overture.ide.plugins.rttraceviewer.TracefileViewerPlugin;
import org.overture.ide.plugins.rttraceviewer.data.Conjecture;
import org.overture.ide.plugins.rttraceviewer.data.Conjecture.ConjectureType;
import org.overture.ide.plugins.rttraceviewer.data.ConjectureData;
import org.overture.ide.plugins.rttraceviewer.view.GenericTabItem.AllowedOverrunDirection;
import org.overture.ide.ui.internal.util.ConsoleWriter;
public class VdmRtLogEditor extends EditorPart implements IViewCallback
{
static final boolean $assertionsDisabled = false;// !org/overturetool/tracefile/viewer/TracefileViewer.desiredAssertionStatus();
private static final ConsoleWriter cw = new ConsoleWriter("RT Log viewer");
private File selectedFile;
private Display display;
private SashForm form;
private TabFolder folder;
// private ValidationTable theConjectures;
private GenericTabItem theArch;
private GenericTabItem theOverview;
private HashMap<Long, GenericTabItem> cpuTabs; // CPU Id, Tab
private String fileName;
private List<Long> theTimes;
private long currentTime;
private boolean canExportJpg = true;
private boolean canMoveHorizontal = true;
private boolean canOpenValidation = true;
private TraceFileRunner traceRunner;
private TracefileMarker theMarkers;
private ConjectureData conjectureData;
public VdmRtLogEditor()
{
conjectureData = new ConjectureData();
// theConjectures = null;
theArch = null;
theOverview = null;
cpuTabs = new HashMap<Long, GenericTabItem>();
fileName = null;
theTimes = null;
currentTime = 0L;
traceRunner = null;
theMarkers = null;
}
@Override
public void init(IEditorSite site, IEditorInput input)
throws PartInitException
{
setSite(site);
setInput(input);
this.display = site.getShell().getDisplay();
IPath path = ((IPathEditorInput) input).getPath();
selectedFile = path.toFile();
fileName = selectedFile.getAbsolutePath();
}
@Override
public void createPartControl(Composite parent)
{
Control[] childern = parent.getChildren();
for (Control control : childern)
{
control.setVisible(false);
}
form = new SashForm(parent, 512);
form.setLayout(new FillLayout());
folder = new TabFolder(form, 128);
// theConjectures = new ValidationTable(form, this);
// form.setWeights(new int[] { 85, 15 });
theArch = new GenericTabItem("Architecture overview", folder, AllowedOverrunDirection.Both);
theOverview = new GenericTabItem("Execution overview", folder, AllowedOverrunDirection.Vertical);
cw.clear();
IFile file = null;
try
{
file = ((FileEditorInput) getEditorInput()).getFile();
FileUtility.deleteMarker(file, null, TracefileViewerPlugin.PLUGIN_ID);
theMarkers = new TracefileMarker(file);
if (FileUtility.getContent(file).size() == 0)
{
ErrorDialog.openError(getSite().getShell(), "Editor open", "File is empty", Status.CANCEL_STATUS);
return;
}
} catch (Exception e)
{
TracefileViewerPlugin.log(e);
} catch (OutOfMemoryError m)
{
showMessage("The trace file can not be visualized because the Java Virtual Machine ran out of heap space. Try to allow Overture more heap space using Virtual Machine custom arguments (e.g. -Xms40m -Xmx512m).");
return;
}
try
{
parseFile(selectedFile.getAbsolutePath());
} catch (Exception e)
{
TracefileViewerPlugin.log(e);
}
openValidationConjectures(file);
}
private void openValidationConjectures(IFile editorInputFile)
{
IPath p = new Path(editorInputFile.getName());
p = p.addFileExtension("vtc");
IFile vtcFile = editorInputFile.getParent().getFile(p);
if (vtcFile.exists())
{
try
{
ValidationConjecturesView v = getValidationConjecturesView();
if (v != null)
{
conjectureData.clear();
v.initializeLink(new InputStreamReader(vtcFile.getContents()), this);
updateOverviewPage();
}
} catch (PartInitException e)
{
TracefileViewerPlugin.log(e);
} catch (CoreException e)
{
TracefileViewerPlugin.log(e);
}
}
}
private ValidationConjecturesView getValidationConjecturesView()
{
IViewPart v;
try
{
if (PlatformUI.getWorkbench().isClosing())
{
return null;
}
v = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(IRealTimeTaceViewer.CONJECTURE_VIEW_ID);
if (v instanceof ValidationConjecturesView)
{
return (ValidationConjecturesView) v;
}
} catch (CoreException e)
{
TracefileViewerPlugin.log(e);
}
return null;
}
void openValidationConjectures()
{
FileDialog fDlg = new FileDialog(getSite().getShell());
String valFileName = fDlg.open();
ValidationConjecturesView v = getValidationConjecturesView();
if (v != null)
{
conjectureData.clear();
try
{
v.initializeLink(new FileReader(valFileName), this);
} catch (FileNotFoundException e)
{
TracefileViewerPlugin.log(e);
}
updateOverviewPage();
}
}
void diagramExportAction()
{
theArch.exportJPG(fileName + ".arch");
theOverview.exportJPG(fileName + ".overview");
for (GenericTabItem tab : cpuTabs.values())
{
tab.exportJPG(fileName + "." + tab.getName());
}
}
void moveHorizontal()
{
SelectTimeDialog theDialog = new SelectTimeDialog(folder.getShell(), theTimes, currentTime);
if (theDialog.open() == 0 && theDialog.selectedTime != currentTime)
{
currentTime = theDialog.selectedTime;
updateOverviewPage();
}
}
void moveNextHorizontal()
{
int index = theTimes.indexOf(currentTime);
if (index + 1 < theTimes.size())
{
currentTime = theTimes.get(index + 1);
updateOverviewPage();
}
}
void movePreviousHorizontal()
{
int index = theTimes.indexOf(currentTime);
if (index - 1 >= 0)
{
currentTime = theTimes.get(index - 1);
updateOverviewPage();
}
}
void refresh()
{
updateOverviewPage();
}
/*
* (non-Javadoc)
* @see org.overture.ide.plugins.rttraceviewer.viewer.IViewCallback#panToTime(long, long)
*/
public void panToTime(long time, long thrid)
{
for (Iterator<Long> iter = theTimes.iterator(); iter.hasNext();)
{
long theTime = iter.next().longValue();
if (theTime < time)
currentTime = theTime;
}
folder.setSelection(theOverview.getTabItem());
updateOverviewPage();
}
public void addLowerError(Long time, Long threadID, String name)
{
conjectureData.addConjecture(new Conjecture(time, threadID, name, ConjectureType.SOURCE));
}
public void addUpperError(Long time, Long threadID, String name)
{
conjectureData.addConjecture(new Conjecture(time, threadID, name, ConjectureType.DESTINATION));
}
private void parseFile(final String fname)
{
Shell shell = super.getSite().getShell();
try
{
IRunnableWithProgress op = new IRunnableWithProgress()
{
public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException
{
doParse(fname, monitor);
}
};
new ProgressMonitorDialog(shell).run(false, true, op);
} catch (InvocationTargetException e)
{
TracefileViewerPlugin.log(e);
} catch (InterruptedException e)
{
TracefileViewerPlugin.log(e);
}
}
@SuppressWarnings("deprecation")
private void doParse(final String fname, IProgressMonitor monitor)
{
TraceFileParser t = new TraceFileParser(fname);
t.start();
while (!t.isFinished())
{
if (monitor.isCanceled())
{
try
{
t.stop();
} catch (Exception e)
{
}
}
}
if (t.error != null)
{
showMessage("Parser error " + t.error.getMessage());
} else if (t.data != null)
{
traceRunner = new TraceFileRunner(t.data, conjectureData);
theTimes = t.data.getEventManager().getEventTimes();
getSite().getShell().getDisplay().asyncExec(new Runnable()
{
public void run()
{
createTabPages();
}
});
} else
{
showMessage("Unable to display log data. RT Logger is unset");
}
}
private void createTabPages()
{
try
{
traceRunner.drawArchitecture(theArch);
traceRunner.drawOverview(theOverview, new Long(currentTime));
canExportJpg = true;
canMoveHorizontal = true;
canOpenValidation = true;
Vector<Long> theCpus = traceRunner.getCpuIds();
cpuTabs.clear();
for (Long cpu : theCpus)
{
String cpuName = traceRunner.getCpuName(cpu);
GenericTabItem theDetail = new GenericTabItem(cpuName, folder, AllowedOverrunDirection.Horizontal);
traceRunner.drawCpu(theDetail, cpu, new Long(currentTime));
cpuTabs.put(cpu, theDetail);
}
} catch (Exception e)
{
TracefileViewerPlugin.log(e);
}
}
/*
* (non-Javadoc)
* @see org.overture.ide.plugins.rttraceviewer.viewer.IViewCallback#updateOverviewPage ()
*/
public void updateOverviewPage()
{
try
{
theOverview.disposeFigures();
traceRunner.drawOverview(theOverview, new Long(currentTime));
for (Long cpu : cpuTabs.keySet())
{
GenericTabItem tab = cpuTabs.get(cpu);
tab.disposeFigures();
traceRunner.drawCpu(tab, cpu, new Long(currentTime));
}
} catch (Exception e)
{
TracefileViewerPlugin.log(e);
}
}
/*
* (non-Javadoc)
* @see org.overture.ide.plugins.rttraceviewer.viewer.IViewCallback#showMessage(java .lang.String)
*/
public void showMessage(final String message)
{
display.asyncExec(new Runnable()
{
public void run()
{
cw.println(message);
cw.show();
}
});
}
@Override
public void setFocus()
{
folder.setFocus();
}
@Override
public void dispose()
{
try
{
ValidationConjecturesView v = getValidationConjecturesView();
if (v != null)
{
v.unlink(this);
}
theOverview.disposeFigures();
if (theMarkers != null)
{
theMarkers.dispose();
}
} catch (Exception e)
{
TracefileViewerPlugin.log(e);
}
}
@Override
public void doSave(IProgressMonitor monitor)
{
}
@Override
public void doSaveAs()
{
}
@Override
public boolean isSaveAsAllowed()
{
return false;
}
@Override
public boolean isDirty()
{
return false;
}
public boolean canExportJpg()
{
return canExportJpg;
}
public boolean canMoveHorizontal()
{
return canMoveHorizontal;
}
public boolean canOpenValidation()
{
return canOpenValidation;
}
}