analysis: Move plugins to their own sub-directory
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / project / model / TmfCommonProjectElement.java
CommitLineData
99504bb8 1/*******************************************************************************
58ffe079 2 * Copyright (c) 2010, 2015 Ericsson, École Polytechnique de Montréal
99504bb8
GB
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 * Bernd Hufmann - Added supplementary files handling (in class TmfTraceElement)
11 * Geneviève Bastien - Copied supplementary files handling from TmfTracElement
16036bc2
GB
12 * Moved to this class code to copy a model element
13 * Renamed from TmfWithFolderElement to TmfCommonProjectElement
339d539c 14 * Patrick Tasse - Add support for folder elements
99504bb8
GB
15 *******************************************************************************/
16
2bdf0193 17package org.eclipse.tracecompass.tmf.ui.project.model;
99504bb8 18
8f5221c2
GB
19import java.io.ByteArrayInputStream;
20import java.io.InputStream;
21import java.util.ArrayList;
22import java.util.HashMap;
23import java.util.List;
24import java.util.Map;
25
339d539c 26import org.eclipse.core.resources.IContainer;
8f5221c2 27import org.eclipse.core.resources.IFile;
99504bb8
GB
28import org.eclipse.core.resources.IFolder;
29import org.eclipse.core.resources.IResource;
8f5221c2 30import org.eclipse.core.resources.ResourcesPlugin;
99504bb8 31import org.eclipse.core.runtime.CoreException;
beb19106 32import org.eclipse.core.runtime.IPath;
99504bb8 33import org.eclipse.core.runtime.NullProgressMonitor;
339d539c 34import org.eclipse.core.runtime.Path;
8f5221c2 35import org.eclipse.osgi.util.NLS;
2bdf0193 36import org.eclipse.tracecompass.internal.tmf.ui.Activator;
3d04a314 37import org.eclipse.tracecompass.internal.tmf.ui.editors.ITmfEventsEditorConstants;
2bdf0193
AM
38import org.eclipse.tracecompass.tmf.core.TmfCommonConstants;
39import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModuleHelper;
40import org.eclipse.tracecompass.tmf.core.analysis.TmfAnalysisManager;
41import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
42import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
43import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
44import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
45import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
46import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
2bdf0193 47import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
8f5221c2
GB
48import org.eclipse.ui.IEditorReference;
49import org.eclipse.ui.IWorkbench;
50import org.eclipse.ui.IWorkbenchPage;
51import org.eclipse.ui.IWorkbenchWindow;
52import org.eclipse.ui.PartInitException;
53import org.eclipse.ui.PlatformUI;
54import org.eclipse.ui.part.FileEditorInput;
99504bb8 55
99504bb8 56/**
16036bc2
GB
57 * Base class for tracing project elements: it implements the common behavior of
58 * all project elements: supplementary files, analysis, types, etc.
99504bb8 59 *
e73a4ba5 60 * @author Geneviève Bastien
99504bb8 61 */
16036bc2 62public abstract class TmfCommonProjectElement extends TmfProjectModelElement {
99504bb8 63
8f5221c2
GB
64 // ------------------------------------------------------------------------
65 // Attributes
66 // ------------------------------------------------------------------------
67
68 // This trace type ID as defined in plugin.xml
69 private String fTraceTypeId = null;
70
71 private static final String BOOKMARKS_HIDDEN_FILE = ".bookmarks"; //$NON-NLS-1$
72
99504bb8
GB
73 // ------------------------------------------------------------------------
74 // Constructors
75 // ------------------------------------------------------------------------
76
99504bb8 77 /**
16036bc2
GB
78 * Constructor. Creates model element.
79 *
80 * @param name
81 * The name of the element
82 * @param resource
83 * The resource.
84 * @param parent
85 * The parent element
99504bb8 86 */
16036bc2 87 public TmfCommonProjectElement(String name, IResource resource, TmfProjectModelElement parent) {
99504bb8 88 super(name, resource, parent);
8f5221c2
GB
89 parent.addChild(this);
90 refreshTraceType();
91 TmfSignalManager.register(this);
92 }
93
94 // ------------------------------------------------------------------------
95 // TmfProjectModelElement
96 // ------------------------------------------------------------------------
97
98 @Override
99 void refreshChildren() {
100
101 /* Refreshes the analysis under this trace */
102 Map<String, TmfAnalysisElement> childrenMap = new HashMap<>();
103 for (TmfAnalysisElement analysis : getAvailableAnalysis()) {
104 childrenMap.put(analysis.getAnalysisId(), analysis);
105 }
106
a4a116c3 107 TraceTypeHelper helper = TmfTraceType.getTraceType(getTraceType());
8f5221c2
GB
108
109 Class<? extends ITmfTrace> traceClass = null;
110
4b3b667b 111 if (helper != null) {
8f5221c2
GB
112 traceClass = helper.getTraceClass();
113 }
114
115 /* Remove all analysis and return */
116 if (traceClass == null) {
117 for (TmfAnalysisElement analysis : childrenMap.values()) {
118 removeChild(analysis);
119 }
120 return;
121 }
122
123 /** Get the base path to put the resource to */
124 IPath path = fResource.getFullPath();
125
126 /* Add all new analysis modules or refresh outputs of existing ones */
127 for (IAnalysisModuleHelper module : TmfAnalysisManager.getAnalysisModules(traceClass).values()) {
128
129 /* If the analysis is not a child of the trace, create it */
130 TmfAnalysisElement analysis = childrenMap.remove(module.getId());
131 if (analysis == null) {
132 /**
133 * No need for the resource to exist, nothing will be done with
134 * it
135 */
136 IFolder newresource = ResourcesPlugin.getWorkspace().getRoot().getFolder(path.append(module.getId()));
9897c39c 137 analysis = new TmfAnalysisElement(module.getName(), newresource, this, module);
8f5221c2
GB
138 }
139 analysis.refreshChildren();
140 }
141
142 /* Remove analysis that are not children of this trace anymore */
143 for (TmfAnalysisElement analysis : childrenMap.values()) {
144 removeChild(analysis);
145 }
146 }
147
148 // ------------------------------------------------------------------------
149 // Operations
150 // ------------------------------------------------------------------------
151
152 /**
153 * Returns the trace type ID.
154 *
155 * @return trace type ID.
156 */
157 public String getTraceType() {
158 return fTraceTypeId;
159 }
160
161 /**
4b3b667b
PT
162 * Refreshes the trace type field by reading the trace type persistent
163 * property of the resource.
8f5221c2
GB
164 */
165 public void refreshTraceType() {
166 try {
4b3b667b 167 fTraceTypeId = TmfTraceType.getTraceTypeId(getResource());
8f5221c2
GB
168 } catch (CoreException e) {
169 Activator.getDefault().logError(NLS.bind(Messages.TmfCommonProjectElement_ErrorRefreshingProperty, getName()), e);
170 }
99504bb8
GB
171 }
172
8f5221c2
GB
173 /**
174 * Instantiate a <code>ITmfTrace</code> object based on the trace type and
175 * the corresponding extension.
176 *
177 * @return the <code>ITmfTrace</code> or <code>null</code> for an error
178 */
179 public abstract ITmfTrace instantiateTrace();
180
99504bb8 181 /**
339d539c
PT
182 * Return the supplementary folder path for this element. The returned path
183 * is relative to the project's supplementary folder.
99504bb8 184 *
339d539c 185 * @return The supplementary folder path for this element
99504bb8 186 */
339d539c
PT
187 protected String getSupplementaryFolderPath() {
188 return getElementPath() + getSuffix();
99504bb8
GB
189 }
190
191 /**
339d539c
PT
192 * Return the element path relative to its common element (traces folder,
193 * experiments folder or experiment element).
e9e2c5ee 194 *
339d539c
PT
195 * @return The element path
196 */
197 public String getElementPath() {
198 ITmfProjectModelElement parent = getParent();
199 while (!(parent instanceof TmfTracesFolder || parent instanceof TmfExperimentElement || parent instanceof TmfExperimentFolder)) {
200 parent = parent.getParent();
201 }
202 IPath path = fResource.getFullPath().makeRelativeTo(parent.getPath());
203 return path.toString();
204 }
205
206 /**
207 * @return The suffix for the supplementary folder
99504bb8
GB
208 */
209 protected String getSuffix() {
210 return ""; //$NON-NLS-1$
211 }
212
8f5221c2
GB
213 /**
214 * Returns a list of TmfTraceElements contained in project element.
215 *
216 * @return a list of TmfTraceElements, empty list if none
217 */
218 public List<TmfTraceElement> getTraces() {
219 return new ArrayList<>();
220 }
221
222 /**
223 * Get the instantiated trace associated with this element.
224 *
225 * @return The instantiated trace or null if trace is not (yet) available
226 */
227 public ITmfTrace getTrace() {
228 for (ITmfTrace trace : TmfTraceManager.getInstance().getOpenedTraces()) {
229 if (trace.getResource().equals(getResource())) {
230 return trace;
231 }
232 }
233 return null;
234 }
235
236 /**
237 * Returns the file resource used to store bookmarks after creating it if
238 * necessary. If the trace resource is a file, it is returned directly. If
239 * the trace resource is a folder, a linked file is returned. The file will
240 * be created if it does not exist.
241 *
242 * @return the bookmarks file
243 * @throws CoreException
244 * if the bookmarks file cannot be created
245 */
246 public abstract IFile createBookmarksFile() throws CoreException;
247
248 /**
249 * Actually returns the bookmark file or creates it in the project element's
250 * folder
251 *
252 * @param bookmarksFolder
253 * Folder where to put the bookmark file
58ffe079
MAL
254 * @param editorInputType
255 * The editor input type to set (trace or experiment)
8f5221c2
GB
256 * @return The bookmark file
257 * @throws CoreException
258 * if the bookmarks file cannot be created
259 */
58ffe079 260 protected IFile createBookmarksFile(IFolder bookmarksFolder, String editorInputType) throws CoreException {
8f5221c2
GB
261 IFile file = getBookmarksFile();
262 if (!file.exists()) {
263 final IFile bookmarksFile = bookmarksFolder.getFile(BOOKMARKS_HIDDEN_FILE);
264 if (!bookmarksFile.exists()) {
265 final InputStream source = new ByteArrayInputStream(new byte[0]);
858a35cf 266 bookmarksFile.create(source, IResource.FORCE | IResource.HIDDEN, null);
8f5221c2 267 }
858a35cf 268 file.createLink(bookmarksFile.getLocation(), IResource.REPLACE | IResource.HIDDEN, null);
58ffe079 269 file.setPersistentProperty(TmfCommonConstants.TRACETYPE, editorInputType);
8f5221c2
GB
270 }
271 return file;
272 }
273
274 /**
275 * Returns the optional editor ID from the trace type extension.
276 *
277 * @return the editor ID or <code>null</code> if not defined.
278 */
279 public abstract String getEditorId();
280
281 /**
282 * Returns the file resource used to store bookmarks. The file may not
283 * exist.
284 *
285 * @return the bookmarks file
286 */
287 public IFile getBookmarksFile() {
288 final IFolder folder = (IFolder) fResource;
289 IFile file = folder.getFile(getName() + '_');
290 return file;
291 }
292
293 /**
294 * Close open editors associated with this experiment.
295 */
296 public void closeEditors() {
297 IFile file = getBookmarksFile();
298 FileEditorInput input = new FileEditorInput(file);
299 IWorkbench wb = PlatformUI.getWorkbench();
300 for (IWorkbenchWindow wbWindow : wb.getWorkbenchWindows()) {
301 for (IWorkbenchPage wbPage : wbWindow.getPages()) {
302 for (IEditorReference editorReference : wbPage.getEditorReferences()) {
303 try {
304 if (editorReference.getEditorInput().equals(input)) {
305 wbPage.closeEditor(editorReference.getEditor(false), false);
306 }
307 } catch (PartInitException e) {
308 Activator.getDefault().logError(NLS.bind(Messages.TmfCommonProjectElement_ErrorClosingEditor, getName()), e);
309 }
310 }
311 }
312 }
313 }
314
315 /**
316 * Get a friendly name for the type of element this common project element
317 * is, to be displayed in UI messages.
318 *
319 * @return A string for the type of project element this object is, for
320 * example "trace" or "experiment"
321 */
322 public abstract String getTypeName();
323
324 /**
325 * Copy this model element
326 *
327 * @param newName
328 * The name of the new element
329 * @param copySuppFiles
330 * Whether to copy supplementary files or not
331 * @return the new Resource object
332 */
333 public IResource copy(final String newName, final boolean copySuppFiles) {
334
335 final IPath newPath = getParent().getResource().getFullPath().addTrailingSeparator().append(newName);
336
337 /* Copy supplementary files first, only if needed */
338 if (copySuppFiles) {
339d539c
PT
339 String newElementPath = new Path(getElementPath()).removeLastSegments(1).append(newName).toString();
340 copySupplementaryFolder(newElementPath);
8f5221c2
GB
341 }
342 /* Copy the trace */
343 try {
344 getResource().copy(newPath, IResource.FORCE | IResource.SHALLOW, null);
e9e2c5ee 345 IResource trace = ((IFolder) getParent().getResource()).findMember(newName);
8f5221c2
GB
346
347 /* Delete any bookmarks file found in copied trace folder */
e9e2c5ee
MK
348 if (trace instanceof IFolder) {
349 IFolder folderTrace = (IFolder) trace;
350 for (IResource member : folderTrace.members()) {
4b3b667b 351 String traceTypeId = TmfTraceType.getTraceTypeId(member);
3d04a314 352 if (ITmfEventsEditorConstants.TRACE_INPUT_TYPE_CONSTANTS.contains(traceTypeId)) {
8f5221c2 353 member.delete(true, null);
3d04a314 354 } else if (ITmfEventsEditorConstants.EXPERIMENT_INPUT_TYPE_CONSTANTS.contains(traceTypeId)) {
8f5221c2
GB
355 member.delete(true, null);
356 }
357 }
358 }
e9e2c5ee 359 return trace;
8f5221c2
GB
360 } catch (CoreException e) {
361
362 }
363 return null;
364 }
365
366 /**
367 * Get the list of analysis elements
368 *
369 * @return Array of analysis elements
370 */
371 public List<TmfAnalysisElement> getAvailableAnalysis() {
372 List<ITmfProjectModelElement> children = getChildren();
373 List<TmfAnalysisElement> analysis = new ArrayList<>();
374 for (ITmfProjectModelElement child : children) {
375 if (child instanceof TmfAnalysisElement) {
376 analysis.add((TmfAnalysisElement) child);
377 }
378 }
379 return analysis;
380 }
381
16036bc2
GB
382 // ------------------------------------------------------------------------
383 // Supplementary files operations
384 // ------------------------------------------------------------------------
385
99504bb8
GB
386 /**
387 * Deletes this element specific supplementary folder.
388 */
389 public void deleteSupplementaryFolder() {
339d539c
PT
390 IFolder supplFolder = getTraceSupplementaryFolder(getSupplementaryFolderPath());
391 try {
392 deleteFolder(supplFolder);
393 } catch (CoreException e) {
394 Activator.getDefault().logError("Error deleting supplementary folder " + supplFolder, e); //$NON-NLS-1$
395 }
396 }
397
398 private static void deleteFolder(IFolder folder) throws CoreException {
399 if (folder.exists()) {
400 folder.delete(true, new NullProgressMonitor());
401 }
402 IContainer parent = folder.getParent();
403 // delete empty folders up to the parent project
404 if (parent instanceof IFolder && (!parent.exists() || parent.members().length == 0)) {
405 deleteFolder((IFolder) parent);
99504bb8
GB
406 }
407 }
408
409 /**
16036bc2 410 * Renames the element specific supplementary folder according to the new
339d539c 411 * element name or path.
99504bb8 412 *
339d539c
PT
413 * @param newElementPath
414 * The new element name or path
99504bb8 415 */
339d539c
PT
416 public void renameSupplementaryFolder(String newElementPath) {
417 IFolder oldSupplFolder = getTraceSupplementaryFolder(getSupplementaryFolderPath());
99504bb8
GB
418
419 // Rename supplementary folder
339d539c
PT
420 try {
421 if (oldSupplFolder.exists()) {
422 IFolder newSupplFolder = prepareTraceSupplementaryFolder(newElementPath + getSuffix(), false);
99504bb8 423 oldSupplFolder.move(newSupplFolder.getFullPath(), true, new NullProgressMonitor());
99504bb8 424 }
339d539c
PT
425 deleteFolder(oldSupplFolder);
426 } catch (CoreException e) {
427 Activator.getDefault().logError("Error renaming supplementary folder " + oldSupplFolder, e); //$NON-NLS-1$
99504bb8
GB
428 }
429 }
430
431 /**
339d539c
PT
432 * Copies the element specific supplementary folder to the new element name
433 * or path.
99504bb8 434 *
339d539c
PT
435 * @param newElementPath
436 * The new element name or path
99504bb8 437 */
339d539c
PT
438 public void copySupplementaryFolder(String newElementPath) {
439 IFolder oldSupplFolder = getTraceSupplementaryFolder(getSupplementaryFolderPath());
99504bb8
GB
440
441 // copy supplementary folder
442 if (oldSupplFolder.exists()) {
443 try {
339d539c 444 IFolder newSupplFolder = prepareTraceSupplementaryFolder(newElementPath + getSuffix(), false);
99504bb8
GB
445 oldSupplFolder.copy(newSupplFolder.getFullPath(), true, new NullProgressMonitor());
446 } catch (CoreException e) {
447 Activator.getDefault().logError("Error renaming supplementary folder " + oldSupplFolder, e); //$NON-NLS-1$
448 }
449 }
450 }
451
452 /**
453 * Copies the element specific supplementary folder a new folder.
454 *
16036bc2
GB
455 * @param destination
456 * The destination folder to copy to.
99504bb8
GB
457 */
458 public void copySupplementaryFolder(IFolder destination) {
339d539c 459 IFolder oldSupplFolder = getTraceSupplementaryFolder(getSupplementaryFolderPath());
99504bb8
GB
460
461 // copy supplementary folder
462 if (oldSupplFolder.exists()) {
463 try {
c2f1c5b6 464 TraceUtils.createFolder((IFolder) destination.getParent(), new NullProgressMonitor());
99504bb8
GB
465 oldSupplFolder.copy(destination.getFullPath(), true, new NullProgressMonitor());
466 } catch (CoreException e) {
467 Activator.getDefault().logError("Error copying supplementary folder " + oldSupplFolder, e); //$NON-NLS-1$
468 }
469 }
470 }
471
99504bb8 472 /**
16036bc2
GB
473 * Refreshes the element specific supplementary folder information. It
474 * creates the folder if not exists. It sets the persistence property of the
475 * trace resource
99504bb8
GB
476 */
477 public void refreshSupplementaryFolder() {
6b44794a
MK
478 IFolder supplFolder = createSupplementaryFolder();
479 try {
480 supplFolder.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
481 } catch (CoreException e) {
482 Activator.getDefault().logError("Error refreshing supplementary folder " + supplFolder, e); //$NON-NLS-1$
483 }
99504bb8
GB
484 }
485
486 /**
487 * Checks if supplementary resource exist or not.
488 *
16036bc2
GB
489 * @return <code>true</code> if one or more files are under the element
490 * supplementary folder
99504bb8
GB
491 */
492 public boolean hasSupplementaryResources() {
493 IResource[] resources = getSupplementaryResources();
494 return (resources.length > 0);
495 }
496
497 /**
498 * Returns the supplementary resources under the trace supplementary folder.
499 *
500 * @return array of resources under the trace supplementary folder.
501 */
502 public IResource[] getSupplementaryResources() {
339d539c 503 IFolder supplFolder = getTraceSupplementaryFolder(getSupplementaryFolderPath());
99504bb8
GB
504 if (supplFolder.exists()) {
505 try {
506 return supplFolder.members();
507 } catch (CoreException e) {
508 Activator.getDefault().logError("Error deleting supplementary folder " + supplFolder, e); //$NON-NLS-1$
509 }
510 }
511 return new IResource[0];
512 }
513
514 /**
515 * Deletes the given resources.
516 *
16036bc2
GB
517 * @param resources
518 * array of resources to delete.
99504bb8
GB
519 */
520 public void deleteSupplementaryResources(IResource[] resources) {
521
522 for (int i = 0; i < resources.length; i++) {
523 try {
524 resources[i].delete(true, new NullProgressMonitor());
525 } catch (CoreException e) {
526 Activator.getDefault().logError("Error deleting supplementary resource " + resources[i], e); //$NON-NLS-1$
527 }
528 }
529 }
530
4726e963
BH
531 /**
532 * Deletes all supplementary resources in the supplementary directory
533 */
534 public void deleteSupplementaryResources() {
535 deleteSupplementaryResources(getSupplementaryResources());
536 }
537
6b44794a 538 private IFolder createSupplementaryFolder() {
339d539c 539 IFolder supplFolder = prepareTraceSupplementaryFolder(getSupplementaryFolderPath(), true);
99504bb8
GB
540
541 try {
cdb43c16 542 fResource.setPersistentProperty(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER, supplFolder.getLocation().toOSString());
99504bb8
GB
543 } catch (CoreException e) {
544 Activator.getDefault().logError("Error setting persistant property " + TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER, e); //$NON-NLS-1$
545 }
6b44794a 546 return supplFolder;
99504bb8
GB
547 }
548
8f5221c2
GB
549 // -------------------------------------------------------
550 // Signal handlers
551 // -------------------------------------------------------
16036bc2 552
beb19106 553 /**
8f5221c2 554 * Handler for the Trace Opened signal
beb19106 555 *
8f5221c2
GB
556 * @param signal
557 * The incoming signal
beb19106 558 */
8f5221c2
GB
559 @TmfSignalHandler
560 public void traceOpened(TmfTraceOpenedSignal signal) {
561 IResource resource = signal.getTrace().getResource();
562 if ((resource == null) || !resource.equals(getResource())) {
563 return;
beb19106 564 }
beb19106 565
8f5221c2 566 getParent().refresh();
beb19106
GB
567 }
568
99504bb8 569}
This page took 0.101436 seconds and 5 git commands to generate.