1 /*******************************************************************************
2 * Copyright (c) 2016 Ericsson
4 * All rights reserved. This program and the accompanying materials are made
5 * 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 package org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.ui
.handler
;
12 import java
.util
.ArrayList
;
15 import org
.eclipse
.core
.filesystem
.EFS
;
16 import org
.eclipse
.core
.resources
.IProject
;
17 import org
.eclipse
.core
.resources
.IResource
;
18 import org
.eclipse
.core
.resources
.ResourcesPlugin
;
19 import org
.eclipse
.core
.runtime
.CoreException
;
20 import org
.eclipse
.core
.runtime
.IPath
;
21 import org
.eclipse
.core
.runtime
.IStatus
;
22 import org
.eclipse
.core
.runtime
.Path
;
23 import org
.eclipse
.jdt
.annotation
.Nullable
;
24 import org
.eclipse
.jface
.dialogs
.Dialog
;
25 import org
.eclipse
.jface
.dialogs
.IDialogConstants
;
26 import org
.eclipse
.jface
.dialogs
.MessageDialog
;
27 import org
.eclipse
.jface
.viewers
.ISelection
;
28 import org
.eclipse
.jface
.viewers
.ISelectionProvider
;
29 import org
.eclipse
.jface
.viewers
.TreeSelection
;
30 import org
.eclipse
.osgi
.util
.NLS
;
31 import org
.eclipse
.swt
.SWT
;
32 import org
.eclipse
.swt
.events
.SelectionEvent
;
33 import org
.eclipse
.swt
.events
.SelectionListener
;
34 import org
.eclipse
.swt
.layout
.GridData
;
35 import org
.eclipse
.swt
.layout
.GridLayout
;
36 import org
.eclipse
.swt
.widgets
.Button
;
37 import org
.eclipse
.swt
.widgets
.Composite
;
38 import org
.eclipse
.swt
.widgets
.Control
;
39 import org
.eclipse
.swt
.widgets
.Display
;
40 import org
.eclipse
.swt
.widgets
.FileDialog
;
41 import org
.eclipse
.swt
.widgets
.Label
;
42 import org
.eclipse
.swt
.widgets
.List
;
43 import org
.eclipse
.swt
.widgets
.Shell
;
44 import org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.module
.XmlAnalysisModuleSource
;
45 import org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.core
.module
.XmlUtils
;
46 import org
.eclipse
.tracecompass
.internal
.tmf
.analysis
.xml
.ui
.Activator
;
47 import org
.eclipse
.tracecompass
.tmf
.ui
.dialog
.TmfFileDialogFactory
;
48 import org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
.TmfCommonProjectElement
;
49 import org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
.TmfProjectElement
;
50 import org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
.TmfProjectModelElement
;
51 import org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
.TmfProjectRegistry
;
52 import org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
.TraceUtils
;
53 import org
.eclipse
.ui
.IEditorPart
;
54 import org
.eclipse
.ui
.IPropertyListener
;
55 import org
.eclipse
.ui
.ISaveablePart
;
56 import org
.eclipse
.ui
.IWorkbenchPage
;
57 import org
.eclipse
.ui
.IWorkbenchPart
;
58 import org
.eclipse
.ui
.IWorkbenchWindow
;
59 import org
.eclipse
.ui
.PlatformUI
;
60 import org
.eclipse
.ui
.ide
.IDE
;
63 * Dialog for XML analysis files
65 * @author Jean-Christian Kouame
67 public class ManageXMLAnalysisDialog
extends Dialog
{
69 private final String XML_FILTER_EXTENSION
= "*.xml"; //$NON-NLS-1$
70 private List fAnalysesList
;
71 private Button fDeleteButton
;
72 private Button fImportButton
;
73 private Button fExportButton
;
74 private Button fEditButton
;
75 private Label fInvalidFileLabel
;
81 * Parent shell of this dialog
83 public ManageXMLAnalysisDialog(Shell parent
) {
85 setShellStyle(SWT
.RESIZE
| SWT
.MAX
| getShellStyle());
89 protected Control
createDialogArea(Composite parent
) {
90 getShell().setText(Messages
.ManageXMLAnalysisDialog_ManageXmlAnalysesFiles
);
92 Composite composite
= (Composite
) super.createDialogArea(parent
);
93 composite
.setLayout(new GridLayout(2, false));
95 Composite listContainer
= new Composite(composite
, SWT
.NONE
);
96 listContainer
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
97 GridLayout lcgl
= new GridLayout();
98 lcgl
.marginHeight
= 0;
100 listContainer
.setLayout(lcgl
);
102 fAnalysesList
= new List(listContainer
, SWT
.SINGLE
| SWT
.BORDER
| SWT
.H_SCROLL
| SWT
.V_SCROLL
);
103 fAnalysesList
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
104 fAnalysesList
.addSelectionListener(new SelectionListener() {
106 public void widgetDefaultSelected(SelectionEvent e
) {
110 public void widgetSelected(SelectionEvent e
) {
111 if (fAnalysesList
.getSelectionCount() == 0) {
112 fDeleteButton
.setEnabled(false);
113 fExportButton
.setEnabled(false);
114 fEditButton
.setEnabled(false);
116 fDeleteButton
.setEnabled(true);
117 fExportButton
.setEnabled(true);
118 fEditButton
.setEnabled(true);
119 handleSelection(fAnalysesList
.getSelection());
124 fInvalidFileLabel
= new Label(listContainer
, SWT
.ICON_ERROR
);
125 fInvalidFileLabel
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, false, false));
126 fInvalidFileLabel
.setForeground(getShell().getDisplay().getSystemColor(SWT
.COLOR_RED
));
127 fInvalidFileLabel
.setText(Messages
.ManageXMLAnalysisDialog_FileValidationError
);
128 fInvalidFileLabel
.setVisible(false);
130 Composite buttonContainer
= new Composite(composite
, SWT
.NULL
);
131 buttonContainer
.setLayout(new GridLayout());
132 buttonContainer
.setLayoutData(new GridData(SWT
.CENTER
, SWT
.TOP
, false, false));
134 fImportButton
= new Button(buttonContainer
, SWT
.PUSH
);
135 fImportButton
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, false, false));
136 fImportButton
.setText(Messages
.ManageXMLAnalysisDialog_Import
);
137 fImportButton
.addSelectionListener(new SelectionListener() {
139 public void widgetDefaultSelected(SelectionEvent e
) {
143 public void widgetSelected(SelectionEvent e
) {
148 fExportButton
= new Button(buttonContainer
, SWT
.PUSH
);
149 fExportButton
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, false, false));
150 fExportButton
.setText(Messages
.ManageXMLAnalysisDialog_Export
);
151 fExportButton
.setEnabled(false);
152 fExportButton
.addSelectionListener(new SelectionListener() {
154 public void widgetDefaultSelected(SelectionEvent e
) {
158 public void widgetSelected(SelectionEvent e
) {
163 fEditButton
= new Button(buttonContainer
, SWT
.PUSH
);
164 fEditButton
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, false, false));
165 fEditButton
.setText(Messages
.ManageXMLAnalysisDialog_Edit
);
166 fEditButton
.setEnabled(false);
167 fEditButton
.addSelectionListener(new SelectionListener() {
169 public void widgetDefaultSelected(SelectionEvent e
) {
173 public void widgetSelected(SelectionEvent e
) {
179 fDeleteButton
= new Button(buttonContainer
, SWT
.PUSH
);
180 fDeleteButton
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, false, false));
181 fDeleteButton
.setText(Messages
.ManageXMLAnalysisDialog_Delete
);
182 fDeleteButton
.setEnabled(false);
183 fDeleteButton
.addSelectionListener(new SelectionListener() {
185 public void widgetDefaultSelected(SelectionEvent e
) {
189 public void widgetSelected(SelectionEvent e
) {
197 getShell().setMinimumSize(300, 275);
201 private void handleSelection(String
[] selection
) {
202 Map
<String
, File
> files
= XmlUtils
.listFiles();
203 File file
= files
.get(createXmlFileString(selection
[0]));
204 if (file
!= null && XmlUtils
.xmlValidate(file
).isOK()) {
205 fInvalidFileLabel
.setVisible(false);
207 fInvalidFileLabel
.setVisible(true);
211 private static void deleteSupplementaryFile(String xmlFile
) {
212 // 1. Look for all traces that have this analysis
213 // 2. Close them if they are opened.
214 // 3. Delete the related supplementary files
215 java
.util
.List
<IResource
> resourceToDelete
= new ArrayList
<>();
216 java
.util
.List
<String
> ids
= XmlUtils
.getAnalysisIdsFromFile(xmlFile
);
217 IProject
[] projects
= ResourcesPlugin
.getWorkspace().getRoot().getProjects(0);
218 for (IProject project
: projects
) {
219 TmfProjectElement pElement
= TmfProjectRegistry
.getProject(project
);
220 if (pElement
!= null) {
221 java
.util
.List
<TmfCommonProjectElement
> tElements
= new ArrayList
<>();
222 tElements
.addAll(pElement
.getTracesFolder().getTraces());
223 tElements
.addAll(pElement
.getExperimentsFolder().getExperiments());
224 for (TmfCommonProjectElement tElement
: tElements
) {
225 boolean closeEditor
= false;
226 for (IResource resource
: tElement
.getSupplementaryResources()) {
227 for (String id
: ids
) {
228 if (resource
.getName().startsWith(id
)) {
229 resourceToDelete
.add(resource
);
235 tElement
.closeEditors();
240 for (IResource resource
: resourceToDelete
) {
242 resource
.delete(false, null);
243 } catch (CoreException e
) {
244 Activator
.logError(NLS
.bind(Messages
.ManageXMLAnalysisDialog_DeleteFileError
, resource
.getName()));
250 protected void createButtonsForButtonBar(Composite parent
) {
251 createButton(parent
, IDialogConstants
.OK_ID
, IDialogConstants
.CLOSE_LABEL
, false);
254 private void fillAnalysesList() {
255 fAnalysesList
.removeAll();
256 Map
<String
, File
> files
= XmlUtils
.listFiles();
257 for (String file
: files
.keySet()) {
258 // Remove the extension from the file path. The extension is at the
259 // end of the file path
260 IPath path
= new Path(file
);
261 fAnalysesList
.add(path
.removeFileExtension().toString());
263 fDeleteButton
.setEnabled(false);
264 fExportButton
.setEnabled(false);
267 private void importAnalysis() {
268 FileDialog dialog
= TmfFileDialogFactory
.create(Display
.getCurrent().getActiveShell(), SWT
.OPEN
);
269 dialog
.setText(Messages
.ManageXMLAnalysisDialog_SelectFileImport
);
270 dialog
.setFilterNames(new String
[] { Messages
.ManageXMLAnalysisDialog_ImportXmlFile
+ " (*.xml)" }); //$NON-NLS-1$
271 dialog
.setFilterExtensions(new String
[] { XML_FILTER_EXTENSION
});
272 String path
= dialog
.open();
274 File file
= new File(path
);
275 if (loadXmlFile(file
, true)) {
281 private static boolean loadXmlFile(File file
, boolean addFile
) {
282 IStatus status
= XmlUtils
.xmlValidate(file
);
284 deleteSupplementaryFile(file
.getName());
286 status
= XmlUtils
.addXmlFile(file
);
289 XmlAnalysisModuleSource
.notifyModuleChange();
291 * FIXME: It refreshes the list of analysis under a trace,
292 * but since modules are instantiated when the trace opens,
293 * the changes won't apply to an opened trace, it needs to
294 * be closed then reopened
300 Activator
.logError(Messages
.ManageXMLAnalysisDialog_ImportFileFailed
);
301 TraceUtils
.displayErrorMsg(Messages
.ManageXMLAnalysisDialog_ImportFileFailed
, status
.getMessage());
303 Activator
.logError(Messages
.ManageXMLAnalysisDialog_ImportFileFailed
);
304 TraceUtils
.displayErrorMsg(Messages
.ManageXMLAnalysisDialog_ImportFileFailed
, status
.getMessage());
309 private void exportAnalysis() {
310 FileDialog dialog
= TmfFileDialogFactory
.create(Display
.getCurrent().getActiveShell(), SWT
.SAVE
);
311 dialog
.setText(NLS
.bind(Messages
.ManageXMLAnalysisDialog_SelectFileExport
, fAnalysesList
.getSelection()[0]));
312 dialog
.setFilterExtensions(new String
[] { XML_FILTER_EXTENSION
, "*" }); //$NON-NLS-1$
313 String selection
= createXmlFileString(fAnalysesList
.getSelection()[0]);
314 dialog
.setFileName(selection
);
315 String path
= dialog
.open();
317 if (!XmlUtils
.exportXmlFile(selection
, path
).isOK()) {
318 Activator
.logError(NLS
.bind(Messages
.ManageXMLAnalysisDialog_FailedToExport
, selection
));
323 private void editAnalysis() {
324 String selection
= createXmlFileString(fAnalysesList
.getSelection()[0]);
326 File file
= XmlUtils
.listFiles().get(selection
);
328 Activator
.logError(NLS
.bind(Messages
.ManageXMLAnalysisDialog_FailedToEdit
, selection
));
329 TraceUtils
.displayErrorMsg(NLS
.bind(Messages
.ManageXMLAnalysisDialog_FailedToEdit
, selection
), NLS
.bind(Messages
.ManageXMLAnalysisDialog_FailedToEdit
, selection
));
333 IEditorPart editorPart
= IDE
.openEditorOnFileStore(PlatformUI
.getWorkbench().getActiveWorkbenchWindow().getActivePage(), EFS
.getStore(file
.toURI()));
334 editorPart
.addPropertyListener(new IPropertyListener() {
336 public void propertyChanged(Object source
, int propId
) {
337 if (ISaveablePart
.PROP_DIRTY
== propId
) {
338 if (!editorPart
.isDirty()) {
339 // Editor is not dirty anymore, i.e. it was saved
340 loadXmlFile(file
, false);
346 } catch (CoreException e
) {
347 Activator
.logError(NLS
.bind(Messages
.ManageXMLAnalysisDialog_FailedToEdit
, selection
));
348 TraceUtils
.displayErrorMsg(NLS
.bind(Messages
.ManageXMLAnalysisDialog_FailedToEdit
, selection
), e
.getMessage());
352 private void deleteAnalysis() {
353 boolean confirm
= MessageDialog
.openQuestion(
355 Messages
.ManageXMLAnalysisDialog_DeleteFile
,
356 NLS
.bind(Messages
.ManageXMLAnalysisDialog_DeleteConfirmation
, fAnalysesList
.getSelection()[0]));
358 String selection
= createXmlFileString(fAnalysesList
.getSelection()[0]);
359 deleteSupplementaryFile(selection
);
360 XmlUtils
.deleteFile(selection
);
362 fInvalidFileLabel
.setVisible(false);
363 XmlAnalysisModuleSource
.notifyModuleChange();
365 * FIXME: It refreshes the list of analysis under a trace, but since
366 * modules are instantiated when the trace opens, the changes won't
367 * apply to an opened trace, it needs to be closed then reopened
374 * Refresh the selected project with the new XML file import
376 private static void refreshProject() {
377 // Check if we are closing down
378 IWorkbenchWindow window
= PlatformUI
.getWorkbench().getActiveWorkbenchWindow();
379 if (window
== null) {
384 IWorkbenchPage page
= PlatformUI
.getWorkbench().getActiveWorkbenchWindow().getActivePage();
385 IWorkbenchPart part
= page
.getActivePart();
389 ISelectionProvider selectionProvider
= part
.getSite().getSelectionProvider();
390 if (selectionProvider
== null) {
393 ISelection selection
= selectionProvider
.getSelection();
395 if (selection
instanceof TreeSelection
) {
396 TreeSelection sel
= (TreeSelection
) selection
;
397 // There should be only one item selected as per the plugin.xml
398 Object element
= sel
.getFirstElement();
399 if (element
instanceof TmfProjectModelElement
) {
400 ((TmfProjectModelElement
) element
).getProject().refresh();
405 private static String
createXmlFileString(String baseName
) {
406 IPath path
= new Path(baseName
).addFileExtension(XmlUtils
.XML_EXTENSION
);
407 return path
.toString();