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