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