tmf: Move TmfExperiment to its own package
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / project / model / TmfOpenTraceHelper.java
1 /**********************************************************************
2 * Copyright (c) 2013, 2014 Ericsson, É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 * Matthew Khouzam - Initial API and implementation
11 * Patrick Tasse - Update open trace and add open experiment
12 * Geneviève Bastien - Merge methods to open trace and experiments
13 * Bernd Hufmann - Updated handling of directory traces
14 **********************************************************************/
15
16 package org.eclipse.tracecompass.tmf.ui.project.model;
17
18 import java.io.File;
19 import java.util.List;
20
21 import org.eclipse.core.resources.IFile;
22 import org.eclipse.core.resources.IFolder;
23 import org.eclipse.core.resources.IResource;
24 import org.eclipse.core.runtime.CoreException;
25 import org.eclipse.core.runtime.IPath;
26 import org.eclipse.core.runtime.IStatus;
27 import org.eclipse.core.runtime.Path;
28 import org.eclipse.core.runtime.Status;
29 import org.eclipse.core.runtime.URIUtil;
30 import org.eclipse.jface.util.OpenStrategy;
31 import org.eclipse.osgi.util.NLS;
32 import org.eclipse.swt.widgets.Display;
33 import org.eclipse.swt.widgets.MessageBox;
34 import org.eclipse.swt.widgets.Shell;
35 import org.eclipse.tracecompass.internal.tmf.ui.Activator;
36 import org.eclipse.tracecompass.internal.tmf.ui.project.model.TmfImportHelper;
37 import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
38 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
39 import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException;
40 import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceImportException;
41 import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
42 import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
43 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
44 import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
45 import org.eclipse.tracecompass.tmf.ui.editors.TmfEditorInput;
46 import org.eclipse.tracecompass.tmf.ui.editors.TmfEventsEditor;
47 import org.eclipse.ui.IEditorInput;
48 import org.eclipse.ui.IEditorPart;
49 import org.eclipse.ui.IEditorReference;
50 import org.eclipse.ui.IReusableEditor;
51 import org.eclipse.ui.IWorkbench;
52 import org.eclipse.ui.IWorkbenchPage;
53 import org.eclipse.ui.PartInitException;
54 import org.eclipse.ui.PlatformUI;
55 import org.eclipse.ui.ide.IDE;
56 import org.eclipse.ui.part.FileEditorInput;
57
58 /**
59 * Open trace helper
60 *
61 * Helper class for opening trace resources and loading them to a tracing
62 * project.
63 *
64 * @author Matthew Khouzam
65 * @since 2.1
66 */
67 public class TmfOpenTraceHelper {
68
69 private TmfOpenTraceHelper() {
70 }
71
72 private static final String ENDL = System.getProperty("line.separator"); //$NON-NLS-1$
73
74 /**
75 * Opens a trace from a path while importing it to the destination folder.
76 * The trace is linked as a resource.
77 *
78 * @param destinationFolder
79 * The destination trace folder
80 * @param path
81 * the file to import
82 * @param shell
83 * the shell to use for dialogs
84 * @return IStatus OK if successful
85 * @throws CoreException
86 * core exceptions if something is not well set up in the back
87 * end
88 * @since 3.0
89 */
90 public static IStatus openTraceFromPath(TmfTraceFolder destinationFolder, String path, Shell shell) throws CoreException {
91 return openTraceFromPath(destinationFolder, path, shell, null);
92 }
93
94 /**
95 * Opens a trace from a path while importing it to the destination folder.
96 * The trace is linked as a resource.
97 *
98 * @param destinationFolder
99 * The destination trace folder
100 * @param path
101 * the file to import
102 * @param shell
103 * the shell to use for dialogs
104 * @param tracetypeHint
105 * The trace type id, can be null
106 * @return IStatus OK if successful
107 * @throws CoreException
108 * core exceptions if something is not well set up in the back
109 * end
110 *
111 * @since 3.0
112 */
113 public static IStatus openTraceFromPath(TmfTraceFolder destinationFolder, String path, Shell shell, String tracetypeHint) throws CoreException {
114 final String pathToUse = checkTracePath(path);
115 TraceTypeHelper traceTypeToSet = null;
116 try {
117 traceTypeToSet = TmfTraceTypeUIUtils.selectTraceType(pathToUse, null, tracetypeHint);
118 } catch (TmfTraceImportException e) {
119 MessageBox mb = new MessageBox(shell);
120 mb.setMessage(e.getMessage());
121 mb.open();
122 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage());
123 }
124
125 IFolder folder = destinationFolder.getResource();
126 String traceName = getTraceName(pathToUse, folder);
127 if (traceExists(pathToUse, folder)) {
128 return openTraceFromFolder(destinationFolder, traceName);
129 }
130 final IPath pathString = Path.fromOSString(pathToUse);
131 IResource linkedTrace = TmfImportHelper.createLink(folder, pathString, traceName);
132
133 if (linkedTrace == null || !linkedTrace.exists()) {
134 return new Status(IStatus.ERROR, Activator.PLUGIN_ID,
135 Messages.TmfOpenTraceHelper_LinkFailed);
136 }
137
138 String sourceLocation = URIUtil.toUnencodedString(pathString.toFile().toURI());
139 linkedTrace.setPersistentProperty(TmfCommonConstants.SOURCE_LOCATION, sourceLocation);
140
141 // No trace type was determined.
142 if (traceTypeToSet == null) {
143 return Status.OK_STATUS;
144 }
145
146 IStatus ret = TmfTraceTypeUIUtils.setTraceType(linkedTrace, traceTypeToSet);
147 if (ret.isOK()) {
148 ret = openTraceFromFolder(destinationFolder, traceName);
149 }
150 return ret;
151 }
152
153 /**
154 * Checks whether the parent or grandparent of given path to a file is a
155 * valid directory trace. If it is a directory trace then return the parent
156 * or grandparent path.
157 *
158 * @param path
159 * the path to check
160 * @return path to use for trace type validation.
161 */
162 private static String checkTracePath(String path) {
163 File file = new File(path);
164 if (file.exists() && !file.isDirectory()) {
165 // First check parent
166 File parent = file.getParentFile();
167 String pathToUse = parent.getAbsolutePath();
168 if (TmfTraceType.isDirectoryTrace(pathToUse)) {
169 return pathToUse;
170 }
171 // Second check grandparent
172 File grandParent = parent.getParentFile();
173 if (grandParent != null) {
174 pathToUse = grandParent.getAbsolutePath();
175 if (TmfTraceType.isDirectoryTrace(pathToUse)) {
176 return pathToUse;
177 }
178 }
179 }
180 return path;
181 }
182
183 private static boolean traceExists(String path, IFolder folder) {
184 String val = getTraceName(path, folder);
185 return (folder.findMember(val) != null);
186 }
187
188 private static boolean isWrongMember(IFolder folder, String name, final File traceFile) {
189 final IResource candidate = folder.findMember(name);
190 if (candidate != null) {
191 final IPath rawLocation = candidate.getRawLocation();
192 final File file = rawLocation.toFile();
193 return !file.equals(traceFile);
194 }
195 return false;
196 }
197
198 /**
199 * Gets the display name, either "filename" or "filename(n)" if there is
200 * already a filename existing where n is the next unused integer starting
201 * from 2
202 *
203 * @param path
204 * the file path
205 * @param folder
206 * the folder to import to
207 * @return the filename
208 */
209 private static String getTraceName(String path, IFolder folder) {
210 String name;
211 final File traceFile = new File(path);
212 name = traceFile.getName();
213 for (int i = 2; isWrongMember(folder, name, traceFile); i++) {
214 name = traceFile.getName() + '(' + i + ')';
215 }
216 return name;
217 }
218
219 /**
220 * Open a trace from a trace folder
221 *
222 * @param destinationFolder
223 * The destination trace folder
224 * @param traceName
225 * the trace name
226 * @return success or error
227 * @since 3.0
228 */
229 private static IStatus openTraceFromFolder(TmfTraceFolder destinationFolder, String traceName) {
230 final List<ITmfProjectModelElement> elements = destinationFolder.getChildren();
231 TmfTraceElement traceElement = null;
232 for (ITmfProjectModelElement element : elements) {
233 if (element instanceof TmfTraceElement && element.getName().equals(traceName)) {
234 traceElement = (TmfTraceElement) element;
235 }
236 }
237 if (traceElement == null) {
238 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, NLS.bind(Messages.TmfOpenTraceHelper_TraceNotFound, traceName));
239 }
240 openTraceFromElement(traceElement);
241 return Status.OK_STATUS;
242 }
243
244 private static ITmfTrace openTraceElement(final TmfTraceElement traceElement) {
245 final ITmfTrace trace = traceElement.instantiateTrace();
246 final ITmfEvent traceEvent = traceElement.instantiateEvent();
247 if ((trace == null) || (traceEvent == null)) {
248 TraceUtils.displayErrorMsg(NLS.bind(Messages.TmfOpenTraceHelper_OpenElement, traceElement.getTypeName()),
249 Messages.TmfOpenTraceHelper_NoTraceType);
250 if (trace != null) {
251 trace.dispose();
252 }
253 return null;
254 }
255
256 try {
257 trace.initTrace(traceElement.getResource(), traceElement.getResource().getLocation().toOSString(), traceEvent.getClass(), traceElement.getElementPath());
258 } catch (final TmfTraceException e) {
259 TraceUtils.displayErrorMsg(NLS.bind(Messages.TmfOpenTraceHelper_OpenElement, traceElement.getTypeName()),
260 Messages.TmfOpenTraceHelper_InitError + ENDL + ENDL + e);
261 trace.dispose();
262 return null;
263 }
264 return trace;
265 }
266
267 private static ITmfTrace openExperimentElement(final TmfExperimentElement experimentElement) {
268 /* Experiment element now has an experiment type associated with it */
269 final TmfExperiment experiment = experimentElement.instantiateTrace();
270 if (experiment == null) {
271 TraceUtils.displayErrorMsg(NLS.bind(Messages.TmfOpenTraceHelper_OpenElement, experimentElement.getTypeName()),
272 NLS.bind(Messages.TmfOpenTraceHelper_NoTraceOrExperimentType, experimentElement.getTypeName()));
273 return null;
274 }
275
276 // Instantiate the experiment's traces
277 final List<TmfTraceElement> traceEntries = experimentElement.getTraces();
278 int cacheSize = Integer.MAX_VALUE;
279 final ITmfTrace[] traces = new ITmfTrace[traceEntries.size()];
280 for (int i = 0; i < traceEntries.size(); i++) {
281 TmfTraceElement element = traceEntries.get(i);
282
283 // Since trace is under an experiment, use the original trace from
284 // the traces folder
285 element = element.getElementUnderTraceFolder();
286
287 ITmfTrace trace = openTraceElement(element);
288
289 if (trace == null) {
290 for (int j = 0; j < i; j++) {
291 traces[j].dispose();
292 }
293 return null;
294 }
295 cacheSize = Math.min(cacheSize, trace.getCacheSize());
296
297 traces[i] = trace;
298 }
299
300 // Create the experiment
301 experiment.initExperiment(ITmfEvent.class, experimentElement.getName(), traces, cacheSize, experimentElement.getResource());
302
303 return experiment;
304 }
305
306 private static ITmfTrace openProjectElement(final TmfCommonProjectElement element) {
307 ITmfTrace trace = null;
308 if (element instanceof TmfTraceElement) {
309 trace = openTraceElement((TmfTraceElement) element);
310 } else if (element instanceof TmfExperimentElement) {
311 trace = openExperimentElement((TmfExperimentElement) element);
312 }
313 return trace;
314 }
315
316 /**
317 * Open a trace (or experiment) from a project element. If the trace is already opened, its
318 * editor is activated and brought to top.
319 *
320 * @param traceElement
321 * the {@link TmfTraceElement} to open
322 * @since 3.0
323 */
324 public static void openTraceFromElement(final TmfCommonProjectElement traceElement) {
325
326 final IFile file;
327 try {
328 file = traceElement.createBookmarksFile();
329 } catch (final CoreException e) {
330 Activator.getDefault().logError(NLS.bind(Messages.TmfOpenTraceHelper_ErrorOpeningElement, traceElement.getTypeName()) + ' ' + traceElement.getName());
331 TraceUtils.displayErrorMsg(NLS.bind(Messages.TmfOpenTraceHelper_OpenElement, traceElement.getTypeName()),
332 NLS.bind(Messages.TmfOpenTraceHelper_ErrorElement, traceElement.getTypeName()) + ENDL + ENDL + e.getMessage());
333 return;
334 }
335
336 final IWorkbench wb = PlatformUI.getWorkbench();
337 final IWorkbenchPage activePage = wb.getActiveWorkbenchWindow().getActivePage();
338 final IEditorPart editor = findEditor(new FileEditorInput(file), true);
339 if (editor != null) {
340 activePage.activate(editor);
341 return;
342 }
343
344 // If a trace type is not set then delegate it to the eclipse platform
345 if ((traceElement instanceof TmfTraceElement) && (traceElement.getResource() instanceof IFile) && (traceElement.getTraceType() == null)) {
346 try {
347 boolean activate = OpenStrategy.activateOnOpen();
348 // only local open is supported
349 IDE.openEditor(activePage, file, activate);
350 } catch (PartInitException e) {
351 TraceUtils.displayErrorMsg(NLS.bind(Messages.TmfOpenTraceHelper_OpenElement, traceElement.getTypeName()),
352 NLS.bind(Messages.TmfOpenTraceHelper_ErrorOpeningElement, traceElement.getElementPath()) + ENDL + ENDL + e.getMessage());
353 }
354 return;
355 }
356
357 Thread thread = new Thread() {
358 @Override
359 public void run() {
360 final ITmfTrace trace = openProjectElement(traceElement);
361
362 if (trace == null) {
363 return;
364 }
365
366 // Get the editor id from the extension point
367 String traceEditorId = traceElement.getEditorId();
368 final String editorId = (traceEditorId != null) ? traceEditorId : TmfEventsEditor.ID;
369 final IEditorInput editorInput = new TmfEditorInput(file, trace);
370
371 Display.getDefault().asyncExec(new Runnable() {
372 @Override
373 public void run() {
374 try {
375 activePage.openEditor(editorInput, editorId);
376 IDE.setDefaultEditor(file, editorId);
377 // editor should dispose the trace on close
378 } catch (final PartInitException e) {
379 TraceUtils.displayErrorMsg(NLS.bind(Messages.TmfOpenTraceHelper_OpenElement, traceElement.getTypeName()),
380 NLS.bind(Messages.TmfOpenTraceHelper_ErrorOpeningElement, traceElement.getTypeName()) + ENDL + ENDL + e.getMessage());
381 Activator.getDefault().logError(NLS.bind(Messages.TmfOpenTraceHelper_ErrorOpeningElement, traceElement.getTypeName()) + ' ' + traceElement.getName());
382 trace.dispose();
383 }
384 }
385 });
386 }
387 };
388 thread.start();
389 }
390
391 /**
392 * Returns the editor with the specified input. Returns null if there is no
393 * opened editor with that input. If restore is requested, the method finds
394 * and returns the editor even if it is not restored yet after a restart.
395 *
396 * @param input
397 * the editor input
398 * @param restore
399 * true if the editor should be restored
400 * @return an editor with input equals to <code>input</code>
401 */
402 private static IEditorPart findEditor(IEditorInput input, boolean restore) {
403 final IWorkbench wb = PlatformUI.getWorkbench();
404 final IWorkbenchPage activePage = wb.getActiveWorkbenchWindow().getActivePage();
405 for (IEditorReference editorReference : activePage.getEditorReferences()) {
406 try {
407 IEditorInput editorInput = editorReference.getEditorInput();
408 if (editorInput.equals(input)) {
409 return editorReference.getEditor(restore);
410 }
411 } catch (PartInitException e) {
412 }
413 }
414 return null;
415 }
416
417 /**
418 * Reopen a trace or experiment from a project element in the provided
419 * editor
420 *
421 * @param traceElement
422 * the {@link TmfTraceElement} to open
423 * @param editor
424 * the reusable editor
425 * @since 3.0
426 */
427 public static void reopenTraceFromElement(final TmfCommonProjectElement traceElement, final IReusableEditor editor) {
428
429 final IFile file;
430 try {
431 file = traceElement.createBookmarksFile();
432 } catch (final CoreException e) {
433 Activator.getDefault().logError(NLS.bind(Messages.TmfOpenTraceHelper_ErrorOpeningElement, traceElement.getTypeName()) + ' ' + traceElement.getName());
434 TraceUtils.displayErrorMsg(NLS.bind(Messages.TmfOpenTraceHelper_OpenElement, traceElement.getTypeName()),
435 NLS.bind(Messages.TmfOpenTraceHelper_ErrorElement, traceElement.getTypeName()) + ENDL + ENDL + e.getMessage());
436 return;
437 }
438
439 Thread thread = new Thread() {
440 @Override
441 public void run() {
442
443 final ITmfTrace trace = openProjectElement(traceElement);
444 if (trace == null) {
445 return;
446 }
447
448 final IEditorInput editorInput = new TmfEditorInput(file, trace);
449
450 Display.getDefault().asyncExec(new Runnable() {
451 @Override
452 public void run() {
453 final IWorkbench wb = PlatformUI.getWorkbench();
454 final IWorkbenchPage activePage = wb.getActiveWorkbenchWindow().getActivePage();
455 activePage.reuseEditor(editor, editorInput);
456 activePage.activate(editor);
457 }
458 });
459 }
460 };
461 thread.start();
462 }
463
464 }
This page took 0.040374 seconds and 5 git commands to generate.