tmf: Fix Filter viewer context menu when opened from Colors view
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / analysis / TmfAbstractAnalysisModule.java
CommitLineData
c068a752 1/*******************************************************************************
60ae41e1 2 * Copyright (c) 2013, 2014 École Polytechnique de Montréal
c068a752
GB
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 * Contributors:
10 * Geneviève Bastien - Initial API and implementation
11 *******************************************************************************/
12
13package org.eclipse.linuxtools.tmf.core.analysis;
14
15import java.util.ArrayList;
63c43609 16import java.util.Collections;
c068a752
GB
17import java.util.HashMap;
18import java.util.List;
19import java.util.Map;
20import java.util.concurrent.CountDownLatch;
21import java.util.concurrent.TimeUnit;
22
23import org.eclipse.core.runtime.IProgressMonitor;
24import org.eclipse.core.runtime.IStatus;
25import org.eclipse.core.runtime.Status;
26import org.eclipse.core.runtime.jobs.Job;
dc58a1fb 27import org.eclipse.jdt.annotation.NonNull;
c068a752
GB
28import org.eclipse.linuxtools.internal.tmf.core.Activator;
29import org.eclipse.linuxtools.tmf.core.component.TmfComponent;
30import org.eclipse.linuxtools.tmf.core.exceptions.TmfAnalysisException;
31import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
32import org.eclipse.linuxtools.tmf.core.signal.TmfStartAnalysisSignal;
33import org.eclipse.linuxtools.tmf.core.signal.TmfTraceClosedSignal;
34import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
b5e8ee95 35import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
c068a752
GB
36import org.eclipse.osgi.util.NLS;
37
38/**
39 * Base class that analysis modules main class may extend. It provides default
40 * behavior to some methods of the analysis module
41 *
42 * @author Geneviève Bastien
43 * @since 3.0
44 */
45public abstract class TmfAbstractAnalysisModule extends TmfComponent implements IAnalysisModule {
46
dc58a1fb
GB
47 @NonNull private static final String UNDEFINED_ID = "undefined"; //$NON-NLS-1$
48
c068a752
GB
49 private String fName, fId;
50 private boolean fAutomatic = false, fStarted = false;
51 private ITmfTrace fTrace;
a4524c1b
AM
52 private final Map<String, Object> fParameters = new HashMap<>();
53 private final List<String> fParameterNames = new ArrayList<>();
54 private final List<IAnalysisOutput> fOutputs = new ArrayList<>();
55 private List<IAnalysisParameterProvider> fParameterProviders = new ArrayList<>();
c068a752
GB
56 private Job fJob = null;
57
58 private final Object syncObj = new Object();
59
60 /* Latch tracking if the analysis is completed or not */
61 private CountDownLatch fFinishedLatch = new CountDownLatch(0);
62
63 private boolean fAnalysisCancelled = false;
64
65 @Override
66 public boolean isAutomatic() {
67 return fAutomatic;
68 }
69
70 @Override
71 public String getName() {
72 return fName;
73 }
74
75 @Override
76 public void setName(String name) {
77 fName = name;
78 }
79
80 @Override
81 public void setId(String id) {
82 fId = id;
83 }
84
85 @Override
dc58a1fb 86 @NonNull
c068a752 87 public String getId() {
dc58a1fb
GB
88 String id = fId;
89 if (id == null) {
90 Activator.logError("Analysis module getId(): the id should not be null in class " + this.getClass().getSimpleName()); //$NON-NLS-1$
91 return UNDEFINED_ID;
92 }
93 return id;
c068a752
GB
94 }
95
96 @Override
97 public void setAutomatic(boolean auto) {
98 fAutomatic = auto;
99 }
100
101 @Override
102 public void setTrace(ITmfTrace trace) throws TmfAnalysisException {
103 if (fTrace != null) {
104 throw new TmfAnalysisException(NLS.bind(Messages.TmfAbstractAnalysisModule_TraceSetMoreThanOnce, getName()));
105 }
106
107 /* Check that analysis can be executed */
108 if (!canExecute(trace)) {
109 throw new TmfAnalysisException(NLS.bind(Messages.TmfAbstractAnalysisModule_AnalysisCannotExecute, getName()));
110 }
111 fTrace = trace;
112 /* Get the parameter providers for this trace */
113 fParameterProviders = TmfAnalysisManager.getParameterProviders(this, fTrace);
114 for (IAnalysisParameterProvider provider : fParameterProviders) {
115 provider.registerModule(this);
116 }
117 resetAnalysis();
118 fStarted = false;
119 }
120
121 /**
122 * Gets the trace
123 *
124 * @return The trace
125 */
126 protected ITmfTrace getTrace() {
127 return fTrace;
128 }
129
130 @Override
131 public void addParameter(String name) {
132 fParameterNames.add(name);
133 }
134
135 @Override
136 public synchronized void setParameter(String name, Object value) {
137 if (!fParameterNames.contains(name)) {
138 throw new RuntimeException(NLS.bind(Messages.TmfAbstractAnalysisModule_InvalidParameter, name, getName()));
139 }
140 Object oldValue = fParameters.get(name);
141 fParameters.put(name, value);
142 if ((value != null) && !(value.equals(oldValue))) {
143 parameterChanged(name);
144 }
145 }
146
147 @Override
148 public synchronized void notifyParameterChanged(String name) {
149 if (!fParameterNames.contains(name)) {
150 throw new RuntimeException(NLS.bind(Messages.TmfAbstractAnalysisModule_InvalidParameter, name, getName()));
151 }
152 Object oldValue = fParameters.get(name);
153 Object value = getParameter(name);
154 if ((value != null) && !(value.equals(oldValue))) {
155 parameterChanged(name);
156 }
157 }
158
159 /**
160 * Used to indicate that a parameter value has been changed
161 *
162 * @param name
163 * The name of the modified parameter
164 */
165 protected void parameterChanged(String name) {
166
167 }
168
169 @Override
170 public Object getParameter(String name) {
171 Object paramValue = fParameters.get(name);
172 /* The parameter is not set, maybe it can be provided by someone else */
173 if ((paramValue == null) && (fTrace != null)) {
174 for (IAnalysisParameterProvider provider : fParameterProviders) {
175 paramValue = provider.getParameter(name);
176 if (paramValue != null) {
177 break;
178 }
179 }
180 }
181 return paramValue;
182 }
183
184 @Override
185 public boolean canExecute(ITmfTrace trace) {
186 return true;
187 }
188
189 /**
190 * Set the countdown latch back to 1 so the analysis can be executed again
191 */
192 protected void resetAnalysis() {
0d3a54a3 193 fFinishedLatch.countDown();
c068a752
GB
194 fFinishedLatch = new CountDownLatch(1);
195 }
196
197 /**
198 * Actually executes the analysis itself
199 *
200 * @param monitor
201 * Progress monitor
202 * @return Whether the analysis was completed successfully or not
203 * @throws TmfAnalysisException
204 * Method may throw an analysis exception
205 */
206 protected abstract boolean executeAnalysis(final IProgressMonitor monitor) throws TmfAnalysisException;
207
208 /**
209 * Indicate the analysis has been canceled. It is abstract to force
210 * implementing class to cleanup what they are running. This is called by
211 * the job's canceling. It does not need to be called directly.
212 */
213 protected abstract void canceling();
214
215 /**
216 * To be called when the analysis is completed, whether normally or because
217 * it was cancelled or for any other reason.
218 *
219 * It has to be called inside a synchronized block
220 */
221 private void setAnalysisCompleted() {
222 fStarted = false;
223 fJob = null;
224 fFinishedLatch.countDown();
225 }
226
227 /**
228 * Cancels the analysis if it is executing
229 */
230 @Override
231 public final void cancel() {
232 synchronized (syncObj) {
233 if (fJob != null) {
234 if (fJob.cancel()) {
235 fAnalysisCancelled = true;
236 setAnalysisCompleted();
237 }
238 }
239 fStarted = false;
240 }
241 }
242
130e6f4e
MAL
243 @Override
244 public void dispose() {
245 super.dispose();
246 cancel();
247 }
248
c068a752
GB
249 private void execute() {
250
251 /*
252 * TODO: The analysis in a job should be done at the analysis manager
253 * level instead of depending on this abstract class implementation,
254 * otherwise another analysis implementation may block the main thread
255 */
256
257 /* Do not execute if analysis has already run */
258 if (fFinishedLatch.getCount() == 0) {
259 return;
260 }
261
262 /* Do not execute if analysis already running */
263 synchronized (syncObj) {
264 if (fStarted) {
265 return;
266 }
267 fStarted = true;
268 }
269
88567ed2 270 final ITmfTrace trace = fTrace;
c068a752
GB
271 /*
272 * Actual analysis will be run on a separate thread
273 */
274 fJob = new Job(NLS.bind(Messages.TmfAbstractAnalysisModule_RunningAnalysis, getName())) {
275 @Override
276 protected IStatus run(final IProgressMonitor monitor) {
277 try {
278 monitor.beginTask("", IProgressMonitor.UNKNOWN); //$NON-NLS-1$
279 broadcast(new TmfStartAnalysisSignal(TmfAbstractAnalysisModule.this, TmfAbstractAnalysisModule.this));
280 fAnalysisCancelled = !executeAnalysis(monitor);
281 } catch (TmfAnalysisException e) {
282 Activator.logError("Error executing analysis with trace " + getTrace().getName(), e); //$NON-NLS-1$
283 } finally {
284 synchronized (syncObj) {
285 monitor.done();
286 setAnalysisCompleted();
287 }
88567ed2 288 TmfTraceManager.refreshSupplementaryFiles(trace);
c068a752
GB
289 }
290 if (!fAnalysisCancelled) {
291 return Status.OK_STATUS;
292 }
baa96b1d
BH
293 // Reset analysis so that it can be executed again.
294 resetAnalysis();
c068a752
GB
295 return Status.CANCEL_STATUS;
296 }
297
298 @Override
299 protected void canceling() {
300 TmfAbstractAnalysisModule.this.canceling();
301 }
302
303 };
304 fJob.schedule();
305 }
306
307 @Override
308 public IStatus schedule() {
309 if (fTrace == null) {
310 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, String.format("No trace specified for analysis %s", getName())); //$NON-NLS-1$
311 }
312 execute();
313
314 return Status.OK_STATUS;
315 }
316
317 @Override
d9810555
AM
318 public Iterable<IAnalysisOutput> getOutputs() {
319 return fOutputs;
c068a752
GB
320 }
321
322 @Override
323 public void registerOutput(IAnalysisOutput output) {
324 if (!fOutputs.contains(output)) {
325 fOutputs.add(output);
326 }
327 }
328
7d6122fc
AM
329 @Override
330 public boolean waitForCompletion() {
331 try {
332 fFinishedLatch.await();
333 } catch (InterruptedException e) {
334 Activator.logError("Error while waiting for module completion", e); //$NON-NLS-1$
335 }
336 return !fAnalysisCancelled;
337 }
338
c068a752
GB
339 @Override
340 public boolean waitForCompletion(IProgressMonitor monitor) {
341 try {
0d3a54a3
AM
342 while (!fFinishedLatch.await(500, TimeUnit.MILLISECONDS)) {
343 if (fAnalysisCancelled || monitor.isCanceled()) {
c068a752
GB
344 fAnalysisCancelled = true;
345 return false;
346 }
347 }
348 } catch (InterruptedException e) {
349 Activator.logError("Error while waiting for module completion", e); //$NON-NLS-1$
350 }
351 return !fAnalysisCancelled;
352 }
353
354 /**
355 * Signal handler for trace closing
356 *
357 * @param signal
358 * Trace closed signal
359 */
360 @TmfSignalHandler
361 public void traceClosed(TmfTraceClosedSignal signal) {
362 /* Is the closing trace the one that was requested? */
363 if (signal.getTrace() == fTrace) {
364 cancel();
365 fTrace = null;
366 }
367 }
368
369 /**
370 * Returns a full help text to display
371 *
372 * @return Full help text for the module
373 */
374 protected String getFullHelpText() {
375 return NLS.bind(Messages.TmfAbstractAnalysisModule_AnalysisModule, getName());
376 }
377
378 /**
379 * Gets a short help text, to display as header to other help text
380 *
381 * @param trace
382 * The trace to show help for
383 *
384 * @return Short help text describing the module
385 */
386 protected String getShortHelpText(ITmfTrace trace) {
387 return NLS.bind(Messages.TmfAbstractAnalysisModule_AnalysisForTrace, getName(), trace.getName());
388 }
389
390 /**
391 * Gets the help text specific for a trace who does not have required
392 * characteristics for module to execute
393 *
394 * @param trace
395 * The trace to apply the analysis to
396 * @return Help text
397 */
398 protected String getTraceCannotExecuteHelpText(ITmfTrace trace) {
399 return Messages.TmfAbstractAnalysisModule_AnalysisCannotExecute;
400 }
401
402 @Override
403 public String getHelpText() {
404 return getFullHelpText();
405 }
406
407 @Override
408 public String getHelpText(ITmfTrace trace) {
409 if (trace == null) {
410 return getHelpText();
411 }
412 String text = getShortHelpText(trace);
413 if (!canExecute(trace)) {
414 text = text + getTraceCannotExecuteHelpText(trace);
415 }
416 return text;
417 }
418
63c43609
MR
419 @Override
420 public Iterable<TmfAnalysisRequirement> getAnalysisRequirements() {
421 return Collections.EMPTY_SET;
422 }
c068a752 423}
This page took 0.047955 seconds and 5 git commands to generate.