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