ed79990dd117562d644acab7456e26ae519fa566
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.analysis.xml.ui / src / org / eclipse / tracecompass / internal / tmf / analysis / xml / ui / handler / ManageXMLAnalysisDialog.java
1 /*******************************************************************************
2 * Copyright (c) 2016 Ericsson
3 *
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;
10
11 import java.io.File;
12 import java.util.ArrayList;
13 import java.util.Map;
14
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;
60
61 /**
62 * Dialog for XML analysis files
63 *
64 * @author Jean-Christian Kouame
65 */
66 public class ManageXMLAnalysisDialog extends Dialog {
67
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;
75
76 /**
77 * Constructor
78 *
79 * @param parent
80 * Parent shell of this dialog
81 */
82 public ManageXMLAnalysisDialog(Shell parent) {
83 super(parent);
84 setShellStyle(SWT.RESIZE | SWT.MAX | getShellStyle());
85 }
86
87 @Override
88 protected Control createDialogArea(Composite parent) {
89 getShell().setText(Messages.ManageXMLAnalysisDialog_ManageXmlAnalysesFiles);
90
91 Composite composite = (Composite) super.createDialogArea(parent);
92 composite.setLayout(new GridLayout(2, false));
93
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;
98 lcgl.marginWidth = 0;
99 listContainer.setLayout(lcgl);
100
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() {
104 @Override
105 public void widgetDefaultSelected(SelectionEvent e) {
106 }
107
108 @Override
109 public void widgetSelected(SelectionEvent e) {
110 if (fAnalysesList.getSelectionCount() == 0) {
111 fDeleteButton.setEnabled(false);
112 fExportButton.setEnabled(false);
113 fEditButton.setEnabled(false);
114 } else {
115 fDeleteButton.setEnabled(true);
116 fExportButton.setEnabled(true);
117 fEditButton.setEnabled(true);
118 handleSelection(fAnalysesList.getSelection());
119 }
120 }
121 });
122
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);
128
129 Composite buttonContainer = new Composite(composite, SWT.NULL);
130 buttonContainer.setLayout(new GridLayout());
131 buttonContainer.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, false, false));
132
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() {
137 @Override
138 public void widgetDefaultSelected(SelectionEvent e) {
139 }
140
141 @Override
142 public void widgetSelected(SelectionEvent e) {
143 importAnalysis();
144 }
145 });
146
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() {
152 @Override
153 public void widgetDefaultSelected(SelectionEvent e) {
154 }
155
156 @Override
157 public void widgetSelected(SelectionEvent e) {
158 exportAnalysis();
159 }
160 });
161
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() {
167 @Override
168 public void widgetDefaultSelected(SelectionEvent e) {
169 }
170
171 @Override
172 public void widgetSelected(SelectionEvent e) {
173 editAnalysis();
174 }
175
176 });
177
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() {
183 @Override
184 public void widgetDefaultSelected(SelectionEvent e) {
185 }
186
187 @Override
188 public void widgetSelected(SelectionEvent e) {
189 deleteAnalysis();
190 }
191
192 });
193
194 fillAnalysesList();
195
196 getShell().setMinimumSize(300, 275);
197 return composite;
198 }
199
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);
205 } else {
206 fInvalidFileLabel.setVisible(true);
207 }
208 }
209
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);
229 closeEditor = true;
230 }
231 }
232 }
233 if (closeEditor) {
234 tElement.closeEditors();
235 }
236 }
237 }
238 }
239 for (IResource resource : resourceToDelete) {
240 try {
241 resource.delete(false, null);
242 } catch (CoreException e) {
243 Activator.logError(NLS.bind(Messages.ManageXMLAnalysisDialog_DeleteFileError, resource.getName()));
244 }
245 }
246 }
247
248 @Override
249 protected void createButtonsForButtonBar(Composite parent) {
250 createButton(parent, IDialogConstants.OK_ID, IDialogConstants.CLOSE_LABEL, false);
251 }
252
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());
261 }
262 fDeleteButton.setEnabled(false);
263 fExportButton.setEnabled(false);
264 }
265
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();
272 if (path != null) {
273 File file = new File(path);
274 if (loadXmlFile(file, true)) {
275 fillAnalysesList();
276 }
277 }
278 }
279
280 private static boolean loadXmlFile(File file, boolean addFile) {
281 IStatus status = XmlUtils.xmlValidate(file);
282 if (status.isOK()) {
283 deleteSupplementaryFile(file.getName());
284 if (addFile) {
285 status = XmlUtils.addXmlFile(file);
286 }
287 if (status.isOK()) {
288 XmlAnalysisModuleSource.notifyModuleChange();
289 /*
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
294 */
295 refreshProject();
296 return true;
297 }
298
299 Activator.logError(Messages.ManageXMLAnalysisDialog_ImportFileFailed);
300 TraceUtils.displayErrorMsg(Messages.ManageXMLAnalysisDialog_ImportFileFailed, status.getMessage());
301 } else {
302 Activator.logError(Messages.ManageXMLAnalysisDialog_ImportFileFailed);
303 TraceUtils.displayErrorMsg(Messages.ManageXMLAnalysisDialog_ImportFileFailed, status.getMessage());
304 }
305 return false;
306 }
307
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();
315 if (path != null) {
316 if (!XmlUtils.exportXmlFile(selection, path).isOK()) {
317 Activator.logError(NLS.bind(Messages.ManageXMLAnalysisDialog_FailedToExport, selection));
318 }
319 }
320 }
321
322 private void editAnalysis() {
323 String selection = createXmlFileString(fAnalysesList.getSelection()[0]);
324 @Nullable
325 File file = XmlUtils.listFiles().get(selection);
326 if (file == null) {
327 Activator.logError(NLS.bind(Messages.ManageXMLAnalysisDialog_FailedToEdit, selection));
328 TraceUtils.displayErrorMsg(NLS.bind(Messages.ManageXMLAnalysisDialog_FailedToEdit, selection), NLS.bind(Messages.ManageXMLAnalysisDialog_FailedToEdit, selection));
329 return;
330 }
331 try {
332 IEditorPart editorPart = IDE.openEditorOnFileStore(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), EFS.getStore(file.toURI()));
333 editorPart.addPropertyListener(new IPropertyListener() {
334 @Override
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);
340 }
341 }
342 }
343 });
344 close();
345 } catch (CoreException e) {
346 Activator.logError(NLS.bind(Messages.ManageXMLAnalysisDialog_FailedToEdit, selection));
347 TraceUtils.displayErrorMsg(NLS.bind(Messages.ManageXMLAnalysisDialog_FailedToEdit, selection), e.getMessage());
348 }
349 }
350
351 private void deleteAnalysis() {
352 boolean confirm = MessageDialog.openQuestion(
353 getShell(),
354 Messages.ManageXMLAnalysisDialog_DeleteFile,
355 NLS.bind(Messages.ManageXMLAnalysisDialog_DeleteConfirmation, fAnalysesList.getSelection()[0]));
356 if (confirm) {
357 String selection = createXmlFileString(fAnalysesList.getSelection()[0]);
358 deleteSupplementaryFile(selection);
359 XmlUtils.deleteFile(selection);
360 fillAnalysesList();
361 fInvalidFileLabel.setVisible(false);
362 XmlAnalysisModuleSource.notifyModuleChange();
363 /*
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
367 */
368 refreshProject();
369 }
370 }
371
372 /**
373 * Refresh the selected project with the new XML file import
374 */
375 private static void refreshProject() {
376 // Check if we are closing down
377 IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
378 if (window == null) {
379 return;
380 }
381
382 // Get the selection
383 IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
384 IWorkbenchPart part = page.getActivePart();
385 if (part == null) {
386 return;
387 }
388 ISelectionProvider selectionProvider = part.getSite().getSelectionProvider();
389 if (selectionProvider == null) {
390 return;
391 }
392 ISelection selection = selectionProvider.getSelection();
393
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();
400 }
401 }
402 }
403
404 private static String createXmlFileString(String baseName) {
405 IPath path = new Path(baseName).addFileExtension(XmlUtils.XML_EXTENSION);
406 return path.toString();
407 }
408 }
This page took 0.043787 seconds and 4 git commands to generate.