1 /*******************************************************************************
2 * Copyright (c) 2010, 2011, 2012 Ericsson
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 *******************************************************************************/
14 package org
.eclipse
.linuxtools
.tmf
.ui
.project
.model
;
16 import java
.io
.ByteArrayInputStream
;
17 import java
.io
.InputStream
;
18 import java
.util
.Arrays
;
19 import java
.util
.HashMap
;
22 import org
.eclipse
.core
.resources
.IFile
;
23 import org
.eclipse
.core
.resources
.IFolder
;
24 import org
.eclipse
.core
.resources
.IResource
;
25 import org
.eclipse
.core
.runtime
.CoreException
;
26 import org
.eclipse
.core
.runtime
.IConfigurationElement
;
27 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
28 import org
.eclipse
.core
.runtime
.Platform
;
29 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.Activator
;
30 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.parsers
.custom
.CustomTxtEvent
;
31 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.parsers
.custom
.CustomTxtTrace
;
32 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.parsers
.custom
.CustomTxtTraceDefinition
;
33 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.parsers
.custom
.CustomXmlEvent
;
34 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.parsers
.custom
.CustomXmlTrace
;
35 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.parsers
.custom
.CustomXmlTraceDefinition
;
36 import org
.eclipse
.linuxtools
.tmf
.core
.TmfCommonConstants
;
37 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfEvent
;
38 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.ITmfTrace
;
39 import org
.eclipse
.linuxtools
.tmf
.core
.trace
.TmfTrace
;
40 import org
.eclipse
.linuxtools
.tmf
.ui
.editors
.TmfEventsEditor
;
41 import org
.eclipse
.ui
.IActionFilter
;
42 import org
.eclipse
.ui
.views
.properties
.IPropertyDescriptor
;
43 import org
.eclipse
.ui
.views
.properties
.IPropertySource2
;
44 import org
.eclipse
.ui
.views
.properties
.TextPropertyDescriptor
;
47 * Implementation of trace model element representing a trace. It provides methods to instantiate
48 * <code>ITmfTrace</code> and <code>ITmfEvent</code> as well as editor ID from the trace type
49 * extension definition.
52 * @author Francois Chouinard
54 public class TmfTraceElement
extends TmfProjectModelElement
implements IActionFilter
, IPropertySource2
{
56 // ------------------------------------------------------------------------
58 // ------------------------------------------------------------------------
62 * Bundle attribute name
64 public static final String BUNDLE
= "bundle"; //$NON-NLS-1$
66 * IsLinked attribute name.
68 public static final String IS_LINKED
= "isLinked"; //$NON-NLS-1$
70 // Property View stuff
71 private static final String sfInfoCategory
= "Info"; //$NON-NLS-1$
72 private static final String sfName
= "name"; //$NON-NLS-1$
73 private static final String sfPath
= "path"; //$NON-NLS-1$
74 private static final String sfLocation
= "location"; //$NON-NLS-1$
75 private static final String sfEventType
= "type"; //$NON-NLS-1$
76 private static final String sfIsLinked
= "linked"; //$NON-NLS-1$
78 private static final TextPropertyDescriptor sfNameDescriptor
= new TextPropertyDescriptor(sfName
, sfName
);
79 private static final TextPropertyDescriptor sfPathDescriptor
= new TextPropertyDescriptor(sfPath
, sfPath
);
80 private static final TextPropertyDescriptor sfLocationDescriptor
= new TextPropertyDescriptor(sfLocation
, sfLocation
);
81 private static final TextPropertyDescriptor sfTypeDescriptor
= new TextPropertyDescriptor(sfEventType
, sfEventType
);
82 private static final TextPropertyDescriptor sfIsLinkedDescriptor
= new TextPropertyDescriptor(sfIsLinked
, sfIsLinked
);
84 private static final IPropertyDescriptor
[] sfDescriptors
= { sfNameDescriptor
, sfPathDescriptor
, sfLocationDescriptor
,
85 sfTypeDescriptor
, sfIsLinkedDescriptor
};
88 sfNameDescriptor
.setCategory(sfInfoCategory
);
89 sfPathDescriptor
.setCategory(sfInfoCategory
);
90 sfLocationDescriptor
.setCategory(sfInfoCategory
);
91 sfTypeDescriptor
.setCategory(sfInfoCategory
);
92 sfIsLinkedDescriptor
.setCategory(sfInfoCategory
);
95 private static final String BOOKMARKS_HIDDEN_FILE
= ".bookmarks"; //$NON-NLS-1$
97 // ------------------------------------------------------------------------
99 // ------------------------------------------------------------------------
101 // This trace type ID as defined in plugin.xml
102 private String fTraceTypeId
= null;
104 // ------------------------------------------------------------------------
105 // Static initialization
106 // ------------------------------------------------------------------------
108 // The mapping of available trace type IDs to their corresponding configuration element
109 private static final Map
<String
, IConfigurationElement
> sfTraceTypeAttributes
= new HashMap
<String
, IConfigurationElement
>();
110 private static final Map
<String
, IConfigurationElement
> sfTraceCategories
= new HashMap
<String
, IConfigurationElement
>();
113 * Initialize statically at startup by getting extensions from the platform extension registry.
115 public static void init() {
116 IConfigurationElement
[] config
= Platform
.getExtensionRegistry().getConfigurationElementsFor(TmfTraceType
.TMF_TRACE_TYPE_ID
);
117 for (IConfigurationElement ce
: config
) {
118 String elementName
= ce
.getName();
119 if (elementName
.equals(TmfTraceType
.TYPE_ELEM
)) {
120 String traceTypeId
= ce
.getAttribute(TmfTraceType
.ID_ATTR
);
121 sfTraceTypeAttributes
.put(traceTypeId
, ce
);
122 } else if (elementName
.equals(TmfTraceType
.CATEGORY_ELEM
)) {
123 String categoryId
= ce
.getAttribute(TmfTraceType
.ID_ATTR
);
124 sfTraceCategories
.put(categoryId
, ce
);
129 // ------------------------------------------------------------------------
131 // ------------------------------------------------------------------------
134 * Creates trace model element under the trace folder.
135 * @param name The name of trace
136 * @param trace The trace resource.
137 * @param parent The parent element (trace folder)
139 public TmfTraceElement(String name
, IResource trace
, TmfTraceFolder parent
) {
140 this(name
, trace
, (TmfProjectModelElement
) parent
);
144 * Creates trace model element under the experiment folder.
145 * @param name The name of trace
146 * @param trace The trace resource.
147 * @param parent The parent element (experiment folder)
149 public TmfTraceElement(String name
, IResource trace
, TmfExperimentElement parent
) {
150 this(name
, trace
, (TmfProjectModelElement
) parent
);
153 private TmfTraceElement(String name
, IResource trace
, TmfProjectModelElement parent
) {
154 super(name
, trace
, parent
);
155 parent
.addChild(this);
159 // ------------------------------------------------------------------------
161 // ------------------------------------------------------------------------
163 * Returns the trace type ID.
164 * @return trace type ID.
166 public String
getTraceType() {
171 * Refreshes the trace type filed by reading the trace type persistent property of the resource
174 public void refreshTraceType() {
176 fTraceTypeId
= getResource().getPersistentProperty(TmfCommonConstants
.TRACETYPE
);
177 } catch (CoreException e
) {
178 Activator
.getDefault().logError("Error refreshing trace type pesistent property for trace " + getName(), e
); //$NON-NLS-1$
183 * Instantiate a <code>ITmfTrace</code> object based on the trace type and the corresponding extension.
185 * @return the <code>ITmfTrace</code> or <code>null</code> for an error
187 public ITmfTrace
instantiateTrace() {
190 // make sure that supplementary folder exists
191 refreshSupplementaryFolder();
193 if (fTraceTypeId
!= null) {
194 if (fTraceTypeId
.startsWith(CustomTxtTrace
.class.getCanonicalName())) {
195 for (CustomTxtTraceDefinition def
: CustomTxtTraceDefinition
.loadAll()) {
196 if (fTraceTypeId
.equals(CustomTxtTrace
.class.getCanonicalName() + ":" + def
.definitionName
)) { //$NON-NLS-1$
197 return new CustomTxtTrace(def
);
201 if (fTraceTypeId
.startsWith(CustomXmlTrace
.class.getCanonicalName())) {
202 for (CustomXmlTraceDefinition def
: CustomXmlTraceDefinition
.loadAll()) {
203 if (fTraceTypeId
.equals(CustomXmlTrace
.class.getCanonicalName() + ":" + def
.definitionName
)) { //$NON-NLS-1$
204 return new CustomXmlTrace(def
);
208 IConfigurationElement ce
= sfTraceTypeAttributes
.get(fTraceTypeId
);
209 ITmfTrace trace
= (ITmfTrace
) ce
.createExecutableExtension(TmfTraceType
.TRACE_TYPE_ATTR
);
212 } catch (CoreException e
) {
213 Activator
.getDefault().logError("Error instantiating ITmfTrace object for trace " + getName(), e
); //$NON-NLS-1$
219 * Instantiate a <code>ITmfEvent</code> object based on the trace type and the corresponding extension.
221 * @return the <code>ITmfEvent</code> or <code>null</code> for an error
223 public ITmfEvent
instantiateEvent() {
225 if (fTraceTypeId
!= null) {
226 if (fTraceTypeId
.startsWith(CustomTxtTrace
.class.getCanonicalName())) {
227 for (CustomTxtTraceDefinition def
: CustomTxtTraceDefinition
.loadAll()) {
228 if (fTraceTypeId
.equals(CustomTxtTrace
.class.getCanonicalName() + ":" + def
.definitionName
)) { //$NON-NLS-1$
229 return new CustomTxtEvent(def
);
233 if (fTraceTypeId
.startsWith(CustomXmlTrace
.class.getCanonicalName())) {
234 for (CustomXmlTraceDefinition def
: CustomXmlTraceDefinition
.loadAll()) {
235 if (fTraceTypeId
.equals(CustomXmlTrace
.class.getCanonicalName() + ":" + def
.definitionName
)) { //$NON-NLS-1$
236 return new CustomXmlEvent(def
);
240 IConfigurationElement ce
= sfTraceTypeAttributes
.get(fTraceTypeId
);
241 ITmfEvent event
= (ITmfEvent
) ce
.createExecutableExtension(TmfTraceType
.EVENT_TYPE_ATTR
);
244 } catch (CoreException e
) {
245 Activator
.getDefault().logError("Error instantiating ITmfEvent object for trace " + getName(), e
); //$NON-NLS-1$
251 * Returns the optional editor ID from the trace type extension.
252 * @return the editor ID or <code>null</code> if not defined.
254 public String
getEditorId() {
255 if (fTraceTypeId
!= null) {
256 if (fTraceTypeId
.startsWith(CustomTxtTrace
.class.getCanonicalName())) {
257 return TmfEventsEditor
.ID
;
259 if (fTraceTypeId
.startsWith(CustomXmlTrace
.class.getCanonicalName())) {
260 return TmfEventsEditor
.ID
;
262 IConfigurationElement ce
= sfTraceTypeAttributes
.get(fTraceTypeId
);
263 IConfigurationElement
[] defaultEditorCE
= ce
.getChildren(TmfTraceType
.DEFAULT_EDITOR_ELEM
);
264 if (defaultEditorCE
.length
== 1) {
265 return defaultEditorCE
[0].getAttribute(TmfTraceType
.ID_ATTR
);
272 * Returns the file resource used to store bookmarks.
273 * If the trace resource is a file, it is returned directly.
274 * If the trace resource is a folder, a linked file is returned.
275 * The linked file will be created if it doesn't exist.
276 * @return the bookmarks file
277 * @throws CoreException if the bookmarks file cannot be created
280 public IFile
getBookmarksFile() throws CoreException
{
282 if (fResource
instanceof IFile
) {
283 file
= (IFile
) fResource
;
284 } else if (fResource
instanceof IFolder
) {
285 final IFile bookmarksFile
= getProject().getTracesFolder().getResource().getFile(BOOKMARKS_HIDDEN_FILE
);
286 if (!bookmarksFile
.exists()) {
287 final InputStream source
= new ByteArrayInputStream(new byte[0]);
288 bookmarksFile
.create(source
, true, null);
290 bookmarksFile
.setHidden(true);
292 final IFolder folder
= (IFolder
) fResource
;
293 file
= folder
.getFile(getName() + '_');
294 if (!file
.exists()) {
295 file
.createLink(bookmarksFile
.getLocation(), IResource
.REPLACE
, null);
297 file
.setHidden(true);
298 file
.setPersistentProperty(TmfCommonConstants
.TRACETYPE
, TmfTrace
.class.getCanonicalName());
304 * Returns the <code>TmfTraceElement</code> located under the <code>TmfTracesFolder</code>.
306 * @return <code>this</code> if this element is under the <code>TmfTracesFolder</code>
307 * else the corresponding <code>TmfTraceElement</code> if this element is under
308 * <code>TmfExperimentElement</code>.
310 public TmfTraceElement
getElementUnderTraceFolder() {
312 // If trace is under an experiment, return original trace from the traces folder
313 if (getParent() instanceof TmfExperimentElement
) {
314 for (TmfTraceElement aTrace
: getProject().getTracesFolder().getTraces()) {
315 if (aTrace
.getName().equals(getName())) {
324 * Deletes the trace specific supplementary folder.
326 public void deleteSupplementaryFolder() {
327 IFolder supplFolder
= getTraceSupplementaryFolder(fResource
.getName());
328 if (supplFolder
.exists()) {
330 supplFolder
.delete(true, new NullProgressMonitor());
331 } catch (CoreException e
) {
332 Activator
.getDefault().logError("Error deleting supplementary folder " + supplFolder
, e
); //$NON-NLS-1$
338 * Renames the trace specific supplementary folder according to the new trace name.
340 * @param newTraceName The new trace name
342 public void renameSupplementaryFolder(String newTraceName
) {
343 IFolder oldSupplFolder
= getTraceSupplementaryFolder(fResource
.getName());
344 IFolder newSupplFolder
= getTraceSupplementaryFolder(newTraceName
);
346 // Rename supplementary folder
347 if (oldSupplFolder
.exists()) {
349 oldSupplFolder
.move(newSupplFolder
.getFullPath(), true, new NullProgressMonitor());
350 } catch (CoreException e
) {
351 Activator
.getDefault().logError("Error renaming supplementary folder " + oldSupplFolder
, e
); //$NON-NLS-1$
357 * Copies the trace specific supplementary folder to the new trace name.
359 * @param newTraceName The new trace name
361 public void copySupplementaryFolder(String newTraceName
) {
362 IFolder oldSupplFolder
= getTraceSupplementaryFolder(fResource
.getName());
363 IFolder newSupplFolder
= getTraceSupplementaryFolder(newTraceName
);
365 // copy supplementary folder
366 if (oldSupplFolder
.exists()) {
368 oldSupplFolder
.copy(newSupplFolder
.getFullPath(), true, new NullProgressMonitor());
369 } catch (CoreException e
) {
370 Activator
.getDefault().logError("Error renaming supplementary folder " + oldSupplFolder
, e
); //$NON-NLS-1$
376 * Copies the trace specific supplementary folder a new folder.
378 * @param destination The destination folder to copy to.
380 public void copySupplementaryFolder(IFolder destination
) {
381 IFolder oldSupplFolder
= getTraceSupplementaryFolder(fResource
.getName());
383 // copy supplementary folder
384 if (oldSupplFolder
.exists()) {
386 oldSupplFolder
.copy(destination
.getFullPath(), true, new NullProgressMonitor());
387 } catch (CoreException e
) {
388 Activator
.getDefault().logError("Error copying supplementary folder " + oldSupplFolder
, e
); //$NON-NLS-1$
395 * Refreshes the trace specific supplementary folder information. It creates the folder if not exists.
396 * It sets the persistence property of the trace resource
398 public void refreshSupplementaryFolder() {
399 createSupplementaryDirectory();
403 * Checks if supplementary resource exist or not.
405 * @return <code>true</code> if one or more files are under the trace supplementary folder
407 public boolean hasSupplementaryResources() {
408 IResource
[] resources
= getSupplementaryResources();
409 return (resources
.length
> 0);
413 * Returns the supplementary resources under the trace supplementary folder.
415 * @return array of resources under the trace supplementary folder.
417 public IResource
[] getSupplementaryResources() {
418 IFolder supplFolder
= getTraceSupplementaryFolder(fResource
.getName());
419 if (supplFolder
.exists()) {
421 return supplFolder
.members();
422 } catch (CoreException e
) {
423 Activator
.getDefault().logError("Error deleting supplementary folder " + supplFolder
, e
); //$NON-NLS-1$
426 return new IResource
[0];
430 * Deletes the given resources.
432 * @param resources array of resources to delete.
434 public void deleteSupplementaryResources(IResource
[] resources
) {
436 for (int i
= 0; i
< resources
.length
; i
++) {
438 resources
[i
].delete(true, new NullProgressMonitor());
439 } catch (CoreException e
) {
440 Activator
.getDefault().logError("Error deleting supplementary resource " + resources
[i
], e
); //$NON-NLS-1$
445 private void createSupplementaryDirectory() {
446 IFolder supplFolder
= getTraceSupplementaryFolder(fResource
.getName());
447 if (!supplFolder
.exists()) {
449 supplFolder
.create(true, true, new NullProgressMonitor());
450 } catch (CoreException e
) {
451 Activator
.getDefault().logError("Error creating resource supplementary file " + supplFolder
, e
); //$NON-NLS-1$
456 fResource
.setPersistentProperty(TmfCommonConstants
.TRACE_SUPPLEMENTARY_FOLDER
, supplFolder
.getLocationURI().getPath());
457 } catch (CoreException e
) {
458 Activator
.getDefault().logError("Error setting persistant property " + TmfCommonConstants
.TRACE_SUPPLEMENTARY_FOLDER
, e
); //$NON-NLS-1$
463 // ------------------------------------------------------------------------
465 // ------------------------------------------------------------------------
468 public boolean testAttribute(Object target
, String name
, String value
) {
469 if (name
.equals(IS_LINKED
)) {
470 boolean isLinked
= getResource().isLinked();
471 return Boolean
.toString(isLinked
).equals(value
);
476 // ------------------------------------------------------------------------
478 // ------------------------------------------------------------------------
481 * @see org.eclipse.linuxtools.tmf.ui.project.model.ITmfProjectModelElement#getProject()
484 public TmfProjectElement
getProject() {
485 if (getParent() instanceof TmfTraceFolder
) {
486 TmfTraceFolder folder
= (TmfTraceFolder
) getParent();
487 TmfProjectElement project
= (TmfProjectElement
) folder
.getParent();
490 if (getParent() instanceof TmfExperimentElement
) {
491 TmfExperimentElement experiment
= (TmfExperimentElement
) getParent();
492 TmfExperimentFolder folder
= (TmfExperimentFolder
) experiment
.getParent();
493 TmfProjectElement project
= (TmfProjectElement
) folder
.getParent();
499 // ------------------------------------------------------------------------
501 // ------------------------------------------------------------------------
505 * @see org.eclipse.ui.views.properties.IPropertySource#getEditableValue()
508 public Object
getEditableValue() {
514 * @see org.eclipse.ui.views.properties.IPropertySource#getPropertyDescriptors()
517 public IPropertyDescriptor
[] getPropertyDescriptors() {
518 return (sfDescriptors
!= null) ? Arrays
.copyOf(sfDescriptors
, sfDescriptors
.length
) : null;
523 * @see org.eclipse.ui.views.properties.IPropertySource#getPropertyValue(java.lang.Object)
526 public Object
getPropertyValue(Object id
) {
528 if (sfName
.equals(id
)) {
532 if (sfPath
.equals(id
)) {
533 return getPath().toString();
536 if (sfLocation
.equals(id
)) {
537 return getLocation().toString();
540 if (sfIsLinked
.equals(id
)) {
541 return Boolean
.valueOf(getResource().isLinked()).toString();
544 if (sfEventType
.equals(id
)) {
545 if (fTraceTypeId
!= null) {
546 IConfigurationElement ce
= sfTraceTypeAttributes
.get(fTraceTypeId
);
547 return (ce
!= null) ?
(getCategory(ce
) + " : " + ce
.getAttribute(TmfTraceType
.NAME_ATTR
)) : ""; //$NON-NLS-1$ //$NON-NLS-2$
554 private static String
getCategory(IConfigurationElement ce
) {
555 String categoryId
= ce
.getAttribute(TmfTraceType
.CATEGORY_ATTR
);
556 if (categoryId
!= null) {
557 IConfigurationElement category
= sfTraceCategories
.get(categoryId
);
558 if (category
!= null) {
559 return category
.getAttribute(TmfTraceType
.NAME_ATTR
);
562 return "[no category]"; //$NON-NLS-1$
567 * @see org.eclipse.ui.views.properties.IPropertySource#resetPropertyValue(java.lang.Object)
570 public void resetPropertyValue(Object id
) {
575 * @see org.eclipse.ui.views.properties.IPropertySource#setPropertyValue(java.lang.Object, java.lang.Object)
578 public void setPropertyValue(Object id
, Object value
) {
583 * @see org.eclipse.ui.views.properties.IPropertySource2#isPropertyResettable(java.lang.Object)
586 public boolean isPropertyResettable(Object id
) {
592 * @see org.eclipse.ui.views.properties.IPropertySource2#isPropertySet(java.lang.Object)
595 public boolean isPropertySet(Object id
) {