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