Commit | Line | Data |
---|---|---|
f98e9dbe JCK |
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 | ||
c02cb8e4 | 15 | import org.eclipse.core.filesystem.EFS; |
f98e9dbe JCK |
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; | |
537572cd | 20 | import org.eclipse.core.runtime.IPath; |
f98e9dbe | 21 | import org.eclipse.core.runtime.IStatus; |
537572cd | 22 | import org.eclipse.core.runtime.Path; |
c02cb8e4 | 23 | import org.eclipse.jdt.annotation.Nullable; |
f98e9dbe JCK |
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; | |
6eca054d GB |
44 | import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlAnalysisModuleSource; |
45 | import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlUtils; | |
f98e9dbe | 46 | import org.eclipse.tracecompass.internal.tmf.analysis.xml.ui.Activator; |
674c702f | 47 | import org.eclipse.tracecompass.tmf.ui.dialog.TmfFileDialogFactory; |
f98e9dbe JCK |
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; | |
c02cb8e4 MAL |
53 | import org.eclipse.ui.IEditorPart; |
54 | import org.eclipse.ui.IPropertyListener; | |
55 | import org.eclipse.ui.ISaveablePart; | |
f98e9dbe JCK |
56 | import org.eclipse.ui.IWorkbenchPage; |
57 | import org.eclipse.ui.IWorkbenchPart; | |
58 | import org.eclipse.ui.IWorkbenchWindow; | |
59 | import org.eclipse.ui.PlatformUI; | |
c02cb8e4 | 60 | import org.eclipse.ui.ide.IDE; |
f98e9dbe JCK |
61 | |
62 | /** | |
63 | * Dialog for XML analysis files | |
64 | * | |
65 | * @author Jean-Christian Kouame | |
66 | */ | |
67 | public class ManageXMLAnalysisDialog extends Dialog { | |
68 | ||
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; | |
c02cb8e4 | 74 | private Button fEditButton; |
f98e9dbe JCK |
75 | private Label fInvalidFileLabel; |
76 | ||
77 | /** | |
78 | * Constructor | |
79 | * | |
80 | * @param parent | |
81 | * Parent shell of this dialog | |
82 | */ | |
83 | public ManageXMLAnalysisDialog(Shell parent) { | |
84 | super(parent); | |
85 | setShellStyle(SWT.RESIZE | SWT.MAX | getShellStyle()); | |
86 | } | |
87 | ||
88 | @Override | |
89 | protected Control createDialogArea(Composite parent) { | |
90 | getShell().setText(Messages.ManageXMLAnalysisDialog_ManageXmlAnalysesFiles); | |
91 | ||
92 | Composite composite = (Composite) super.createDialogArea(parent); | |
93 | composite.setLayout(new GridLayout(2, false)); | |
94 | ||
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; | |
99 | lcgl.marginWidth = 0; | |
100 | listContainer.setLayout(lcgl); | |
101 | ||
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() { | |
105 | @Override | |
106 | public void widgetDefaultSelected(SelectionEvent e) { | |
107 | } | |
108 | ||
109 | @Override | |
110 | public void widgetSelected(SelectionEvent e) { | |
111 | if (fAnalysesList.getSelectionCount() == 0) { | |
112 | fDeleteButton.setEnabled(false); | |
113 | fExportButton.setEnabled(false); | |
c02cb8e4 | 114 | fEditButton.setEnabled(false); |
f98e9dbe JCK |
115 | } else { |
116 | fDeleteButton.setEnabled(true); | |
117 | fExportButton.setEnabled(true); | |
c02cb8e4 | 118 | fEditButton.setEnabled(true); |
f98e9dbe JCK |
119 | handleSelection(fAnalysesList.getSelection()); |
120 | } | |
121 | } | |
122 | }); | |
123 | ||
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); | |
129 | ||
130 | Composite buttonContainer = new Composite(composite, SWT.NULL); | |
131 | buttonContainer.setLayout(new GridLayout()); | |
132 | buttonContainer.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, false, false)); | |
133 | ||
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() { | |
138 | @Override | |
139 | public void widgetDefaultSelected(SelectionEvent e) { | |
140 | } | |
141 | ||
142 | @Override | |
143 | public void widgetSelected(SelectionEvent e) { | |
144 | importAnalysis(); | |
145 | } | |
146 | }); | |
147 | ||
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() { | |
153 | @Override | |
154 | public void widgetDefaultSelected(SelectionEvent e) { | |
155 | } | |
156 | ||
157 | @Override | |
158 | public void widgetSelected(SelectionEvent e) { | |
159 | exportAnalysis(); | |
160 | } | |
161 | }); | |
162 | ||
c02cb8e4 MAL |
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() { | |
168 | @Override | |
169 | public void widgetDefaultSelected(SelectionEvent e) { | |
170 | } | |
171 | ||
172 | @Override | |
173 | public void widgetSelected(SelectionEvent e) { | |
174 | editAnalysis(); | |
175 | } | |
176 | ||
177 | }); | |
178 | ||
f98e9dbe JCK |
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() { | |
184 | @Override | |
185 | public void widgetDefaultSelected(SelectionEvent e) { | |
186 | } | |
187 | ||
188 | @Override | |
189 | public void widgetSelected(SelectionEvent e) { | |
190 | deleteAnalysis(); | |
191 | } | |
192 | ||
193 | }); | |
194 | ||
195 | fillAnalysesList(); | |
196 | ||
197 | getShell().setMinimumSize(300, 275); | |
198 | return composite; | |
199 | } | |
200 | ||
201 | private void handleSelection(String[] selection) { | |
537572cd BH |
202 | Map<String, File> files = XmlUtils.listFiles(); |
203 | File file = files.get(createXmlFileString(selection[0])); | |
f98e9dbe JCK |
204 | if (file != null && XmlUtils.xmlValidate(file).isOK()) { |
205 | fInvalidFileLabel.setVisible(false); | |
206 | } else { | |
207 | fInvalidFileLabel.setVisible(true); | |
208 | } | |
209 | } | |
210 | ||
537572cd | 211 | private static void deleteSupplementaryFile(String xmlFile) { |
f98e9dbe JCK |
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<>(); | |
537572cd | 216 | java.util.List<String> ids = XmlUtils.getAnalysisIdsFromFile(xmlFile); |
f98e9dbe JCK |
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); | |
230 | closeEditor = true; | |
231 | } | |
232 | } | |
233 | } | |
234 | if (closeEditor) { | |
235 | tElement.closeEditors(); | |
236 | } | |
237 | } | |
238 | } | |
239 | } | |
240 | for (IResource resource : resourceToDelete) { | |
241 | try { | |
242 | resource.delete(false, null); | |
243 | } catch (CoreException e) { | |
244 | Activator.logError(NLS.bind(Messages.ManageXMLAnalysisDialog_DeleteFileError, resource.getName())); | |
245 | } | |
246 | } | |
247 | } | |
248 | ||
249 | @Override | |
250 | protected void createButtonsForButtonBar(Composite parent) { | |
251 | createButton(parent, IDialogConstants.OK_ID, IDialogConstants.CLOSE_LABEL, false); | |
252 | } | |
253 | ||
254 | private void fillAnalysesList() { | |
255 | fAnalysesList.removeAll(); | |
537572cd | 256 | Map<String, File> files = XmlUtils.listFiles(); |
f98e9dbe JCK |
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 | |
537572cd BH |
260 | IPath path = new Path(file); |
261 | fAnalysesList.add(path.removeFileExtension().toString()); | |
f98e9dbe JCK |
262 | } |
263 | fDeleteButton.setEnabled(false); | |
264 | fExportButton.setEnabled(false); | |
265 | } | |
266 | ||
267 | private void importAnalysis() { | |
674c702f | 268 | FileDialog dialog = TmfFileDialogFactory.create(Display.getCurrent().getActiveShell(), SWT.OPEN); |
f98e9dbe JCK |
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(); | |
273 | if (path != null) { | |
274 | File file = new File(path); | |
c02cb8e4 MAL |
275 | if (loadXmlFile(file, true)) { |
276 | fillAnalysesList(); | |
277 | } | |
278 | } | |
279 | } | |
280 | ||
281 | private static boolean loadXmlFile(File file, boolean addFile) { | |
282 | IStatus status = XmlUtils.xmlValidate(file); | |
283 | if (status.isOK()) { | |
284 | deleteSupplementaryFile(file.getName()); | |
285 | if (addFile) { | |
f98e9dbe | 286 | status = XmlUtils.addXmlFile(file); |
f98e9dbe | 287 | } |
c02cb8e4 MAL |
288 | if (status.isOK()) { |
289 | XmlAnalysisModuleSource.notifyModuleChange(); | |
290 | /* | |
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 | |
295 | */ | |
296 | refreshProject(); | |
297 | return true; | |
298 | } | |
299 | ||
300 | Activator.logError(Messages.ManageXMLAnalysisDialog_ImportFileFailed); | |
301 | TraceUtils.displayErrorMsg(Messages.ManageXMLAnalysisDialog_ImportFileFailed, status.getMessage()); | |
302 | } else { | |
303 | Activator.logError(Messages.ManageXMLAnalysisDialog_ImportFileFailed); | |
304 | TraceUtils.displayErrorMsg(Messages.ManageXMLAnalysisDialog_ImportFileFailed, status.getMessage()); | |
f98e9dbe | 305 | } |
c02cb8e4 | 306 | return false; |
f98e9dbe JCK |
307 | } |
308 | ||
309 | private void exportAnalysis() { | |
674c702f | 310 | FileDialog dialog = TmfFileDialogFactory.create(Display.getCurrent().getActiveShell(), SWT.SAVE); |
f98e9dbe JCK |
311 | dialog.setText(NLS.bind(Messages.ManageXMLAnalysisDialog_SelectFileExport, fAnalysesList.getSelection()[0])); |
312 | dialog.setFilterExtensions(new String[] { XML_FILTER_EXTENSION, "*" }); //$NON-NLS-1$ | |
537572cd BH |
313 | String selection = createXmlFileString(fAnalysesList.getSelection()[0]); |
314 | dialog.setFileName(selection); | |
f98e9dbe JCK |
315 | String path = dialog.open(); |
316 | if (path != null) { | |
537572cd BH |
317 | if (!XmlUtils.exportXmlFile(selection, path).isOK()) { |
318 | Activator.logError(NLS.bind(Messages.ManageXMLAnalysisDialog_FailedToExport, selection)); | |
f98e9dbe JCK |
319 | } |
320 | } | |
321 | } | |
322 | ||
c02cb8e4 MAL |
323 | private void editAnalysis() { |
324 | String selection = createXmlFileString(fAnalysesList.getSelection()[0]); | |
325 | @Nullable | |
326 | File file = XmlUtils.listFiles().get(selection); | |
327 | if (file == null) { | |
328 | Activator.logError(NLS.bind(Messages.ManageXMLAnalysisDialog_FailedToEdit, selection)); | |
329 | TraceUtils.displayErrorMsg(NLS.bind(Messages.ManageXMLAnalysisDialog_FailedToEdit, selection), NLS.bind(Messages.ManageXMLAnalysisDialog_FailedToEdit, selection)); | |
330 | return; | |
331 | } | |
332 | try { | |
333 | IEditorPart editorPart = IDE.openEditorOnFileStore(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), EFS.getStore(file.toURI())); | |
334 | editorPart.addPropertyListener(new IPropertyListener() { | |
335 | @Override | |
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); | |
341 | } | |
342 | } | |
343 | } | |
344 | }); | |
345 | close(); | |
346 | } catch (CoreException e) { | |
347 | Activator.logError(NLS.bind(Messages.ManageXMLAnalysisDialog_FailedToEdit, selection)); | |
348 | TraceUtils.displayErrorMsg(NLS.bind(Messages.ManageXMLAnalysisDialog_FailedToEdit, selection), e.getMessage()); | |
349 | } | |
350 | } | |
351 | ||
f98e9dbe JCK |
352 | private void deleteAnalysis() { |
353 | boolean confirm = MessageDialog.openQuestion( | |
354 | getShell(), | |
355 | Messages.ManageXMLAnalysisDialog_DeleteFile, | |
356 | NLS.bind(Messages.ManageXMLAnalysisDialog_DeleteConfirmation, fAnalysesList.getSelection()[0])); | |
357 | if (confirm) { | |
537572cd | 358 | String selection = createXmlFileString(fAnalysesList.getSelection()[0]); |
f98e9dbe | 359 | deleteSupplementaryFile(selection); |
537572cd | 360 | XmlUtils.deleteFile(selection); |
f98e9dbe JCK |
361 | fillAnalysesList(); |
362 | fInvalidFileLabel.setVisible(false); | |
363 | XmlAnalysisModuleSource.notifyModuleChange(); | |
364 | /* | |
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 | |
368 | */ | |
369 | refreshProject(); | |
370 | } | |
371 | } | |
372 | ||
373 | /** | |
374 | * Refresh the selected project with the new XML file import | |
375 | */ | |
376 | private static void refreshProject() { | |
377 | // Check if we are closing down | |
378 | IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); | |
379 | if (window == null) { | |
380 | return; | |
381 | } | |
382 | ||
383 | // Get the selection | |
384 | IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); | |
385 | IWorkbenchPart part = page.getActivePart(); | |
386 | if (part == null) { | |
387 | return; | |
388 | } | |
389 | ISelectionProvider selectionProvider = part.getSite().getSelectionProvider(); | |
390 | if (selectionProvider == null) { | |
391 | return; | |
392 | } | |
393 | ISelection selection = selectionProvider.getSelection(); | |
394 | ||
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(); | |
401 | } | |
402 | } | |
403 | } | |
537572cd BH |
404 | |
405 | private static String createXmlFileString(String baseName) { | |
406 | IPath path = new Path(baseName).addFileExtension(XmlUtils.XML_EXTENSION); | |
407 | return path.toString(); | |
408 | } | |
f98e9dbe | 409 | } |