bf1eb976d85a6a0995abd6e7a1ffc52197dd0231
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / project / model / TmfTraceElement.java
1 /*******************************************************************************
2 * Copyright (c) 2010, 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 * Francois Chouinard - Initial API and implementation
11 * Bernd Hufmann - Added supplementary files handling
12 * Geneviève Bastien - Moved supplementary files handling to parent class,
13 * added code to copy trace
14 * Patrick Tasse - Close editors to release resources
15 * Jean-Christian Kouame - added trace properties to be shown into
16 * the properties view
17 * Geneviève Bastien - Moved trace type related methods to parent class
18 *******************************************************************************/
19
20 package org.eclipse.linuxtools.tmf.ui.project.model;
21
22 import java.util.Arrays;
23 import java.util.HashMap;
24 import java.util.LinkedList;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.eclipse.core.resources.IFile;
29 import org.eclipse.core.resources.IFolder;
30 import org.eclipse.core.resources.IResource;
31 import org.eclipse.core.runtime.CoreException;
32 import org.eclipse.core.runtime.IConfigurationElement;
33 import org.eclipse.core.runtime.IPath;
34 import org.eclipse.core.runtime.IProgressMonitor;
35 import org.eclipse.core.runtime.Platform;
36 import org.eclipse.core.runtime.URIUtil;
37 import org.eclipse.linuxtools.internal.tmf.ui.Activator;
38 import org.eclipse.linuxtools.tmf.core.TmfCommonConstants;
39 import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
40 import org.eclipse.linuxtools.tmf.core.parsers.custom.CustomTxtEvent;
41 import org.eclipse.linuxtools.tmf.core.parsers.custom.CustomTxtTrace;
42 import org.eclipse.linuxtools.tmf.core.parsers.custom.CustomTxtTraceDefinition;
43 import org.eclipse.linuxtools.tmf.core.parsers.custom.CustomXmlEvent;
44 import org.eclipse.linuxtools.tmf.core.parsers.custom.CustomXmlTrace;
45 import org.eclipse.linuxtools.tmf.core.parsers.custom.CustomXmlTraceDefinition;
46 import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceType;
47 import org.eclipse.linuxtools.tmf.core.project.model.TraceTypeHelper;
48 import org.eclipse.linuxtools.tmf.core.synchronization.TimestampTransformFactory;
49 import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestampFormat;
50 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
51 import org.eclipse.linuxtools.tmf.core.trace.ITmfTraceProperties;
52 import org.eclipse.linuxtools.tmf.core.trace.TmfTrace;
53 import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
54 import org.eclipse.linuxtools.tmf.ui.editors.TmfEventsEditor;
55 import org.eclipse.linuxtools.tmf.ui.properties.ReadOnlyTextPropertyDescriptor;
56 import org.eclipse.swt.widgets.Display;
57 import org.eclipse.ui.IActionFilter;
58 import org.eclipse.ui.views.properties.IPropertyDescriptor;
59 import org.eclipse.ui.views.properties.IPropertySource2;
60
61 /**
62 * Implementation of trace model element representing a trace. It provides
63 * methods to instantiate <code>ITmfTrace</code> and <code>ITmfEvent</code> as
64 * well as editor ID from the trace type extension definition.
65 *
66 * @version 1.0
67 * @author Francois Chouinard
68 */
69 public class TmfTraceElement extends TmfCommonProjectElement implements IActionFilter, IPropertySource2 {
70
71 // ------------------------------------------------------------------------
72 // Constants
73 // ------------------------------------------------------------------------
74
75 // Other attributes
76 /**
77 * Bundle attribute name
78 */
79 public static final String BUNDLE = "bundle"; //$NON-NLS-1$
80 /**
81 * IsLinked attribute name.
82 */
83 public static final String IS_LINKED = "isLinked"; //$NON-NLS-1$
84
85 // Property View stuff
86 private static final String sfResourcePropertiesCategory = Messages.TmfTraceElement_ResourceProperties;
87 private static final String sfName = Messages.TmfTraceElement_Name;
88 private static final String sfPath = Messages.TmfTraceElement_Path;
89 private static final String sfLocation = Messages.TmfTraceElement_Location;
90 private static final String sfTraceType = Messages.TmfTraceElement_EventType;
91 private static final String sfIsLinked = Messages.TmfTraceElement_IsLinked;
92 private static final String sfSourceLocation = Messages.TmfTraceElement_SourceLocation;
93 private static final String sfTimeOffset = Messages.TmfTraceElement_TimeOffset;
94 private static final String sfTracePropertiesCategory = Messages.TmfTraceElement_TraceProperties;
95
96 private static final ReadOnlyTextPropertyDescriptor sfNameDescriptor = new ReadOnlyTextPropertyDescriptor(sfName, sfName);
97 private static final ReadOnlyTextPropertyDescriptor sfPathDescriptor = new ReadOnlyTextPropertyDescriptor(sfPath, sfPath);
98 private static final ReadOnlyTextPropertyDescriptor sfLocationDescriptor = new ReadOnlyTextPropertyDescriptor(sfLocation, sfLocation);
99 private static final ReadOnlyTextPropertyDescriptor sfTypeDescriptor = new ReadOnlyTextPropertyDescriptor(sfTraceType, sfTraceType);
100 private static final ReadOnlyTextPropertyDescriptor sfIsLinkedDescriptor = new ReadOnlyTextPropertyDescriptor(sfIsLinked, sfIsLinked);
101 private static final ReadOnlyTextPropertyDescriptor sfSourceLocationDescriptor = new ReadOnlyTextPropertyDescriptor(sfSourceLocation, sfSourceLocation);
102 private static final ReadOnlyTextPropertyDescriptor sfTimeOffsetDescriptor = new ReadOnlyTextPropertyDescriptor(sfTimeOffset, sfTimeOffset);
103
104 private static final IPropertyDescriptor[] sfDescriptors = { sfNameDescriptor, sfPathDescriptor, sfLocationDescriptor,
105 sfTypeDescriptor, sfIsLinkedDescriptor, sfSourceLocationDescriptor,
106 sfTimeOffsetDescriptor};
107
108 static {
109 sfNameDescriptor.setCategory(sfResourcePropertiesCategory);
110 sfPathDescriptor.setCategory(sfResourcePropertiesCategory);
111 sfLocationDescriptor.setCategory(sfResourcePropertiesCategory);
112 sfTypeDescriptor.setCategory(sfResourcePropertiesCategory);
113 sfIsLinkedDescriptor.setCategory(sfResourcePropertiesCategory);
114 sfSourceLocationDescriptor.setCategory(sfResourcePropertiesCategory);
115 sfTimeOffsetDescriptor.setCategory(sfResourcePropertiesCategory);
116 }
117
118 private static final TmfTimestampFormat OFFSET_FORMAT = new TmfTimestampFormat("T.SSS SSS SSS s"); //$NON-NLS-1$
119
120 // ------------------------------------------------------------------------
121 // Static initialization
122 // ------------------------------------------------------------------------
123
124 // The mapping of available trace type IDs to their corresponding
125 // configuration element
126 private static final Map<String, IConfigurationElement> sfTraceTypeAttributes = new HashMap<>();
127 private static final Map<String, IConfigurationElement> sfTraceTypeUIAttributes = new HashMap<>();
128 private static final Map<String, IConfigurationElement> sfTraceCategories = new HashMap<>();
129
130 /**
131 * Initialize statically at startup by getting extensions from the platform
132 * extension registry.
133 */
134 public static void init() {
135 /* Read the tmf.core "tracetype" extension point */
136 IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(TmfTraceType.TMF_TRACE_TYPE_ID);
137 for (IConfigurationElement ce : config) {
138 switch (ce.getName()) {
139 case TmfTraceType.TYPE_ELEM:
140 String traceTypeId = ce.getAttribute(TmfTraceType.ID_ATTR);
141 sfTraceTypeAttributes.put(traceTypeId, ce);
142 break;
143 case TmfTraceType.CATEGORY_ELEM:
144 String categoryId = ce.getAttribute(TmfTraceType.ID_ATTR);
145 sfTraceCategories.put(categoryId, ce);
146 break;
147 default:
148 }
149 }
150
151 /*
152 * Read the corresponding tmf.ui "tracetypeui" extension point for this
153 * trace type, if it exists.
154 */
155 config = Platform.getExtensionRegistry().getConfigurationElementsFor(TmfTraceTypeUIUtils.TMF_TRACE_TYPE_UI_ID);
156 for (IConfigurationElement ce : config) {
157 String elemName = ce.getName();
158 if (TmfTraceTypeUIUtils.TYPE_ELEM.equals(elemName)) {
159 String traceType = ce.getAttribute(TmfTraceTypeUIUtils.TRACETYPE_ATTR);
160 sfTraceTypeUIAttributes.put(traceType, ce);
161 }
162 }
163 }
164
165 // ------------------------------------------------------------------------
166 // Constructors
167 // ------------------------------------------------------------------------
168 /**
169 * Constructor. Creates trace model element under the trace folder.
170 *
171 * @param name
172 * The name of trace
173 * @param trace
174 * The trace resource.
175 * @param parent
176 * The parent element (trace folder)
177 */
178 public TmfTraceElement(String name, IResource trace, TmfTraceFolder parent) {
179 super(name, trace, parent);
180 }
181
182 /**
183 * Constructor. Creates trace model element under the experiment folder.
184 *
185 * @param name
186 * The name of trace
187 * @param trace
188 * The trace resource.
189 * @param parent
190 * The parent element (experiment folder)
191 */
192 public TmfTraceElement(String name, IResource trace, TmfExperimentElement parent) {
193 super(name, trace, parent);
194 }
195
196 // ------------------------------------------------------------------------
197 // Operations
198 // ------------------------------------------------------------------------
199
200 /**
201 * Instantiate a <code>ITmfTrace</code> object based on the trace type and
202 * the corresponding extension.
203 *
204 * @return the <code>ITmfTrace</code> or <code>null</code> for an error
205 */
206 @Override
207 public ITmfTrace instantiateTrace() {
208 try {
209
210 // make sure that supplementary folder exists
211 refreshSupplementaryFolder();
212
213 if (getTraceType() != null) {
214 if (getTraceType().startsWith(CustomTxtTrace.class.getCanonicalName())) {
215 for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) {
216 if (getTraceType().equals(CustomTxtTrace.class.getCanonicalName() + ':' + def.categoryName+ ':' + def.definitionName)) {
217 return new CustomTxtTrace(def);
218 }
219 }
220 }
221 if (getTraceType().startsWith(CustomXmlTrace.class.getCanonicalName())) {
222 for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) {
223 if (getTraceType().equals(CustomXmlTrace.class.getCanonicalName() + ':' + def.categoryName+ ':' + def.definitionName)) {
224 return new CustomXmlTrace(def);
225 }
226 }
227 }
228 IConfigurationElement ce = sfTraceTypeAttributes.get(getTraceType());
229 if (ce == null) {
230 return null;
231 }
232 ITmfTrace trace = (ITmfTrace) ce.createExecutableExtension(TmfTraceType.TRACE_TYPE_ATTR);
233 return trace;
234 }
235 } catch (CoreException e) {
236 Activator.getDefault().logError("Error instantiating ITmfTrace object for trace " + getName(), e); //$NON-NLS-1$
237 }
238 return null;
239 }
240
241 /**
242 * Instantiate a <code>ITmfEvent</code> object based on the trace type and
243 * the corresponding extension.
244 *
245 * @return the <code>ITmfEvent</code> or <code>null</code> for an error
246 */
247 public ITmfEvent instantiateEvent() {
248 try {
249 if (getTraceType() != null) {
250 if (getTraceType().startsWith(CustomTxtTrace.class.getCanonicalName())) {
251 for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) {
252 if (getTraceType().equals(CustomTxtTrace.class.getCanonicalName() + ':' + def.categoryName+ ':' + def.definitionName)) {
253 return new CustomTxtEvent(def);
254 }
255 }
256 }
257 if (getTraceType().startsWith(CustomXmlTrace.class.getCanonicalName())) {
258 for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) {
259 if (getTraceType().equals(CustomXmlTrace.class.getCanonicalName() + ':' + def.categoryName+ ':' + def.definitionName)) {
260 return new CustomXmlEvent(def);
261 }
262 }
263 }
264 IConfigurationElement ce = sfTraceTypeAttributes.get(getTraceType());
265 if (ce == null) {
266 return null;
267 }
268 ITmfEvent event = (ITmfEvent) ce.createExecutableExtension(TmfTraceType.EVENT_TYPE_ATTR);
269 return event;
270 }
271 } catch (CoreException e) {
272 Activator.getDefault().logError("Error instantiating ITmfEvent object for trace " + getName(), e); //$NON-NLS-1$
273 }
274 return null;
275 }
276
277 @Override
278 public String getEditorId() {
279 if (getTraceType() != null) {
280 if (getTraceType().startsWith(CustomTxtTrace.class.getCanonicalName())) {
281 return TmfEventsEditor.ID;
282 }
283 if (getTraceType().startsWith(CustomXmlTrace.class.getCanonicalName())) {
284 return TmfEventsEditor.ID;
285 }
286 IConfigurationElement ce = sfTraceTypeUIAttributes.get(getTraceType());
287 if (ce == null) {
288 /* This trace type does not define UI attributes */
289 return null;
290 }
291 IConfigurationElement[] defaultEditorCE = ce.getChildren(TmfTraceTypeUIUtils.DEFAULT_EDITOR_ELEM);
292 if (defaultEditorCE.length == 1) {
293 return defaultEditorCE[0].getAttribute(TmfTraceType.ID_ATTR);
294 }
295 }
296 return null;
297 }
298
299 /**
300 * Returns the file resource used to store bookmarks after creating it if
301 * necessary. If the trace resource is a file, it is returned directly. If
302 * the trace resource is a folder, a linked file is returned. The file will
303 * be created if it does not exist.
304 *
305 * @return the bookmarks file
306 * @throws CoreException
307 * if the bookmarks file cannot be created
308 * @since 2.0
309 */
310 @Override
311 public IFile createBookmarksFile() throws CoreException {
312 IFile file = getBookmarksFile();
313 if (fResource instanceof IFolder) {
314 return createBookmarksFile(getProject().getTracesFolder().getResource(), TmfTrace.class.getCanonicalName());
315 }
316 return file;
317 }
318
319 /**
320 * Returns the file resource used to store bookmarks. The file may not
321 * exist.
322 *
323 * @return the bookmarks file
324 * @since 2.0
325 */
326 @Override
327 public IFile getBookmarksFile() {
328 IFile file = null;
329 if (fResource instanceof IFile) {
330 file = (IFile) fResource;
331 } else if (fResource instanceof IFolder) {
332 final IFolder folder = (IFolder) fResource;
333 file = folder.getFile(getName() + '_');
334 }
335 return file;
336 }
337
338 /**
339 * Returns the <code>TmfTraceElement</code> located under the
340 * <code>TmfTracesFolder</code>.
341 *
342 * @return <code>this</code> if this element is under the
343 * <code>TmfTracesFolder</code> else the corresponding
344 * <code>TmfTraceElement</code> if this element is under
345 * <code>TmfExperimentElement</code>.
346 */
347 public TmfTraceElement getElementUnderTraceFolder() {
348
349 // If trace is under an experiment, return original trace from the
350 // traces folder
351 if (getParent() instanceof TmfExperimentElement) {
352 for (TmfTraceElement aTrace : getProject().getTracesFolder().getTraces()) {
353 if (aTrace.getElementPath().equals(getElementPath())) {
354 return aTrace;
355 }
356 }
357 }
358 return this;
359 }
360
361 @Override
362 public String getTypeName() {
363 return Messages.TmfTraceElement_TypeName;
364 }
365
366 // ------------------------------------------------------------------------
367 // IActionFilter
368 // ------------------------------------------------------------------------
369
370 @Override
371 public boolean testAttribute(Object target, String name, String value) {
372 if (name.equals(IS_LINKED)) {
373 boolean isLinked = getResource().isLinked();
374 return Boolean.toString(isLinked).equals(value);
375 }
376 return false;
377 }
378
379 // ------------------------------------------------------------------------
380 // IPropertySource2
381 // ------------------------------------------------------------------------
382
383 @Override
384 public Object getEditableValue() {
385 return null;
386 }
387
388 /**
389 * Get the trace properties of this traceElement if the corresponding trace
390 * is opened in an editor
391 *
392 * @return a map with the names and values of the trace properties
393 * respectively as keys and values
394 */
395 private Map<String, String> getTraceProperties() {
396 for (ITmfTrace openedTrace : TmfTraceManager.getInstance().getOpenedTraces()) {
397 for (ITmfTrace singleTrace : TmfTraceManager.getTraceSet(openedTrace)) {
398 if (getElementUnderTraceFolder().getResource().equals(singleTrace.getResource())) {
399 if (singleTrace instanceof ITmfTraceProperties) {
400 ITmfTraceProperties traceProperties = (ITmfTraceProperties) singleTrace;
401 return traceProperties.getTraceProperties();
402 }
403 }
404 }
405 }
406 return new HashMap<>();
407 }
408
409 @Override
410 public IPropertyDescriptor[] getPropertyDescriptors() {
411 Map<String, String> traceProperties = getTraceProperties();
412 if (!traceProperties.isEmpty()) {
413 IPropertyDescriptor[] propertyDescriptorArray = new IPropertyDescriptor[traceProperties.size() + sfDescriptors.length];
414 int index = 0;
415 for (Map.Entry<String, String> varName : traceProperties.entrySet()) {
416 ReadOnlyTextPropertyDescriptor descriptor = new ReadOnlyTextPropertyDescriptor(this.getName() + "_" + varName.getKey(), varName.getKey()); //$NON-NLS-1$
417 descriptor.setCategory(sfTracePropertiesCategory);
418 propertyDescriptorArray[index] = descriptor;
419 index++;
420 }
421 for (int i = 0; i < sfDescriptors.length; i++) {
422 propertyDescriptorArray[index] = sfDescriptors[i];
423 index++;
424 }
425 return propertyDescriptorArray;
426 }
427 return Arrays.copyOf(sfDescriptors, sfDescriptors.length);
428 }
429
430 @Override
431 public Object getPropertyValue(Object id) {
432
433 if (sfName.equals(id)) {
434 return getName();
435 }
436
437 if (sfPath.equals(id)) {
438 return getPath().toString();
439 }
440
441 if (sfLocation.equals(id)) {
442 return URIUtil.toUnencodedString(getLocation());
443 }
444
445 if (sfIsLinked.equals(id)) {
446 return Boolean.valueOf(getResource().isLinked()).toString();
447 }
448
449 if (sfSourceLocation.equals(id)) {
450 try {
451 String sourceLocation = getElementUnderTraceFolder().getResource().getPersistentProperty(TmfCommonConstants.SOURCE_LOCATION);
452 if (sourceLocation != null) {
453 return sourceLocation;
454 }
455 } catch (CoreException e) {
456 }
457 return ""; //$NON-NLS-1$
458 }
459
460 if (sfTraceType.equals(id)) {
461 if (getTraceType() != null) {
462 TraceTypeHelper helper = TmfTraceType.getTraceType(getTraceType());
463 if (helper != null) {
464 return helper.getCategoryName() + " : " + helper.getName(); //$NON-NLS-1$
465 }
466 }
467 return ""; //$NON-NLS-1$
468 }
469
470 if (sfTimeOffset.equals(id)) {
471 long offset = TimestampTransformFactory.getTimestampTransform(getElementUnderTraceFolder().getResource()).transform(0);
472 if (offset != 0) {
473 return OFFSET_FORMAT.format(offset);
474 }
475 return ""; //$NON-NLS-1$
476 }
477
478 Map<String, String> traceProperties = getTraceProperties();
479 if (id != null && !traceProperties.isEmpty()) {
480 String key = (String) id;
481 key = key.substring(this.getName().length() + 1); // remove name_
482 String value = traceProperties.get(key);
483 return value;
484 }
485
486 return null;
487 }
488
489 @Override
490 public void resetPropertyValue(Object id) {
491 }
492
493 @Override
494 public void setPropertyValue(Object id, Object value) {
495 }
496
497 @Override
498 public boolean isPropertyResettable(Object id) {
499 return false;
500 }
501
502 @Override
503 public boolean isPropertySet(Object id) {
504 return false;
505 }
506
507 /**
508 * Copy this trace in the trace folder. No other parameters are mentioned so
509 * the trace is copied in this element's project trace folder
510 *
511 * @param newName
512 * The new trace name
513 * @return the new Resource object
514 * @since 2.0
515 */
516 public TmfTraceElement copy(String newName) {
517 TmfTraceFolder folder = (TmfTraceFolder) getParent();
518 IResource res = super.copy(newName, false);
519 for (TmfTraceElement trace : folder.getTraces()) {
520 if (trace.getResource().equals(res)) {
521 return trace;
522 }
523 }
524 return null;
525 }
526
527 /**
528 * Close opened editors associated with this trace.
529 *
530 * @since 2.0
531 */
532 @Override
533 public void closeEditors() {
534 super.closeEditors();
535
536 // Close experiments that contain the trace if open
537 if (getParent() instanceof TmfTraceFolder) {
538 TmfExperimentFolder experimentsFolder = getProject().getExperimentsFolder();
539 for (TmfExperimentElement experiment : experimentsFolder.getExperiments()) {
540 for (TmfTraceElement trace : experiment.getTraces()) {
541 if (trace.getElementPath().equals(getElementPath())) {
542 experiment.closeEditors();
543 break;
544 }
545 }
546 }
547 } else if (getParent() instanceof TmfExperimentElement) {
548 TmfExperimentElement experiment = (TmfExperimentElement) getParent();
549 experiment.closeEditors();
550 }
551 }
552
553 /**
554 * Delete the trace resource, remove it from experiments and delete its
555 * supplementary files
556 *
557 * @param progressMonitor
558 * a progress monitor, or null if progress reporting is not
559 * desired
560 *
561 * @throws CoreException
562 * thrown when IResource.delete fails
563 * @since 2.2
564 */
565 public void delete(IProgressMonitor progressMonitor) throws CoreException {
566 // Close editors in UI Thread
567 Display.getDefault().syncExec(new Runnable() {
568 @Override
569 public void run() {
570 closeEditors();
571 }
572 });
573
574 IPath path = fResource.getLocation();
575 if (path != null) {
576 if (getParent() instanceof TmfTraceFolder) {
577 TmfExperimentFolder experimentFolder = getProject().getExperimentsFolder();
578
579 // Propagate the removal to traces
580 for (TmfExperimentElement experiment : experimentFolder.getExperiments()) {
581 List<TmfTraceElement> toRemove = new LinkedList<>();
582 for (TmfTraceElement trace : experiment.getTraces()) {
583 if (trace.getElementPath().equals(getElementPath())) {
584 toRemove.add(trace);
585 }
586 }
587 for (TmfTraceElement child : toRemove) {
588 experiment.removeTrace(child);
589 }
590 }
591
592 // Delete supplementary files
593 deleteSupplementaryFolder();
594
595 } else if (getParent() instanceof TmfExperimentElement) {
596 TmfExperimentElement experimentElement = (TmfExperimentElement) getParent();
597 experimentElement.removeTrace(this);
598 }
599 }
600
601 // Finally, delete the trace
602 fResource.delete(true, progressMonitor);
603 }
604
605 }
This page took 0.044071 seconds and 4 git commands to generate.