tmf: Move TmfExperiment to its own package
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / project / model / TmfExperimentElement.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 * 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 *******************************************************************************/
15
16 package org.eclipse.tracecompass.tmf.ui.project.model;
17
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23
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;
49
50 /**
51 * Implementation of TMF Experiment Model Element.
52 * <p>
53 * @version 1.0
54 * @author Francois Chouinard
55 *
56 */
57 public class TmfExperimentElement extends TmfCommonProjectElement implements IPropertySource2 {
58
59 // ------------------------------------------------------------------------
60 // Constants
61 // ------------------------------------------------------------------------
62
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$
70
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,
74 sfLocation);
75 private static final ReadOnlyTextPropertyDescriptor sfTypeDescriptor = new ReadOnlyTextPropertyDescriptor(sfExperimentType, sfExperimentType);
76
77 private static final IPropertyDescriptor[] sfDescriptors = { sfNameDescriptor, sfPathDescriptor,
78 sfLocationDescriptor, sfTypeDescriptor };
79
80 static {
81 sfNameDescriptor.setCategory(sfInfoCategory);
82 sfPathDescriptor.setCategory(sfInfoCategory);
83 sfLocationDescriptor.setCategory(sfInfoCategory);
84 sfTypeDescriptor.setCategory(sfInfoCategory);
85 }
86
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<>();
92
93 // ------------------------------------------------------------------------
94 // Static initialization
95 // ------------------------------------------------------------------------
96
97 /**
98 * Initialize statically at startup by getting extensions from the platform
99 * extension registry.
100 * @since 3.0
101 */
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);
112 }
113 }
114
115 /*
116 * Read the corresponding tmf.ui "tracetypeui" extension point for this
117 * trace type, if it exists.
118 */
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);
125 }
126 }
127 }
128
129 // ------------------------------------------------------------------------
130 // Constructors
131 // ------------------------------------------------------------------------
132 /**
133 * Constructor
134 * @param name The name of the experiment
135 * @param folder The folder reference
136 * @param parent The experiment folder reference.
137 */
138 public TmfExperimentElement(String name, IFolder folder, TmfExperimentFolder parent) {
139 super(name, folder, parent);
140 }
141
142 // ------------------------------------------------------------------------
143 // TmfProjectModelElement
144 // ------------------------------------------------------------------------
145
146 @Override
147 public IFolder getResource() {
148 return (IFolder) fResource;
149 }
150
151 @Override
152 void refreshChildren() {
153 IFolder folder = getResource();
154
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);
160 }
161
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);
169 } else {
170 element = new TmfTraceElement(name, resource, this);
171 }
172 }
173
174 // Cleanup dangling children from the model
175 for (ITmfProjectModelElement danglingChild : childrenMap.values()) {
176 removeChild(danglingChild);
177 }
178
179 /* Update the analysis under this experiment */
180 super.refreshChildren();
181 }
182
183 private List<IResource> getTraceResources() {
184 IFolder folder = getResource();
185 final List<IResource> list = new ArrayList<>();
186 try {
187 folder.accept(new IResourceProxyVisitor() {
188 @Override
189 public boolean visit(IResourceProxy resource) throws CoreException {
190 if (resource.isLinked()) {
191 list.add(resource.requestResource());
192 }
193 return true;
194 }
195 }, IResource.NONE);
196 } catch (CoreException e) {
197 }
198 return list;
199 }
200
201 // ------------------------------------------------------------------------
202 // Operations
203 // ------------------------------------------------------------------------
204
205 /**
206 * Refreshes the trace type filed by reading the trace type persistent
207 * property of the resource reference.
208 *
209 * If trace type is null after refresh, set it to the generic trace type
210 * (for seamless upgrade)
211 */
212 @Override
213 public void refreshTraceType() {
214 super.refreshTraceType();
215 if (getTraceType() == null) {
216 IConfigurationElement ce = TmfTraceType.getTraceAttributes(TmfTraceType.DEFAULT_EXPERIMENT_TYPE);
217 if (ce != null) {
218 try {
219 IFolder experimentFolder = getResource();
220 experimentFolder.setPersistentProperty(TmfCommonConstants.TRACETYPE, ce.getAttribute(TmfTraceType.ID_ATTR));
221 super.refreshTraceType();
222 } catch (InvalidRegistryObjectException | CoreException e) {
223 }
224 }
225 }
226 }
227
228 /**
229 * Returns a list of TmfTraceElements contained in this experiment.
230 * @return a list of TmfTraceElements
231 */
232 @Override
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);
239 }
240 }
241 return traces;
242 }
243
244 /**
245 * Adds a trace to the experiment
246 *
247 * @param trace The trace element to add
248 * @since 2.0
249 */
250 public void addTrace(TmfTraceElement trace) {
251 addTrace(trace, true);
252 }
253
254 /**
255 * Adds a trace to the experiment
256 *
257 * @param trace The trace element to add
258 * @param refresh Flag for refreshing the project
259 *
260 * @since 3.1
261 */
262 public void addTrace(TmfTraceElement trace, boolean refresh) {
263 /**
264 * Create a link to the actual trace and set the trace type
265 */
266 IFolder experiment = getResource();
267 IResource resource = trace.getResource();
268 IPath location = resource.getLocation();
269 IWorkspace workspace = ResourcesPlugin.getWorkspace();
270 try {
271 String traceTypeId = TmfTraceType.getTraceTypeId(trace.getResource());
272 TraceTypeHelper traceType = TmfTraceType.getTraceType(traceTypeId);
273
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);
282 }
283
284 } else {
285 Activator.getDefault().logError("Error creating link. Invalid trace location " + location); //$NON-NLS-1$
286 }
287 } else {
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);
295 }
296 } else {
297 Activator.getDefault().logError("Error creating link. Invalid trace location " + location); //$NON-NLS-1$
298 }
299 }
300 } catch (CoreException e) {
301 Activator.getDefault().logError("Error creating link to location " + location, e); //$NON-NLS-1$
302 }
303
304 }
305
306 /**
307 * Removes a trace from an experiment
308 *
309 * @param trace The trace to remove
310 * @throws CoreException exception
311 * @since 2.0
312 */
313 public void removeTrace(TmfTraceElement trace) throws CoreException {
314
315 // Close the experiment if open
316 closeEditors();
317
318 /* Finally, remove the trace from experiment*/
319 removeChild(trace);
320 deleteTraceResource(trace.getResource());
321 deleteSupplementaryResources();
322 }
323
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);
330 }
331 }
332
333 @Override
334 public IFile createBookmarksFile() throws CoreException {
335 return createBookmarksFile(getProject().getExperimentsFolder().getResource(), TmfExperiment.class.getCanonicalName());
336 }
337
338 @Override
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());
343 if (ce != null) {
344 IConfigurationElement[] defaultEditorCE = ce.getChildren(TmfTraceTypeUIUtils.DEFAULT_EDITOR_ELEM);
345 if (defaultEditorCE.length == 1) {
346 return defaultEditorCE[0].getAttribute(TmfTraceType.ID_ATTR);
347 }
348 }
349 }
350
351 /* No default editor, try to find a common editor for all traces */
352 final List<TmfTraceElement> traceEntries = getTraces();
353 String commonEditorId = null;
354
355 for (TmfTraceElement element : traceEntries) {
356 // If all traces use the same editorId, use it, otherwise use the
357 // default
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;
363 }
364 }
365 return null;
366 }
367
368 /**
369 * Instantiate a {@link TmfExperiment} object based on the experiment type
370 * and the corresponding extension.
371 *
372 * @return the {@link TmfExperiment} or <code>null</code> for an error
373 * @since 3.0
374 */
375 @Override
376 public TmfExperiment instantiateTrace() {
377 try {
378
379 // make sure that supplementary folder exists
380 refreshSupplementaryFolder();
381
382 if (getTraceType() != null) {
383
384 IConfigurationElement ce = sfTraceTypeAttributes.get(getTraceType());
385 if (ce == null) {
386 return null;
387 }
388 TmfExperiment experiment = (TmfExperiment) ce.createExecutableExtension(TmfTraceType.EXPERIMENT_TYPE_ATTR);
389 return experiment;
390 }
391 } catch (CoreException e) {
392 Activator.getDefault().logError(NLS.bind(Messages.TmfExperimentElement_ErrorInstantiatingTrace, getName()), e);
393 }
394 return null;
395 }
396
397 @Override
398 public String getTypeName() {
399 return Messages.TmfExperimentElement_TypeName;
400 }
401
402 // ------------------------------------------------------------------------
403 // IPropertySource2
404 // ------------------------------------------------------------------------
405
406 @Override
407 public Object getEditableValue() {
408 return null;
409 }
410
411 @Override
412 public IPropertyDescriptor[] getPropertyDescriptors() {
413 return Arrays.copyOf(sfDescriptors, sfDescriptors.length);
414 }
415
416 @Override
417 public Object getPropertyValue(Object id) {
418
419 if (sfName.equals(id)) {
420 return getName();
421 }
422
423 if (sfPath.equals(id)) {
424 return getPath().toString();
425 }
426
427 if (sfLocation.equals(id)) {
428 return getLocation().toString();
429 }
430
431 if (sfExperimentType.equals(id)) {
432 if (getTraceType() != null) {
433 IConfigurationElement ce = sfTraceTypeAttributes.get(getTraceType());
434 if (ce == null) {
435 return ""; //$NON-NLS-1$
436 }
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);
442 }
443 }
444 return ce.getAttribute(TmfTraceType.NAME_ATTR);
445 }
446 }
447
448 return null;
449 }
450
451 @Override
452 public void resetPropertyValue(Object id) {
453 }
454
455 @Override
456 public void setPropertyValue(Object id, Object value) {
457 }
458
459 @Override
460 public boolean isPropertyResettable(Object id) {
461 return false;
462 }
463
464 @Override
465 public boolean isPropertySet(Object id) {
466 return false;
467 }
468
469 /**
470 * Return the suffix for resource names
471 * @return The folder suffix
472 */
473 @Override
474 public String getSuffix() {
475 return sfFolderSuffix;
476 }
477
478 }
This page took 0.042369 seconds and 5 git commands to generate.