1 /*******************************************************************************
2 * Copyright (c) 2010, 2013 Ericsson, École Polytechnique de Montréal
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
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 *******************************************************************************/
17 package org
.eclipse
.linuxtools
.tmf
.ui
.project
.model
;
19 import java
.io
.ByteArrayInputStream
;
20 import java
.io
.InputStream
;
21 import java
.util
.Arrays
;
22 import java
.util
.HashMap
;
25 import org
.eclipse
.core
.resources
.IFile
;
26 import org
.eclipse
.core
.resources
.IFolder
;
27 import org
.eclipse
.core
.resources
.IResource
;
28 import org
.eclipse
.core
.runtime
.CoreException
;
29 import org
.eclipse
.core
.runtime
.IConfigurationElement
;
30 import org
.eclipse
.core
.runtime
.Platform
;
31 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.Activator
;
32 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.parsers
.custom
.CustomTxtEvent
;
33 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.parsers
.custom
.CustomTxtTrace
;
34 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.parsers
.custom
.CustomTxtTraceDefinition
;
35 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.parsers
.custom
.CustomXmlEvent
;
36 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.parsers
.custom
.CustomXmlTrace
;
37 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.parsers
.custom
.CustomXmlTraceDefinition
;
38 import org
.eclipse
.linuxtools
.tmf
.core
.TmfCommonConstants
;
39 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfEvent
;
40 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
41 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfTrace
;
42 import org
.eclipse
.linuxtools
.tmf
.core
.util
.ReadOnlyTextPropertyDescriptor
;
43 import org
.eclipse
.linuxtools
.tmf
.ui
.editors
.TmfEventsEditor
;
44 import org
.eclipse
.ui
.IActionFilter
;
45 import org
.eclipse
.ui
.IEditorReference
;
46 import org
.eclipse
.ui
.IWorkbench
;
47 import org
.eclipse
.ui
.IWorkbenchPage
;
48 import org
.eclipse
.ui
.IWorkbenchWindow
;
49 import org
.eclipse
.ui
.PartInitException
;
50 import org
.eclipse
.ui
.PlatformUI
;
51 import org
.eclipse
.ui
.part
.FileEditorInput
;
52 import org
.eclipse
.ui
.views
.properties
.IPropertyDescriptor
;
53 import org
.eclipse
.ui
.views
.properties
.IPropertySource2
;
56 * Implementation of trace model element representing a trace. It provides
57 * methods to instantiate <code>ITmfTrace</code> and <code>ITmfEvent</code> as
58 * well as editor ID from the trace type extension definition.
61 * @author Francois Chouinard
63 public class TmfTraceElement
extends TmfWithFolderElement
implements IActionFilter
, IPropertySource2
{
65 // ------------------------------------------------------------------------
67 // ------------------------------------------------------------------------
71 * Bundle attribute name
73 public static final String BUNDLE
= "bundle"; //$NON-NLS-1$
75 * IsLinked attribute name.
77 public static final String IS_LINKED
= "isLinked"; //$NON-NLS-1$
79 // Property View stuff
80 private static final String sfInfoCategory
= "Info"; //$NON-NLS-1$
81 private static final String sfName
= "name"; //$NON-NLS-1$
82 private static final String sfPath
= "path"; //$NON-NLS-1$
83 private static final String sfLocation
= "location"; //$NON-NLS-1$
84 private static final String sfEventType
= "type"; //$NON-NLS-1$
85 private static final String sfIsLinked
= "linked"; //$NON-NLS-1$
87 private static final ReadOnlyTextPropertyDescriptor sfNameDescriptor
= new ReadOnlyTextPropertyDescriptor(sfName
, sfName
);
88 private static final ReadOnlyTextPropertyDescriptor sfPathDescriptor
= new ReadOnlyTextPropertyDescriptor(sfPath
, sfPath
);
89 private static final ReadOnlyTextPropertyDescriptor sfLocationDescriptor
= new ReadOnlyTextPropertyDescriptor(sfLocation
, sfLocation
);
90 private static final ReadOnlyTextPropertyDescriptor sfTypeDescriptor
= new ReadOnlyTextPropertyDescriptor(sfEventType
, sfEventType
);
91 private static final ReadOnlyTextPropertyDescriptor sfIsLinkedDescriptor
= new ReadOnlyTextPropertyDescriptor(sfIsLinked
, sfIsLinked
);
93 private static final IPropertyDescriptor
[] sfDescriptors
= { sfNameDescriptor
, sfPathDescriptor
, sfLocationDescriptor
,
94 sfTypeDescriptor
, sfIsLinkedDescriptor
};
97 sfNameDescriptor
.setCategory(sfInfoCategory
);
98 sfPathDescriptor
.setCategory(sfInfoCategory
);
99 sfLocationDescriptor
.setCategory(sfInfoCategory
);
100 sfTypeDescriptor
.setCategory(sfInfoCategory
);
101 sfIsLinkedDescriptor
.setCategory(sfInfoCategory
);
104 private static final String BOOKMARKS_HIDDEN_FILE
= ".bookmarks"; //$NON-NLS-1$
106 // ------------------------------------------------------------------------
108 // ------------------------------------------------------------------------
110 // This trace type ID as defined in plugin.xml
111 private String fTraceTypeId
= null;
113 // ------------------------------------------------------------------------
114 // Static initialization
115 // ------------------------------------------------------------------------
117 // The mapping of available trace type IDs to their corresponding
118 // configuration element
119 private static final Map
<String
, IConfigurationElement
> sfTraceTypeAttributes
= new HashMap
<String
, IConfigurationElement
>();
120 private static final Map
<String
, IConfigurationElement
> sfTraceCategories
= new HashMap
<String
, IConfigurationElement
>();
123 * Initialize statically at startup by getting extensions from the platform
124 * extension registry.
126 public static void init() {
127 IConfigurationElement
[] config
= Platform
.getExtensionRegistry().getConfigurationElementsFor(TmfTraceType
.TMF_TRACE_TYPE_ID
);
128 for (IConfigurationElement ce
: config
) {
129 String elementName
= ce
.getName();
130 if (elementName
.equals(TmfTraceType
.TYPE_ELEM
)) {
131 String traceTypeId
= ce
.getAttribute(TmfTraceType
.ID_ATTR
);
132 sfTraceTypeAttributes
.put(traceTypeId
, ce
);
133 } else if (elementName
.equals(TmfTraceType
.CATEGORY_ELEM
)) {
134 String categoryId
= ce
.getAttribute(TmfTraceType
.ID_ATTR
);
135 sfTraceCategories
.put(categoryId
, ce
);
140 // ------------------------------------------------------------------------
142 // ------------------------------------------------------------------------
144 * Constructor. Creates trace model element under the trace folder.
149 * The trace resource.
151 * The parent element (trace folder)
153 public TmfTraceElement(String name
, IResource trace
, TmfTraceFolder parent
) {
154 this(name
, trace
, (TmfProjectModelElement
) parent
);
158 * Constructor. Creates trace model element under the experiment folder.
163 * The trace resource.
165 * The parent element (experiment folder)
167 public TmfTraceElement(String name
, IResource trace
, TmfExperimentElement parent
) {
168 this(name
, trace
, (TmfProjectModelElement
) parent
);
171 private TmfTraceElement(String name
, IResource trace
, TmfProjectModelElement parent
) {
172 super(name
, trace
, parent
);
173 parent
.addChild(this);
177 // ------------------------------------------------------------------------
179 // ------------------------------------------------------------------------
181 * Returns the trace type ID.
183 * @return trace type ID.
185 public String
getTraceType() {
190 * Refreshes the trace type filed by reading the trace type persistent
191 * property of the resource referenece.
193 public void refreshTraceType() {
195 fTraceTypeId
= getResource().getPersistentProperty(TmfCommonConstants
.TRACETYPE
);
196 } catch (CoreException e
) {
197 Activator
.getDefault().logError("Error refreshing trace type pesistent property for trace " + getName(), e
); //$NON-NLS-1$
202 * Instantiate a <code>ITmfTrace</code> object based on the trace type and
203 * the corresponding extension.
205 * @return the <code>ITmfTrace</code> or <code>null</code> for an error
207 public ITmfTrace
instantiateTrace() {
210 // make sure that supplementary folder exists
211 refreshSupplementaryFolder();
213 if (fTraceTypeId
!= null) {
214 if (fTraceTypeId
.startsWith(CustomTxtTrace
.class.getCanonicalName())) {
215 for (CustomTxtTraceDefinition def
: CustomTxtTraceDefinition
.loadAll()) {
216 if (fTraceTypeId
.equals(CustomTxtTrace
.class.getCanonicalName() + ":" + def
.definitionName
)) { //$NON-NLS-1$
217 return new CustomTxtTrace(def
);
221 if (fTraceTypeId
.startsWith(CustomXmlTrace
.class.getCanonicalName())) {
222 for (CustomXmlTraceDefinition def
: CustomXmlTraceDefinition
.loadAll()) {
223 if (fTraceTypeId
.equals(CustomXmlTrace
.class.getCanonicalName() + ":" + def
.definitionName
)) { //$NON-NLS-1$
224 return new CustomXmlTrace(def
);
228 IConfigurationElement ce
= sfTraceTypeAttributes
.get(fTraceTypeId
);
232 ITmfTrace trace
= (ITmfTrace
) ce
.createExecutableExtension(TmfTraceType
.TRACE_TYPE_ATTR
);
235 } catch (CoreException e
) {
236 Activator
.getDefault().logError("Error instantiating ITmfTrace object for trace " + getName(), e
); //$NON-NLS-1$
242 * Instantiate a <code>ITmfEvent</code> object based on the trace type and
243 * the corresponding extension.
245 * @return the <code>ITmfEvent</code> or <code>null</code> for an error
247 public ITmfEvent
instantiateEvent() {
249 if (fTraceTypeId
!= null) {
250 if (fTraceTypeId
.startsWith(CustomTxtTrace
.class.getCanonicalName())) {
251 for (CustomTxtTraceDefinition def
: CustomTxtTraceDefinition
.loadAll()) {
252 if (fTraceTypeId
.equals(CustomTxtTrace
.class.getCanonicalName() + ":" + def
.definitionName
)) { //$NON-NLS-1$
253 return new CustomTxtEvent(def
);
257 if (fTraceTypeId
.startsWith(CustomXmlTrace
.class.getCanonicalName())) {
258 for (CustomXmlTraceDefinition def
: CustomXmlTraceDefinition
.loadAll()) {
259 if (fTraceTypeId
.equals(CustomXmlTrace
.class.getCanonicalName() + ":" + def
.definitionName
)) { //$NON-NLS-1$
260 return new CustomXmlEvent(def
);
264 IConfigurationElement ce
= sfTraceTypeAttributes
.get(fTraceTypeId
);
268 ITmfEvent event
= (ITmfEvent
) ce
.createExecutableExtension(TmfTraceType
.EVENT_TYPE_ATTR
);
271 } catch (CoreException e
) {
272 Activator
.getDefault().logError("Error instantiating ITmfEvent object for trace " + getName(), e
); //$NON-NLS-1$
278 * Returns the optional editor ID from the trace type extension.
280 * @return the editor ID or <code>null</code> if not defined.
282 public String
getEditorId() {
283 if (fTraceTypeId
!= null) {
284 if (fTraceTypeId
.startsWith(CustomTxtTrace
.class.getCanonicalName())) {
285 return TmfEventsEditor
.ID
;
287 if (fTraceTypeId
.startsWith(CustomXmlTrace
.class.getCanonicalName())) {
288 return TmfEventsEditor
.ID
;
290 IConfigurationElement ce
= sfTraceTypeAttributes
.get(fTraceTypeId
);
291 IConfigurationElement
[] defaultEditorCE
= ce
.getChildren(TmfTraceType
.DEFAULT_EDITOR_ELEM
);
292 if (defaultEditorCE
.length
== 1) {
293 return defaultEditorCE
[0].getAttribute(TmfTraceType
.ID_ATTR
);
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.
305 * @return the bookmarks file
306 * @throws CoreException
307 * if the bookmarks file cannot be created
310 public IFile
createBookmarksFile() throws CoreException
{
311 IFile file
= getBookmarksFile();
312 if (fResource
instanceof IFolder
) {
313 if (!file
.exists()) {
314 final IFile bookmarksFile
= getProject().getTracesFolder().getResource().getFile(BOOKMARKS_HIDDEN_FILE
);
315 if (!bookmarksFile
.exists()) {
316 final InputStream source
= new ByteArrayInputStream(new byte[0]);
317 bookmarksFile
.create(source
, true, null);
319 bookmarksFile
.setHidden(true);
320 file
.createLink(bookmarksFile
.getLocation(), IResource
.REPLACE
, null);
321 file
.setHidden(true);
322 file
.setPersistentProperty(TmfCommonConstants
.TRACETYPE
, TmfTrace
.class.getCanonicalName());
329 * Returns the file resource used to store bookmarks. The file may not
332 * @return the bookmarks file
335 public IFile
getBookmarksFile() {
337 if (fResource
instanceof IFile
) {
338 file
= (IFile
) fResource
;
339 } else if (fResource
instanceof IFolder
) {
340 final IFolder folder
= (IFolder
) fResource
;
341 file
= folder
.getFile(getName() + '_');
347 * Returns the <code>TmfTraceElement</code> located under the
348 * <code>TmfTracesFolder</code>.
350 * @return <code>this</code> if this element is under the
351 * <code>TmfTracesFolder</code> else the corresponding
352 * <code>TmfTraceElement</code> if this element is under
353 * <code>TmfExperimentElement</code>.
355 public TmfTraceElement
getElementUnderTraceFolder() {
357 // If trace is under an experiment, return original trace from the
359 if (getParent() instanceof TmfExperimentElement
) {
360 for (TmfTraceElement aTrace
: getProject().getTracesFolder().getTraces()) {
361 if (aTrace
.getName().equals(getName())) {
369 // ------------------------------------------------------------------------
371 // ------------------------------------------------------------------------
374 public boolean testAttribute(Object target
, String name
, String value
) {
375 if (name
.equals(IS_LINKED
)) {
376 boolean isLinked
= getResource().isLinked();
377 return Boolean
.toString(isLinked
).equals(value
);
382 // ------------------------------------------------------------------------
384 // ------------------------------------------------------------------------
387 public TmfProjectElement
getProject() {
388 if (getParent() instanceof TmfTraceFolder
) {
389 TmfTraceFolder folder
= (TmfTraceFolder
) getParent();
390 TmfProjectElement project
= (TmfProjectElement
) folder
.getParent();
393 if (getParent() instanceof TmfExperimentElement
) {
394 TmfExperimentElement experiment
= (TmfExperimentElement
) getParent();
395 TmfExperimentFolder folder
= (TmfExperimentFolder
) experiment
.getParent();
396 TmfProjectElement project
= (TmfProjectElement
) folder
.getParent();
402 // ------------------------------------------------------------------------
404 // ------------------------------------------------------------------------
407 public Object
getEditableValue() {
412 public IPropertyDescriptor
[] getPropertyDescriptors() {
413 return Arrays
.copyOf(sfDescriptors
, sfDescriptors
.length
);
417 public Object
getPropertyValue(Object id
) {
419 if (sfName
.equals(id
)) {
423 if (sfPath
.equals(id
)) {
424 return getPath().toString();
427 if (sfLocation
.equals(id
)) {
428 return getLocation().toString();
431 if (sfIsLinked
.equals(id
)) {
432 return Boolean
.valueOf(getResource().isLinked()).toString();
435 if (sfEventType
.equals(id
)) {
436 if (fTraceTypeId
!= null) {
437 IConfigurationElement ce
= sfTraceTypeAttributes
.get(fTraceTypeId
);
438 return (ce
!= null) ?
(getCategory(ce
) + " : " + ce
.getAttribute(TmfTraceType
.NAME_ATTR
)) : ""; //$NON-NLS-1$ //$NON-NLS-2$
445 private static String
getCategory(IConfigurationElement ce
) {
446 String categoryId
= ce
.getAttribute(TmfTraceType
.CATEGORY_ATTR
);
447 if (categoryId
!= null) {
448 IConfigurationElement category
= sfTraceCategories
.get(categoryId
);
449 if (category
!= null) {
450 return category
.getAttribute(TmfTraceType
.NAME_ATTR
);
453 return "[no category]"; //$NON-NLS-1$
457 public void resetPropertyValue(Object id
) {
461 public void setPropertyValue(Object id
, Object value
) {
465 public boolean isPropertyResettable(Object id
) {
470 public boolean isPropertySet(Object id
) {
475 * Copy this trace in the trace folder. No other parameters are mentioned so
476 * the trace is copied in this element's project trace folder
480 * @return the new Resource object
483 public TmfTraceElement
copy(String string
) {
484 TmfTraceFolder folder
= this.getProject().getTracesFolder();
485 IResource res
= super.copy(string
, false);
486 return new TmfTraceElement(string
, res
, folder
);
490 * Close opened editors associated with this trace.
493 public void closeEditors() {
494 // Close the trace if open
495 IFile file
= getBookmarksFile();
496 FileEditorInput input
= new FileEditorInput(file
);
497 IWorkbench wb
= PlatformUI
.getWorkbench();
498 for (IWorkbenchWindow wbWindow
: wb
.getWorkbenchWindows()) {
499 for (IWorkbenchPage wbPage
: wbWindow
.getPages()) {
500 for (IEditorReference editorReference
: wbPage
.getEditorReferences()) {
502 if (editorReference
.getEditorInput().equals(input
)) {
503 wbPage
.closeEditor(editorReference
.getEditor(false), false);
505 } catch (PartInitException e
) {
506 Activator
.getDefault().logError("Error closing editor for trace " + getName(), e
); //$NON-NLS-1$
512 // Close experiments that contain the trace if open
513 if (getParent() instanceof TmfTraceFolder
) {
514 TmfExperimentFolder experimentFolder
= getProject().getExperimentsFolder();
515 for (ITmfProjectModelElement experiment
: experimentFolder
.getChildren()) {
516 for (ITmfProjectModelElement child
: experiment
.getChildren()) {
517 if (child
.getName().equals(getName())) {
518 ((TmfExperimentElement
) experiment
).closeEditors();
523 } else if (getParent() instanceof TmfExperimentElement
) {
524 TmfExperimentElement experiment
= (TmfExperimentElement
) getParent();
525 experiment
.closeEditors();