Commit | Line | Data |
---|---|---|
4208b510 AM |
1 | /******************************************************************************* |
2 | * Copyright (c) 2015, 2016 EfficiOS Inc., Alexandre Montplaisir | |
3 | * | |
4 | * All rights reserved. This program and the accompanying materials are | |
5 | * made available under the terms of the Eclipse Public License v1.0 which | |
6 | * accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | *******************************************************************************/ | |
9 | ||
10 | package org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.handler; | |
11 | ||
12 | import static org.eclipse.tracecompass.common.core.NonNullUtils.nullToEmptyString; | |
13 | ||
14 | import java.util.List; | |
15 | ||
16 | import org.eclipse.core.commands.AbstractHandler; | |
17 | import org.eclipse.core.commands.ExecutionEvent; | |
18 | import org.eclipse.core.commands.ExecutionException; | |
19 | import org.eclipse.core.runtime.IProgressMonitor; | |
20 | import org.eclipse.core.runtime.IStatus; | |
21 | import org.eclipse.core.runtime.NullProgressMonitor; | |
22 | import org.eclipse.core.runtime.Status; | |
23 | import org.eclipse.core.runtime.jobs.Job; | |
24 | import org.eclipse.jdt.annotation.Nullable; | |
25 | import org.eclipse.jface.dialogs.IInputValidator; | |
26 | import org.eclipse.jface.dialogs.MessageDialog; | |
27 | import org.eclipse.jface.viewers.ISelection; | |
4208b510 AM |
28 | import org.eclipse.jface.viewers.IStructuredSelection; |
29 | import org.eclipse.jface.window.Window; | |
30 | import org.eclipse.swt.widgets.Display; | |
31 | import org.eclipse.swt.widgets.Shell; | |
32 | import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiAnalysis; | |
33 | import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiAnalysisReport; | |
34 | import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.module.LamiResultTable; | |
35 | import org.eclipse.tracecompass.internal.provisional.analysis.lami.ui.views.LamiReportViewFactory; | |
36 | import org.eclipse.tracecompass.tmf.core.analysis.ondemand.IOnDemandAnalysis; | |
37 | import org.eclipse.tracecompass.tmf.core.analysis.ondemand.IOnDemandAnalysisReport; | |
38 | import org.eclipse.tracecompass.tmf.core.analysis.ondemand.OnDemandAnalysisException; | |
39 | import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange; | |
40 | import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; | |
41 | import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; | |
42 | import org.eclipse.tracecompass.tmf.ui.project.model.TmfCommonProjectElement; | |
43 | import org.eclipse.tracecompass.tmf.ui.project.model.TmfOnDemandAnalysisElement; | |
44 | import org.eclipse.tracecompass.tmf.ui.project.model.TmfReportsElement; | |
4208b510 AM |
45 | import org.eclipse.ui.PartInitException; |
46 | import org.eclipse.ui.PlatformUI; | |
47 | import org.eclipse.ui.handlers.HandlerUtil; | |
48 | ||
49 | /** | |
50 | * The command handler for the "Run External Analysis" menu option. | |
51 | * | |
52 | * @author Alexandre Montplaisir | |
53 | */ | |
54 | public class RunAnalysisHandler extends AbstractHandler { | |
55 | ||
56 | @Override | |
57 | public boolean isEnabled() { | |
664dac59 PP |
58 | final Object element = HandlerUtils.getSelectedModelElement(); |
59 | if (element == null) { | |
4208b510 AM |
60 | return false; |
61 | } | |
62 | ||
4208b510 AM |
63 | /* |
64 | * plugin.xml should have done type verifications already | |
65 | */ | |
4208b510 AM |
66 | TmfOnDemandAnalysisElement elem = (TmfOnDemandAnalysisElement) element; |
67 | if (elem.getAnalysis() instanceof LamiAnalysis && elem.canRun()) { | |
68 | return true; | |
69 | } | |
70 | ||
71 | return false; | |
72 | } | |
73 | ||
74 | @Override | |
75 | public @Nullable Object execute(@Nullable ExecutionEvent event) throws ExecutionException { | |
76 | ||
77 | /* Types should have been checked by the plugin.xml already */ | |
78 | ISelection selection = HandlerUtil.getCurrentSelectionChecked(event); | |
79 | Object element = ((IStructuredSelection) selection).getFirstElement(); | |
80 | final TmfOnDemandAnalysisElement analysisElem = (TmfOnDemandAnalysisElement) element; | |
81 | ||
82 | TmfCommonProjectElement traceElem = analysisElem.getParent().getParent(); | |
83 | ITmfTrace trace = traceElem.getTrace(); | |
84 | if (trace == null) { | |
85 | /* That trace is not currently opened */ | |
86 | return null; | |
87 | } | |
88 | ||
89 | /* Retrieve and initialize the analysis module, aka read the script's metadata */ | |
90 | IOnDemandAnalysis ondemandAnalysis = analysisElem.getAnalysis(); | |
91 | if (!(ondemandAnalysis instanceof LamiAnalysis)) { | |
92 | return null; | |
93 | } | |
94 | LamiAnalysis analysis = (LamiAnalysis) ondemandAnalysis; | |
95 | ||
96 | /* Retrieve the current time range, will be used as parameters to the analysis */ | |
97 | TmfTraceManager tm = TmfTraceManager.getInstance(); | |
98 | TmfTimeRange timeRange = tm.getCurrentTraceContext().getSelectionRange(); | |
99 | if (timeRange.getStartTime().equals(timeRange.getEndTime())) { | |
100 | timeRange = null; | |
101 | } | |
102 | /* Job below needs a final reference... */ | |
103 | final TmfTimeRange tr = timeRange; | |
104 | ||
105 | /* Pop the dialog to ask for extra parameters */ | |
106 | String baseCommand = analysis.getFullCommandAsString(trace, tr); | |
107 | ||
108 | Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); | |
109 | ParameterDialog dialog = new ParameterDialog(shell, Messages.ParameterDialog_ExternalParameters, | |
110 | Messages.ParameterDialog_ExternalParametersDescription, | |
111 | baseCommand, | |
112 | PARAM_STRING_VALIDATOR); | |
113 | if (dialog.open() != Window.OK) { | |
114 | /* User clicked Cancel, don't run */ | |
115 | return null; | |
116 | } | |
117 | String extraParams = nullToEmptyString(dialog.getValue()); | |
118 | ||
119 | /* Execute the analysis and produce the reports */ | |
120 | Job job = new Job(Messages.LamiAnalysis_MainTaskName) { | |
121 | @Override | |
122 | protected @Nullable IStatus run(@Nullable IProgressMonitor monitor) { | |
123 | IProgressMonitor mon = (monitor == null ? new NullProgressMonitor() : monitor); | |
124 | try { | |
125 | List<LamiResultTable> results = analysis.execute(trace, tr, extraParams, mon); | |
126 | ||
127 | String reportName = analysis.getName() +' ' + Messages.ParameterDialog_ReportNameSuffix; | |
128 | LamiAnalysisReport report = new LamiAnalysisReport(reportName, results); | |
129 | registerNewReport(analysisElem, report); | |
130 | ||
131 | /* Automatically open the report for convenience */ | |
132 | Display.getDefault().syncExec(() -> { | |
133 | try { | |
f95c9345 | 134 | LamiReportViewFactory.createNewView(report); |
4208b510 AM |
135 | } catch (PartInitException e) { |
136 | } | |
137 | }); | |
138 | return Status.OK_STATUS; | |
139 | ||
140 | } catch (OnDemandAnalysisException e) { | |
141 | String errMsg = e.getMessage(); | |
142 | ||
143 | if (errMsg != null) { | |
144 | /* The analysis execution yielded an error */ | |
145 | Display.getDefault().asyncExec(() -> { | |
146 | MessageDialog.openError(shell, | |
147 | /* Dialog title */ | |
148 | Messages.ParameterDialog_Error, | |
149 | /* Dialog message */ | |
150 | Messages.ParameterDialog_ErrorMessage + ":\n\n" + //$NON-NLS-1$ | |
151 | errMsg); | |
152 | }); | |
153 | } | |
154 | ||
155 | return Status.CANCEL_STATUS; | |
156 | } | |
157 | } | |
158 | }; | |
159 | job.schedule(); | |
160 | ||
161 | return null; | |
162 | } | |
163 | ||
164 | private static final IInputValidator PARAM_STRING_VALIDATOR = text -> { | |
165 | if (text.isEmpty() || text.matches("[a-zA-Z0-9\\,\\-\\s]+")) { //$NON-NLS-1$ | |
166 | return null; | |
167 | } | |
168 | return Messages.ParameterDialog_StringValidatorMessage; | |
169 | }; | |
170 | ||
171 | /** | |
172 | * Register a new report | |
173 | * | |
174 | * @param analysisElem | |
175 | * The analysis's project element | |
176 | * @param report | |
177 | * The report to add | |
178 | */ | |
179 | public void registerNewReport(TmfOnDemandAnalysisElement analysisElem, IOnDemandAnalysisReport report) { | |
180 | /* For now the TmfProjectReportsElement manages the reports. */ | |
181 | TmfReportsElement reportsElement = analysisElem | |
182 | .getParent() | |
183 | .getParent() | |
184 | .getChildElementReports(); | |
185 | ||
186 | reportsElement.addReport(report); | |
187 | } | |
188 | ||
189 | } |