Tmf: Move some TmfTraceElement methods to parent class
[deliverable/tracecompass.git] / org.eclipse.linuxtools.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 *******************************************************************************/
15
16 package org.eclipse.linuxtools.tmf.ui.project.model;
17
18 import java.io.ByteArrayInputStream;
19 import java.io.InputStream;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24
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.ResourcesPlugin;
29 import org.eclipse.core.runtime.CoreException;
30 import org.eclipse.core.runtime.IPath;
31 import org.eclipse.core.runtime.NullProgressMonitor;
32 import org.eclipse.linuxtools.internal.tmf.ui.Activator;
33 import org.eclipse.linuxtools.tmf.core.TmfCommonConstants;
34 import org.eclipse.linuxtools.tmf.core.analysis.IAnalysisModuleHelper;
35 import org.eclipse.linuxtools.tmf.core.analysis.TmfAnalysisManager;
36 import org.eclipse.linuxtools.tmf.core.parsers.custom.CustomTxtTrace;
37 import org.eclipse.linuxtools.tmf.core.parsers.custom.CustomTxtTraceDefinition;
38 import org.eclipse.linuxtools.tmf.core.parsers.custom.CustomXmlTrace;
39 import org.eclipse.linuxtools.tmf.core.parsers.custom.CustomXmlTraceDefinition;
40 import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceType;
41 import org.eclipse.linuxtools.tmf.core.project.model.TraceTypeHelper;
42 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
43 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalManager;
44 import org.eclipse.linuxtools.tmf.core.signal.TmfTraceOpenedSignal;
45 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
46 import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
47 import org.eclipse.linuxtools.tmf.core.trace.TmfTrace;
48 import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
49 import org.eclipse.osgi.util.NLS;
50 import org.eclipse.ui.IEditorReference;
51 import org.eclipse.ui.IWorkbench;
52 import org.eclipse.ui.IWorkbenchPage;
53 import org.eclipse.ui.IWorkbenchWindow;
54 import org.eclipse.ui.PartInitException;
55 import org.eclipse.ui.PlatformUI;
56 import org.eclipse.ui.part.FileEditorInput;
57
58 /**
59 * Base class for tracing project elements: it implements the common behavior of
60 * all project elements: supplementary files, analysis, types, etc.
61 *
62 * @author Geneviève Bastien
63 * @since 3.0
64 */
65 public abstract class TmfCommonProjectElement extends TmfProjectModelElement {
66
67 // ------------------------------------------------------------------------
68 // Attributes
69 // ------------------------------------------------------------------------
70
71 // This trace type ID as defined in plugin.xml
72 private String fTraceTypeId = null;
73
74 private static final String BOOKMARKS_HIDDEN_FILE = ".bookmarks"; //$NON-NLS-1$
75
76 // ------------------------------------------------------------------------
77 // Constructors
78 // ------------------------------------------------------------------------
79
80 /**
81 * Constructor. Creates model element.
82 *
83 * @param name
84 * The name of the element
85 * @param resource
86 * The resource.
87 * @param parent
88 * The parent element
89 */
90 public TmfCommonProjectElement(String name, IResource resource, TmfProjectModelElement parent) {
91 super(name, resource, parent);
92 parent.addChild(this);
93 refreshTraceType();
94 TmfSignalManager.register(this);
95 }
96
97 // ------------------------------------------------------------------------
98 // TmfProjectModelElement
99 // ------------------------------------------------------------------------
100
101 @Override
102 void refreshChildren() {
103
104 /* Refreshes the analysis under this trace */
105 Map<String, TmfAnalysisElement> childrenMap = new HashMap<>();
106 for (TmfAnalysisElement analysis : getAvailableAnalysis()) {
107 childrenMap.put(analysis.getAnalysisId(), analysis);
108 }
109
110 TraceTypeHelper helper = TmfTraceType.getInstance().getTraceType(getTraceType());
111
112 Class<? extends ITmfTrace> traceClass = null;
113
114 if (helper == null && getTraceType() != null) {
115 if (fTraceTypeId.startsWith(CustomTxtTrace.class.getCanonicalName())) {
116 for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) {
117 if (fTraceTypeId.equals(CustomTxtTrace.class.getCanonicalName() + ":" + def.definitionName)) { //$NON-NLS-1$
118 traceClass = CustomTxtTrace.class;
119 }
120 }
121 }
122 if (fTraceTypeId.startsWith(CustomXmlTrace.class.getCanonicalName())) {
123 for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) {
124 if (fTraceTypeId.equals(CustomXmlTrace.class.getCanonicalName() + ":" + def.definitionName)) { //$NON-NLS-1$
125 traceClass = CustomTxtTrace.class;
126 }
127 }
128 }
129 } else if (helper != null) {
130 traceClass = helper.getTraceClass();
131 }
132
133 /* Remove all analysis and return */
134 if (traceClass == null) {
135 for (TmfAnalysisElement analysis : childrenMap.values()) {
136 removeChild(analysis);
137 }
138 return;
139 }
140
141 /** Get the base path to put the resource to */
142 IPath path = fResource.getFullPath();
143
144 /* Add all new analysis modules or refresh outputs of existing ones */
145 for (IAnalysisModuleHelper module : TmfAnalysisManager.getAnalysisModules(traceClass).values()) {
146
147 /* If the analysis is not a child of the trace, create it */
148 TmfAnalysisElement analysis = childrenMap.remove(module.getId());
149 if (analysis == null) {
150 /**
151 * No need for the resource to exist, nothing will be done with
152 * it
153 */
154 IFolder newresource = ResourcesPlugin.getWorkspace().getRoot().getFolder(path.append(module.getId()));
155 analysis = new TmfAnalysisElement(module.getName(), newresource, this, module.getId());
156 }
157 analysis.refreshChildren();
158 }
159
160 /* Remove analysis that are not children of this trace anymore */
161 for (TmfAnalysisElement analysis : childrenMap.values()) {
162 removeChild(analysis);
163 }
164 }
165
166 // ------------------------------------------------------------------------
167 // Operations
168 // ------------------------------------------------------------------------
169
170 /**
171 * Returns the trace type ID.
172 *
173 * @return trace type ID.
174 */
175 public String getTraceType() {
176 return fTraceTypeId;
177 }
178
179 /**
180 * Refreshes the trace type filed by reading the trace type persistent
181 * property of the resource referenece.
182 */
183 public void refreshTraceType() {
184 try {
185 fTraceTypeId = getResource().getPersistentProperty(TmfCommonConstants.TRACETYPE);
186 } catch (CoreException e) {
187 Activator.getDefault().logError(NLS.bind(Messages.TmfCommonProjectElement_ErrorRefreshingProperty, getName()), e);
188 }
189 }
190
191 /**
192 * Instantiate a <code>ITmfTrace</code> object based on the trace type and
193 * the corresponding extension.
194 *
195 * @return the <code>ITmfTrace</code> or <code>null</code> for an error
196 */
197 public abstract ITmfTrace instantiateTrace();
198
199 /**
200 * Return the resource name for this element
201 *
202 * @return The name of the resource for this element
203 */
204 protected String getResourceName() {
205 return fResource.getName() + getSuffix();
206 }
207
208 /**
209 * @return The suffix for resource names
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 copySupplementaryFolder(newName);
344 }
345 /* Copy the trace */
346 try {
347 getResource().copy(newPath, IResource.FORCE | IResource.SHALLOW, null);
348
349 /* Delete any bookmarks file found in copied trace folder */
350 IFolder folder = ((IFolder) getParent().getResource()).getFolder(newName);
351 if (folder.exists()) {
352 for (IResource member : folder.members()) {
353 if (TmfTrace.class.getCanonicalName().equals(member.getPersistentProperty(TmfCommonConstants.TRACETYPE))) {
354 member.delete(true, null);
355 } else if (TmfExperiment.class.getCanonicalName().equals(member.getPersistentProperty(TmfCommonConstants.TRACETYPE))) {
356 member.delete(true, null);
357 }
358 }
359 }
360 return folder;
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
383 // ------------------------------------------------------------------------
384 // Supplementary files operations
385 // ------------------------------------------------------------------------
386
387 /**
388 * Deletes this element specific supplementary folder.
389 */
390 public void deleteSupplementaryFolder() {
391 IFolder supplFolder = getTraceSupplementaryFolder(getResourceName());
392 if (supplFolder.exists()) {
393 try {
394 supplFolder.delete(true, new NullProgressMonitor());
395 } catch (CoreException e) {
396 Activator.getDefault().logError("Error deleting supplementary folder " + supplFolder, e); //$NON-NLS-1$
397 }
398 }
399 }
400
401 /**
402 * Renames the element specific supplementary folder according to the new
403 * element name.
404 *
405 * @param newName
406 * The new element name
407 */
408 public void renameSupplementaryFolder(String newName) {
409 IFolder oldSupplFolder = getTraceSupplementaryFolder(getResourceName());
410 IFolder newSupplFolder = getTraceSupplementaryFolder(newName + getSuffix());
411
412 // Rename supplementary folder
413 if (oldSupplFolder.exists()) {
414 try {
415 oldSupplFolder.move(newSupplFolder.getFullPath(), true, new NullProgressMonitor());
416 } catch (CoreException e) {
417 Activator.getDefault().logError("Error renaming supplementary folder " + oldSupplFolder, e); //$NON-NLS-1$
418 }
419 }
420 }
421
422 /**
423 * Copies the element specific supplementary folder to the new element name.
424 *
425 * @param newName
426 * The new element name
427 */
428 public void copySupplementaryFolder(String newName) {
429 IFolder oldSupplFolder = getTraceSupplementaryFolder(getResourceName());
430 IFolder newSupplFolder = getTraceSupplementaryFolder(newName + getSuffix());
431
432 // copy supplementary folder
433 if (oldSupplFolder.exists()) {
434 try {
435 oldSupplFolder.copy(newSupplFolder.getFullPath(), true, new NullProgressMonitor());
436 } catch (CoreException e) {
437 Activator.getDefault().logError("Error renaming supplementary folder " + oldSupplFolder, e); //$NON-NLS-1$
438 }
439 }
440 }
441
442 /**
443 * Copies the element specific supplementary folder a new folder.
444 *
445 * @param destination
446 * The destination folder to copy to.
447 */
448 public void copySupplementaryFolder(IFolder destination) {
449 IFolder oldSupplFolder = getTraceSupplementaryFolder(getResourceName());
450
451 // copy supplementary folder
452 if (oldSupplFolder.exists()) {
453 try {
454 oldSupplFolder.copy(destination.getFullPath(), true, new NullProgressMonitor());
455 } catch (CoreException e) {
456 Activator.getDefault().logError("Error copying supplementary folder " + oldSupplFolder, e); //$NON-NLS-1$
457 }
458 }
459 }
460
461 /**
462 * Refreshes the element specific supplementary folder information. It
463 * creates the folder if not exists. It sets the persistence property of the
464 * trace resource
465 */
466 public void refreshSupplementaryFolder() {
467 createSupplementaryDirectory();
468 }
469
470 /**
471 * Checks if supplementary resource exist or not.
472 *
473 * @return <code>true</code> if one or more files are under the element
474 * supplementary folder
475 */
476 public boolean hasSupplementaryResources() {
477 IResource[] resources = getSupplementaryResources();
478 return (resources.length > 0);
479 }
480
481 /**
482 * Returns the supplementary resources under the trace supplementary folder.
483 *
484 * @return array of resources under the trace supplementary folder.
485 */
486 public IResource[] getSupplementaryResources() {
487 IFolder supplFolder = getTraceSupplementaryFolder(getResourceName());
488 if (supplFolder.exists()) {
489 try {
490 return supplFolder.members();
491 } catch (CoreException e) {
492 Activator.getDefault().logError("Error deleting supplementary folder " + supplFolder, e); //$NON-NLS-1$
493 }
494 }
495 return new IResource[0];
496 }
497
498 /**
499 * Deletes the given resources.
500 *
501 * @param resources
502 * array of resources to delete.
503 */
504 public void deleteSupplementaryResources(IResource[] resources) {
505
506 for (int i = 0; i < resources.length; i++) {
507 try {
508 resources[i].delete(true, new NullProgressMonitor());
509 } catch (CoreException e) {
510 Activator.getDefault().logError("Error deleting supplementary resource " + resources[i], e); //$NON-NLS-1$
511 }
512 }
513 }
514
515 /**
516 * Deletes all supplementary resources in the supplementary directory
517 */
518 public void deleteSupplementaryResources() {
519 deleteSupplementaryResources(getSupplementaryResources());
520 }
521
522 private void createSupplementaryDirectory() {
523 IFolder supplFolder = getTraceSupplementaryFolder(getResourceName());
524 if (!supplFolder.exists()) {
525 try {
526 supplFolder.create(true, true, new NullProgressMonitor());
527 } catch (CoreException e) {
528 Activator.getDefault().logError("Error creating resource supplementary file " + supplFolder, e); //$NON-NLS-1$
529 }
530 }
531
532 try {
533 fResource.setPersistentProperty(TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER, supplFolder.getLocationURI().getPath());
534 } catch (CoreException e) {
535 Activator.getDefault().logError("Error setting persistant property " + TmfCommonConstants.TRACE_SUPPLEMENTARY_FOLDER, e); //$NON-NLS-1$
536 }
537
538 }
539
540 // -------------------------------------------------------
541 // Signal handlers
542 // -------------------------------------------------------
543
544 /**
545 * Handler for the Trace Opened signal
546 *
547 * @param signal
548 * The incoming signal
549 */
550 @TmfSignalHandler
551 public void traceOpened(TmfTraceOpenedSignal signal) {
552 IResource resource = signal.getTrace().getResource();
553 if ((resource == null) || !resource.equals(getResource())) {
554 return;
555 }
556
557 getParent().refresh();
558 }
559
560 }
This page took 0.045027 seconds and 6 git commands to generate.