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
.project
.model
.TmfCommonProjectElement
;
48 import org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
.TmfProjectElement
;
49 import org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
.TmfProjectModelElement
;
50 import org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
.TmfProjectRegistry
;
51 import org
.eclipse
.tracecompass
.tmf
.ui
.project
.model
.TraceUtils
;
52 import org
.eclipse
.ui
.IEditorPart
;
53 import org
.eclipse
.ui
.IPropertyListener
;
54 import org
.eclipse
.ui
.ISaveablePart
;
55 import org
.eclipse
.ui
.IWorkbenchPage
;
56 import org
.eclipse
.ui
.IWorkbenchPart
;
57 import org
.eclipse
.ui
.IWorkbenchWindow
;
58 import org
.eclipse
.ui
.PlatformUI
;
59 import org
.eclipse
.ui
.ide
.IDE
;
62 * Dialog for XML analysis files
64 * @author Jean-Christian Kouame
66 public class ManageXMLAnalysisDialog
extends Dialog
{
68 private final String XML_FILTER_EXTENSION
= "*.xml"; //$NON-NLS-1$
69 private List fAnalysesList
;
70 private Button fDeleteButton
;
71 private Button fImportButton
;
72 private Button fExportButton
;
73 private Button fEditButton
;
74 private Label fInvalidFileLabel
;
80 * Parent shell of this dialog
82 public ManageXMLAnalysisDialog(Shell parent
) {
84 setShellStyle(SWT
.RESIZE
| SWT
.MAX
| getShellStyle());
88 protected Control
createDialogArea(Composite parent
) {
89 getShell().setText(Messages
.ManageXMLAnalysisDialog_ManageXmlAnalysesFiles
);
91 Composite composite
= (Composite
) super.createDialogArea(parent
);
92 composite
.setLayout(new GridLayout(2, false));
94 Composite listContainer
= new Composite(composite
, SWT
.NONE
);
95 listContainer
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
96 GridLayout lcgl
= new GridLayout();
97 lcgl
.marginHeight
= 0;
99 listContainer
.setLayout(lcgl
);
101 fAnalysesList
= new List(listContainer
, SWT
.SINGLE
| SWT
.BORDER
| SWT
.H_SCROLL
| SWT
.V_SCROLL
);
102 fAnalysesList
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
103 fAnalysesList
.addSelectionListener(new SelectionListener() {
105 public void widgetDefaultSelected(SelectionEvent e
) {
109 public void widgetSelected(SelectionEvent e
) {
110 if (fAnalysesList
.getSelectionCount() == 0) {
111 fDeleteButton
.setEnabled(false);
112 fExportButton
.setEnabled(false);
113 fEditButton
.setEnabled(false);
115 fDeleteButton
.setEnabled(true);
116 fExportButton
.setEnabled(true);
117 fEditButton
.setEnabled(true);
118 handleSelection(fAnalysesList
.getSelection());
123 fInvalidFileLabel
= new Label(listContainer
, SWT
.ICON_ERROR
);
124 fInvalidFileLabel
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, false, false));
125 fInvalidFileLabel
.setForeground(getShell().getDisplay().getSystemColor(SWT
.COLOR_RED
));
126 fInvalidFileLabel
.setText(Messages
.ManageXMLAnalysisDialog_FileValidationError
);
127 fInvalidFileLabel
.setVisible(false);
129 Composite buttonContainer
= new Composite(composite
, SWT
.NULL
);
130 buttonContainer
.setLayout(new GridLayout());
131 buttonContainer
.setLayoutData(new GridData(SWT
.CENTER
, SWT
.TOP
, false, false));
133 fImportButton
= new Button(buttonContainer
, SWT
.PUSH
);
134 fImportButton
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, false, false));
135 fImportButton
.setText(Messages
.ManageXMLAnalysisDialog_Import
);
136 fImportButton
.addSelectionListener(new SelectionListener() {
138 public void widgetDefaultSelected(SelectionEvent e
) {
142 public void widgetSelected(SelectionEvent e
) {
147 fExportButton
= new Button(buttonContainer
, SWT
.PUSH
);
148 fExportButton
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, false, false));
149 fExportButton
.setText(Messages
.ManageXMLAnalysisDialog_Export
);
150 fExportButton
.setEnabled(false);
151 fExportButton
.addSelectionListener(new SelectionListener() {
153 public void widgetDefaultSelected(SelectionEvent e
) {
157 public void widgetSelected(SelectionEvent e
) {
162 fEditButton
= new Button(buttonContainer
, SWT
.PUSH
);
163 fEditButton
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, false, false));
164 fEditButton
.setText(Messages
.ManageXMLAnalysisDialog_Edit
);
165 fEditButton
.setEnabled(false);
166 fEditButton
.addSelectionListener(new SelectionListener() {
168 public void widgetDefaultSelected(SelectionEvent e
) {
172 public void widgetSelected(SelectionEvent e
) {
178 fDeleteButton
= new Button(buttonContainer
, SWT
.PUSH
);
179 fDeleteButton
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, false, false));
180 fDeleteButton
.setText(Messages
.ManageXMLAnalysisDialog_Delete
);
181 fDeleteButton
.setEnabled(false);
182 fDeleteButton
.addSelectionListener(new SelectionListener() {
184 public void widgetDefaultSelected(SelectionEvent e
) {
188 public void widgetSelected(SelectionEvent e
) {
196 getShell().setMinimumSize(300, 275);
200 private void handleSelection(String
[] selection
) {
201 Map
<String
, File
> files
= XmlUtils
.listFiles();
202 File file
= files
.get(createXmlFileString(selection
[0]));
203 if (file
!= null && XmlUtils
.xmlValidate(file
).isOK()) {
204 fInvalidFileLabel
.setVisible(false);
206 fInvalidFileLabel
.setVisible(true);
210 private static void deleteSupplementaryFile(String xmlFile
) {
211 // 1. Look for all traces that have this analysis
212 // 2. Close them if they are opened.
213 // 3. Delete the related supplementary files
214 java
.util
.List
<IResource
> resourceToDelete
= new ArrayList
<>();
215 java
.util
.List
<String
> ids
= XmlUtils
.getAnalysisIdsFromFile(xmlFile
);
216 IProject
[] projects
= ResourcesPlugin
.getWorkspace().getRoot().getProjects(0);
217 for (IProject project
: projects
) {
218 TmfProjectElement pElement
= TmfProjectRegistry
.getProject(project
);
219 if (pElement
!= null) {
220 java
.util
.List
<TmfCommonProjectElement
> tElements
= new ArrayList
<>();
221 tElements
.addAll(pElement
.getTracesFolder().getTraces());
222 tElements
.addAll(pElement
.getExperimentsFolder().getExperiments());
223 for (TmfCommonProjectElement tElement
: tElements
) {
224 boolean closeEditor
= false;
225 for (IResource resource
: tElement
.getSupplementaryResources()) {
226 for (String id
: ids
) {
227 if (resource
.getName().startsWith(id
)) {
228 resourceToDelete
.add(resource
);
234 tElement
.closeEditors();
239 for (IResource resource
: resourceToDelete
) {
241 resource
.delete(false, null);
242 } catch (CoreException e
) {
243 Activator
.logError(NLS
.bind(Messages
.ManageXMLAnalysisDialog_DeleteFileError
, resource
.getName()));
249 protected void createButtonsForButtonBar(Composite parent
) {
250 createButton(parent
, IDialogConstants
.OK_ID
, IDialogConstants
.CLOSE_LABEL
, false);
253 private void fillAnalysesList() {
254 fAnalysesList
.removeAll();
255 Map
<String
, File
> files
= XmlUtils
.listFiles();
256 for (String file
: files
.keySet()) {
257 // Remove the extension from the file path. The extension is at the
258 // end of the file path
259 IPath path
= new Path(file
);
260 fAnalysesList
.add(path
.removeFileExtension().toString());
262 fDeleteButton
.setEnabled(false);
263 fExportButton
.setEnabled(false);
266 private void importAnalysis() {
267 FileDialog dialog
= new FileDialog(Display
.getCurrent().getActiveShell(), SWT
.OPEN
);
268 dialog
.setText(Messages
.ManageXMLAnalysisDialog_SelectFileImport
);
269 dialog
.setFilterNames(new String
[] { Messages
.ManageXMLAnalysisDialog_ImportXmlFile
+ " (*.xml)" }); //$NON-NLS-1$
270 dialog
.setFilterExtensions(new String
[] { XML_FILTER_EXTENSION
});
271 String path
= dialog
.open();
273 File file
= new File(path
);
274 if (loadXmlFile(file
, true)) {
280 private static boolean loadXmlFile(File file
, boolean addFile
) {
281 IStatus status
= XmlUtils
.xmlValidate(file
);
283 deleteSupplementaryFile(file
.getName());
285 status
= XmlUtils
.addXmlFile(file
);
288 XmlAnalysisModuleSource
.notifyModuleChange();
290 * FIXME: It refreshes the list of analysis under a trace,
291 * but since modules are instantiated when the trace opens,
292 * the changes won't apply to an opened trace, it needs to
293 * be closed then reopened
299 Activator
.logError(Messages
.ManageXMLAnalysisDialog_ImportFileFailed
);
300 TraceUtils
.displayErrorMsg(Messages
.ManageXMLAnalysisDialog_ImportFileFailed
, status
.getMessage());
302 Activator
.logError(Messages
.ManageXMLAnalysisDialog_ImportFileFailed
);
303 TraceUtils
.displayErrorMsg(Messages
.ManageXMLAnalysisDialog_ImportFileFailed
, status
.getMessage());
308 private void exportAnalysis() {
309 FileDialog dialog
= new FileDialog(Display
.getCurrent().getActiveShell(), SWT
.SAVE
);
310 dialog
.setText(NLS
.bind(Messages
.ManageXMLAnalysisDialog_SelectFileExport
, fAnalysesList
.getSelection()[0]));
311 dialog
.setFilterExtensions(new String
[] { XML_FILTER_EXTENSION
, "*" }); //$NON-NLS-1$
312 String selection
= createXmlFileString(fAnalysesList
.getSelection()[0]);
313 dialog
.setFileName(selection
);
314 String path
= dialog
.open();
316 if (!XmlUtils
.exportXmlFile(selection
, path
).isOK()) {
317 Activator
.logError(NLS
.bind(Messages
.ManageXMLAnalysisDialog_FailedToExport
, selection
));
322 private void editAnalysis() {
323 String selection
= createXmlFileString(fAnalysesList
.getSelection()[0]);
325 File file
= XmlUtils
.listFiles().get(selection
);
327 Activator
.logError(NLS
.bind(Messages
.ManageXMLAnalysisDialog_FailedToEdit
, selection
));
328 TraceUtils
.displayErrorMsg(NLS
.bind(Messages
.ManageXMLAnalysisDialog_FailedToEdit
, selection
), NLS
.bind(Messages
.ManageXMLAnalysisDialog_FailedToEdit
, selection
));
332 IEditorPart editorPart
= IDE
.openEditorOnFileStore(PlatformUI
.getWorkbench().getActiveWorkbenchWindow().getActivePage(), EFS
.getStore(file
.toURI()));
333 editorPart
.addPropertyListener(new IPropertyListener() {
335 public void propertyChanged(Object source
, int propId
) {
336 if (ISaveablePart
.PROP_DIRTY
== propId
) {
337 if (!editorPart
.isDirty()) {
338 // Editor is not dirty anymore, i.e. it was saved
339 loadXmlFile(file
, false);
345 } catch (CoreException e
) {
346 Activator
.logError(NLS
.bind(Messages
.ManageXMLAnalysisDialog_FailedToEdit
, selection
));
347 TraceUtils
.displayErrorMsg(NLS
.bind(Messages
.ManageXMLAnalysisDialog_FailedToEdit
, selection
), e
.getMessage());
351 private void deleteAnalysis() {
352 boolean confirm
= MessageDialog
.openQuestion(
354 Messages
.ManageXMLAnalysisDialog_DeleteFile
,
355 NLS
.bind(Messages
.ManageXMLAnalysisDialog_DeleteConfirmation
, fAnalysesList
.getSelection()[0]));
357 String selection
= createXmlFileString(fAnalysesList
.getSelection()[0]);
358 deleteSupplementaryFile(selection
);
359 XmlUtils
.deleteFile(selection
);
361 fInvalidFileLabel
.setVisible(false);
362 XmlAnalysisModuleSource
.notifyModuleChange();
364 * FIXME: It refreshes the list of analysis under a trace, but since
365 * modules are instantiated when the trace opens, the changes won't
366 * apply to an opened trace, it needs to be closed then reopened
373 * Refresh the selected project with the new XML file import
375 private static void refreshProject() {
376 // Check if we are closing down
377 IWorkbenchWindow window
= PlatformUI
.getWorkbench().getActiveWorkbenchWindow();
378 if (window
== null) {
383 IWorkbenchPage page
= PlatformUI
.getWorkbench().getActiveWorkbenchWindow().getActivePage();
384 IWorkbenchPart part
= page
.getActivePart();
388 ISelectionProvider selectionProvider
= part
.getSite().getSelectionProvider();
389 if (selectionProvider
== null) {
392 ISelection selection
= selectionProvider
.getSelection();
394 if (selection
instanceof TreeSelection
) {
395 TreeSelection sel
= (TreeSelection
) selection
;
396 // There should be only one item selected as per the plugin.xml
397 Object element
= sel
.getFirstElement();
398 if (element
instanceof TmfProjectModelElement
) {
399 ((TmfProjectModelElement
) element
).getProject().refresh();
404 private static String
createXmlFileString(String baseName
) {
405 IPath path
= new Path(baseName
).addFileExtension(XmlUtils
.XML_EXTENSION
);
406 return path
.toString();