1 /*******************************************************************************
2 * Copyright (c) 2010, 2014 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 * Geneviève Bastien - Copied code to add/remove traces in this class
12 * Patrick Tasse - Close editors to release resources
13 * Geneviève Bastien - Experiment instantiated with trace type
14 *******************************************************************************/
16 package org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
;
18 import java
.util
.ArrayList
;
19 import java
.util
.Arrays
;
20 import java
.util
.HashMap
;
21 import java
.util
.List
;
24 import org
.eclipse
.core
.resources
.IContainer
;
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
.resources
.IResourceProxy
;
29 import org
.eclipse
.core
.resources
.IResourceProxyVisitor
;
30 import org
.eclipse
.core
.resources
.IWorkspace
;
31 import org
.eclipse
.core
.resources
.ResourcesPlugin
;
32 import org
.eclipse
.core
.runtime
.CoreException
;
33 import org
.eclipse
.core
.runtime
.IConfigurationElement
;
34 import org
.eclipse
.core
.runtime
.IPath
;
35 import org
.eclipse
.core
.runtime
.IStatus
;
36 import org
.eclipse
.core
.runtime
.InvalidRegistryObjectException
;
37 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
38 import org
.eclipse
.core
.runtime
.Platform
;
39 import org
.eclipse
.osgi
.util
.NLS
;
40 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.Activator
;
41 import org
.eclipse
.tracecompass
.tmf
.core
.TmfCommonConstants
;
42 import org
.eclipse
.tracecompass
.tmf
.core
.project
.model
.TmfTraceType
;
43 import org
.eclipse
.tracecompass
.tmf
.core
.project
.model
.TraceTypeHelper
;
44 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.experiment
.TmfExperiment
;
45 import org
.eclipse
.tracecompass
.tmf
.ui
.editors
.TmfEventsEditor
;
46 import org
.eclipse
.tracecompass
.tmf
.ui
.properties
.ReadOnlyTextPropertyDescriptor
;
47 import org
.eclipse
.ui
.views
.properties
.IPropertyDescriptor
;
48 import org
.eclipse
.ui
.views
.properties
.IPropertySource2
;
51 * Implementation of TMF Experiment Model Element.
54 * @author Francois Chouinard
57 public class TmfExperimentElement
extends TmfCommonProjectElement
implements IPropertySource2
{
59 // ------------------------------------------------------------------------
61 // ------------------------------------------------------------------------
63 // Property View stuff
64 private static final String sfInfoCategory
= "Info"; //$NON-NLS-1$
65 private static final String sfName
= "name"; //$NON-NLS-1$
66 private static final String sfPath
= "path"; //$NON-NLS-1$
67 private static final String sfLocation
= "location"; //$NON-NLS-1$
68 private static final String sfFolderSuffix
= "_exp"; //$NON-NLS-1$
69 private static final String sfExperimentType
= "type"; //$NON-NLS-1$
71 private static final ReadOnlyTextPropertyDescriptor sfNameDescriptor
= new ReadOnlyTextPropertyDescriptor(sfName
, sfName
);
72 private static final ReadOnlyTextPropertyDescriptor sfPathDescriptor
= new ReadOnlyTextPropertyDescriptor(sfPath
, sfPath
);
73 private static final ReadOnlyTextPropertyDescriptor sfLocationDescriptor
= new ReadOnlyTextPropertyDescriptor(sfLocation
,
75 private static final ReadOnlyTextPropertyDescriptor sfTypeDescriptor
= new ReadOnlyTextPropertyDescriptor(sfExperimentType
, sfExperimentType
);
77 private static final IPropertyDescriptor
[] sfDescriptors
= { sfNameDescriptor
, sfPathDescriptor
,
78 sfLocationDescriptor
, sfTypeDescriptor
};
81 sfNameDescriptor
.setCategory(sfInfoCategory
);
82 sfPathDescriptor
.setCategory(sfInfoCategory
);
83 sfLocationDescriptor
.setCategory(sfInfoCategory
);
84 sfTypeDescriptor
.setCategory(sfInfoCategory
);
87 // The mapping of available trace type IDs to their corresponding
88 // configuration element
89 private static final Map
<String
, IConfigurationElement
> sfTraceTypeAttributes
= new HashMap
<>();
90 private static final Map
<String
, IConfigurationElement
> sfTraceTypeUIAttributes
= new HashMap
<>();
91 private static final Map
<String
, IConfigurationElement
> sfTraceCategories
= new HashMap
<>();
93 // ------------------------------------------------------------------------
94 // Static initialization
95 // ------------------------------------------------------------------------
98 * Initialize statically at startup by getting extensions from the platform
102 public static void init() {
103 IConfigurationElement
[] config
= Platform
.getExtensionRegistry().getConfigurationElementsFor(TmfTraceType
.TMF_TRACE_TYPE_ID
);
104 for (IConfigurationElement ce
: config
) {
105 String elementName
= ce
.getName();
106 if (elementName
.equals(TmfTraceType
.EXPERIMENT_ELEM
)) {
107 String traceTypeId
= ce
.getAttribute(TmfTraceType
.ID_ATTR
);
108 sfTraceTypeAttributes
.put(traceTypeId
, ce
);
109 } else if (elementName
.equals(TmfTraceType
.CATEGORY_ELEM
)) {
110 String categoryId
= ce
.getAttribute(TmfTraceType
.ID_ATTR
);
111 sfTraceCategories
.put(categoryId
, ce
);
116 * Read the corresponding tmf.ui "tracetypeui" extension point for this
117 * trace type, if it exists.
119 config
= Platform
.getExtensionRegistry().getConfigurationElementsFor(TmfTraceTypeUIUtils
.TMF_TRACE_TYPE_UI_ID
);
120 for (IConfigurationElement ce
: config
) {
121 String elemName
= ce
.getName();
122 if (TmfTraceTypeUIUtils
.EXPERIMENT_ELEM
.equals(elemName
)) {
123 String traceType
= ce
.getAttribute(TmfTraceTypeUIUtils
.TRACETYPE_ATTR
);
124 sfTraceTypeUIAttributes
.put(traceType
, ce
);
129 // ------------------------------------------------------------------------
131 // ------------------------------------------------------------------------
134 * @param name The name of the experiment
135 * @param folder The folder reference
136 * @param parent The experiment folder reference.
138 public TmfExperimentElement(String name
, IFolder folder
, TmfExperimentFolder parent
) {
139 super(name
, folder
, parent
);
142 // ------------------------------------------------------------------------
143 // TmfProjectModelElement
144 // ------------------------------------------------------------------------
147 public IFolder
getResource() {
148 return (IFolder
) fResource
;
152 void refreshChildren() {
153 IFolder folder
= getResource();
155 /* Update the trace children of this experiment */
156 // Get the children from the model
157 Map
<String
, ITmfProjectModelElement
> childrenMap
= new HashMap
<>();
158 for (TmfTraceElement trace
: getTraces()) {
159 childrenMap
.put(trace
.getElementPath(), trace
);
162 List
<IResource
> members
= getTraceResources();
163 for (IResource resource
: members
) {
164 String name
= resource
.getName();
165 String elementPath
= resource
.getFullPath().makeRelativeTo(folder
.getFullPath()).toString();
166 ITmfProjectModelElement element
= childrenMap
.get(elementPath
);
167 if (element
instanceof TmfTraceElement
) {
168 childrenMap
.remove(elementPath
);
170 element
= new TmfTraceElement(name
, resource
, this);
174 // Cleanup dangling children from the model
175 for (ITmfProjectModelElement danglingChild
: childrenMap
.values()) {
176 removeChild(danglingChild
);
179 /* Update the analysis under this experiment */
180 super.refreshChildren();
183 private List
<IResource
> getTraceResources() {
184 IFolder folder
= getResource();
185 final List
<IResource
> list
= new ArrayList
<>();
187 folder
.accept(new IResourceProxyVisitor() {
189 public boolean visit(IResourceProxy resource
) throws CoreException
{
190 if (resource
.isLinked()) {
191 list
.add(resource
.requestResource());
196 } catch (CoreException e
) {
201 // ------------------------------------------------------------------------
203 // ------------------------------------------------------------------------
206 * Refreshes the trace type filed by reading the trace type persistent
207 * property of the resource reference.
209 * If trace type is null after refresh, set it to the generic trace type
210 * (for seamless upgrade)
213 public void refreshTraceType() {
214 super.refreshTraceType();
215 if (getTraceType() == null) {
216 IConfigurationElement ce
= TmfTraceType
.getTraceAttributes(TmfTraceType
.DEFAULT_EXPERIMENT_TYPE
);
219 IFolder experimentFolder
= getResource();
220 experimentFolder
.setPersistentProperty(TmfCommonConstants
.TRACETYPE
, ce
.getAttribute(TmfTraceType
.ID_ATTR
));
221 super.refreshTraceType();
222 } catch (InvalidRegistryObjectException
| CoreException e
) {
229 * Returns a list of TmfTraceElements contained in this experiment.
230 * @return a list of TmfTraceElements
233 public List
<TmfTraceElement
> getTraces() {
234 List
<ITmfProjectModelElement
> children
= getChildren();
235 List
<TmfTraceElement
> traces
= new ArrayList
<>();
236 for (ITmfProjectModelElement child
: children
) {
237 if (child
instanceof TmfTraceElement
) {
238 traces
.add((TmfTraceElement
) child
);
245 * Adds a trace to the experiment
247 * @param trace The trace element to add
250 public void addTrace(TmfTraceElement trace
) {
251 addTrace(trace
, true);
255 * Adds a trace to the experiment
257 * @param trace The trace element to add
258 * @param refresh Flag for refreshing the project
262 public void addTrace(TmfTraceElement trace
, boolean refresh
) {
264 * Create a link to the actual trace and set the trace type
266 IFolder experiment
= getResource();
267 IResource resource
= trace
.getResource();
268 IPath location
= resource
.getLocation();
269 IWorkspace workspace
= ResourcesPlugin
.getWorkspace();
271 String traceTypeId
= TmfTraceType
.getTraceTypeId(trace
.getResource());
272 TraceTypeHelper traceType
= TmfTraceType
.getTraceType(traceTypeId
);
274 if (resource
instanceof IFolder
) {
275 IFolder folder
= experiment
.getFolder(trace
.getElementPath());
276 TraceUtils
.createFolder((IFolder
) folder
.getParent(), new NullProgressMonitor());
277 IStatus result
= workspace
.validateLinkLocation(folder
, location
);
278 if (result
.isOK() || result
.matches(IStatus
.INFO
| IStatus
.WARNING
)) {
279 folder
.createLink(location
, IResource
.REPLACE
, null);
280 if (traceType
!= null) {
281 TmfTraceTypeUIUtils
.setTraceType(folder
, traceType
, refresh
);
285 Activator
.getDefault().logError("Error creating link. Invalid trace location " + location
); //$NON-NLS-1$
288 IFile file
= experiment
.getFile(trace
.getElementPath());
289 TraceUtils
.createFolder((IFolder
) file
.getParent(), new NullProgressMonitor());
290 IStatus result
= workspace
.validateLinkLocation(file
, location
);
291 if (result
.isOK() || result
.matches(IStatus
.INFO
| IStatus
.WARNING
)) {
292 file
.createLink(location
, IResource
.REPLACE
, null);
293 if (traceType
!= null) {
294 TmfTraceTypeUIUtils
.setTraceType(file
, traceType
, refresh
);
297 Activator
.getDefault().logError("Error creating link. Invalid trace location " + location
); //$NON-NLS-1$
300 } catch (CoreException e
) {
301 Activator
.getDefault().logError("Error creating link to location " + location
, e
); //$NON-NLS-1$
307 * Removes a trace from an experiment
309 * @param trace The trace to remove
310 * @throws CoreException exception
313 public void removeTrace(TmfTraceElement trace
) throws CoreException
{
315 // Close the experiment if open
318 /* Finally, remove the trace from experiment*/
320 deleteTraceResource(trace
.getResource());
321 deleteSupplementaryResources();
324 private void deleteTraceResource(IResource resource
) throws CoreException
{
325 resource
.delete(true, null);
326 IContainer parent
= resource
.getParent();
327 // delete empty folders up to the parent experiment folder
328 if (!parent
.equals(getResource()) && parent
.members().length
== 0) {
329 deleteTraceResource(parent
);
334 public IFile
createBookmarksFile() throws CoreException
{
335 return createBookmarksFile(getProject().getExperimentsFolder().getResource(), TmfExperiment
.class.getCanonicalName());
339 public String
getEditorId() {
340 /* See if a default editor was set for this experiment type */
341 if (getTraceType() != null) {
342 IConfigurationElement ce
= sfTraceTypeUIAttributes
.get(getTraceType());
344 IConfigurationElement
[] defaultEditorCE
= ce
.getChildren(TmfTraceTypeUIUtils
.DEFAULT_EDITOR_ELEM
);
345 if (defaultEditorCE
.length
== 1) {
346 return defaultEditorCE
[0].getAttribute(TmfTraceType
.ID_ATTR
);
351 /* No default editor, try to find a common editor for all traces */
352 final List
<TmfTraceElement
> traceEntries
= getTraces();
353 String commonEditorId
= null;
355 for (TmfTraceElement element
: traceEntries
) {
356 // If all traces use the same editorId, use it, otherwise use the
358 final String editorId
= element
.getEditorId();
359 if (commonEditorId
== null) {
360 commonEditorId
= (editorId
!= null) ? editorId
: TmfEventsEditor
.ID
;
361 } else if (!commonEditorId
.equals(editorId
)) {
362 commonEditorId
= TmfEventsEditor
.ID
;
369 * Instantiate a {@link TmfExperiment} object based on the experiment type
370 * and the corresponding extension.
372 * @return the {@link TmfExperiment} or <code>null</code> for an error
376 public TmfExperiment
instantiateTrace() {
379 // make sure that supplementary folder exists
380 refreshSupplementaryFolder();
382 if (getTraceType() != null) {
384 IConfigurationElement ce
= sfTraceTypeAttributes
.get(getTraceType());
388 TmfExperiment experiment
= (TmfExperiment
) ce
.createExecutableExtension(TmfTraceType
.EXPERIMENT_TYPE_ATTR
);
391 } catch (CoreException e
) {
392 Activator
.getDefault().logError(NLS
.bind(Messages
.TmfExperimentElement_ErrorInstantiatingTrace
, getName()), e
);
398 public String
getTypeName() {
399 return Messages
.TmfExperimentElement_TypeName
;
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 (sfExperimentType
.equals(id
)) {
432 if (getTraceType() != null) {
433 IConfigurationElement ce
= sfTraceTypeAttributes
.get(getTraceType());
435 return ""; //$NON-NLS-1$
437 String categoryId
= ce
.getAttribute(TmfTraceType
.CATEGORY_ATTR
);
438 if (categoryId
!= null) {
439 IConfigurationElement category
= sfTraceCategories
.get(categoryId
);
440 if (category
!= null) {
441 return category
.getAttribute(TmfTraceType
.NAME_ATTR
) + ':' + ce
.getAttribute(TmfTraceType
.NAME_ATTR
);
444 return ce
.getAttribute(TmfTraceType
.NAME_ATTR
);
452 public void resetPropertyValue(Object id
) {
456 public void setPropertyValue(Object id
, Object value
) {
460 public boolean isPropertyResettable(Object id
) {
465 public boolean isPropertySet(Object id
) {
470 * Return the suffix for resource names
471 * @return The folder suffix
474 public String
getSuffix() {
475 return sfFolderSuffix
;