tmf: Move TmfWorkspaceModifyOperation to public package
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / internal / tmf / ui / project / handlers / TrimTraceHandler.java
CommitLineData
c9694d54
AM
1/*******************************************************************************
2 * Copyright (c) 2016 EfficiOS Inc., Alexandre Montplaisir
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
10package org.eclipse.tracecompass.internal.tmf.ui.project.handlers;
11
12import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
13
14import java.io.IOException;
15import java.lang.reflect.InvocationTargetException;
16import java.nio.file.Files;
17import java.nio.file.Path;
18import java.nio.file.Paths;
d9c10be1
AM
19import java.util.List;
20import java.util.stream.Collectors;
c9694d54
AM
21
22import org.eclipse.core.commands.AbstractHandler;
23import org.eclipse.core.commands.ExecutionEvent;
24import org.eclipse.core.commands.ExecutionException;
25import org.eclipse.core.runtime.CoreException;
26import org.eclipse.core.runtime.IProgressMonitor;
d9c10be1 27import org.eclipse.core.runtime.IStatus;
c9694d54 28import org.eclipse.core.runtime.NullProgressMonitor;
d9c10be1
AM
29import org.eclipse.core.runtime.Status;
30import org.eclipse.jdt.annotation.NonNull;
c9694d54
AM
31import org.eclipse.jdt.annotation.NonNullByDefault;
32import org.eclipse.jdt.annotation.Nullable;
33import org.eclipse.jface.dialogs.MessageDialog;
34import org.eclipse.jface.viewers.ISelection;
35import org.eclipse.jface.viewers.IStructuredSelection;
36import org.eclipse.swt.widgets.DirectoryDialog;
37import org.eclipse.swt.widgets.Shell;
d9c10be1
AM
38import org.eclipse.tracecompass.common.core.StreamUtils;
39import org.eclipse.tracecompass.internal.tmf.ui.Activator;
d9c10be1
AM
40import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
41import org.eclipse.tracecompass.statesystem.core.Statedump;
42import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
c9694d54
AM
43import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
44import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
45import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
46import org.eclipse.tracecompass.tmf.core.trace.trim.ITmfTrimmableTrace;
47import org.eclipse.tracecompass.tmf.ui.project.handlers.HandlerUtils;
48import org.eclipse.tracecompass.tmf.ui.project.model.TmfOpenTraceHelper;
49import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectElement;
50import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceElement;
51import org.eclipse.tracecompass.tmf.ui.project.model.TmfTraceFolder;
52import org.eclipse.tracecompass.tmf.ui.project.model.TraceUtils;
024a2c6b 53import org.eclipse.tracecompass.tmf.ui.project.operations.TmfWorkspaceModifyOperation;
c9694d54
AM
54import org.eclipse.ui.PlatformUI;
55import org.eclipse.ui.handlers.HandlerUtil;
56
57/**
58 * Handler for the Trace Trim operation.
59 *
60 * @author Alexandre Montplaisir
61 */
62@NonNullByDefault
63public class TrimTraceHandler extends AbstractHandler {
64
65 /** Suffix for new trimmed traces, added to the original trace name */
66 private static final String TRACE_NAME_SUFFIX = "-trimmed"; //$NON-NLS-1$
67
68 @Override
69 public boolean isEnabled() {
70 final Object element = HandlerUtils.getSelectedModelElement();
71 if (element == null) {
72 return false;
73 }
74
75 /*
76 * plugin.xml should have done type/count verification already
77 */
78 TmfTraceElement traceElem = (TmfTraceElement) element;
79 if (!(traceElem.getTrace() instanceof ITmfTrimmableTrace)) {
80 return false;
81 }
82
83 /* Only enable the action if a time range is currently selected */
84 TmfTraceManager tm = TmfTraceManager.getInstance();
85 TmfTimeRange selectionRange = tm.getCurrentTraceContext().getSelectionRange();
86 if (selectionRange.getStartTime().equals(selectionRange.getEndTime())) {
87 return false;
88 }
89
90 return true;
91 }
92
93 @Override
94 public @Nullable Object execute(@Nullable ExecutionEvent event) throws ExecutionException {
95 ISelection selection = HandlerUtil.getCurrentSelectionChecked(event);
96 Object element = ((IStructuredSelection) selection).getFirstElement();
97 final TmfTraceElement traceElem = (TmfTraceElement) element;
98
99 ITmfTrace trace = traceElem.getTrace();
100 if (trace == null) {
101 /* That trace is not currently opened */
102 return null;
103 }
104 ITmfTrimmableTrace trimmableTrace = (ITmfTrimmableTrace) trace;
105
106
107 /* Retrieve the current time range */
108 final Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
109 TmfTraceManager tm = TmfTraceManager.getInstance();
110 TmfTimeRange timeRange = tm.getCurrentTraceContext().getSelectionRange();
111 if (timeRange.getStartTime().equals(timeRange.getEndTime())) {
112 MessageDialog.openError(shell, Messages.TrimTraces_InvalidTimeRange_DialogTitle, Messages.TrimTraces_InvalidTimeRange_DialogText);
113 return null;
114 }
115
116 /* Ensure the time range is in the right direction */
117 final TmfTimeRange tr = ((timeRange.getStartTime().compareTo(timeRange.getEndTime()) > 0) ?
118 new TmfTimeRange(timeRange.getEndTime(), timeRange.getStartTime()) :
119 timeRange);
120
121 /*
122 * Pop a dialog asking the user to select a parent directory for the new
123 * trace.
124 */
125 DirectoryDialog dialog = new DirectoryDialog(shell);
126 dialog.setText(Messages.TrimTraces_DirectoryChooser_DialogTitle);
127 String result = dialog.open();
128 if (result == null) {
129 /* Dialog was cancelled, take no further action. */
130 return null;
131 }
132
133 /* Verify that the selected path is valid and writeable */
134 final Path parentPath = checkNotNull(Paths.get(result));
135 if (!Files.isDirectory(parentPath)) {
136 MessageDialog.openError(shell, Messages.TrimTraces_InvalidDirectory_DialogTitle, Messages.TrimTraces_InvalidDirectory_DialogText);
137 return null;
138 }
139 if (!Files.isWritable(parentPath)) {
140 MessageDialog.openError(shell, Messages.TrimTraces_InvalidDirectory_DialogTitle, Messages.TrimTraces_NoWriteAccess_DialogText);
141 return null;
142 }
143
144 /*
145 * Create a directory for the new trace. We will pick the next available
146 * name, adding -2, -3, etc. as needed.
147 */
148 String newTraceName = trace.getName() + TRACE_NAME_SUFFIX;
149 Path potentialPath = parentPath.resolve(newTraceName);
150 for (int i = 2; Files.exists(potentialPath); i++) {
151 newTraceName = trace.getName() + TRACE_NAME_SUFFIX + '-' + String.valueOf(i);
152 potentialPath = parentPath.resolve(newTraceName);
153 }
154
155 final Path tracePath = checkNotNull(potentialPath);
156 try {
157 Files.createDirectory(tracePath);
158 } catch (IOException e) {
159 /* Should not happen since we have checked permissions, etc. */
160 throw new IllegalStateException(e);
161 }
162
163 TmfWorkspaceModifyOperation trimOperation = new TmfWorkspaceModifyOperation() {
164 @Override
165 public void execute(@Nullable IProgressMonitor monitor) throws CoreException {
166 IProgressMonitor mon = (monitor == null ? new NullProgressMonitor() : monitor);
167
d9c10be1
AM
168 /* Retrieve the state system modules to use */
169 long dumpTime = tr.getStartTime().toNanos();
170 List<@NonNull TmfStateSystemAnalysisModule> statesystemModules = StreamUtils.getStream(trace.getAnalysisModules())
171 .filter(module -> module instanceof TmfStateSystemAnalysisModule)
172 .map(module -> (TmfStateSystemAnalysisModule) module)
173 .collect(Collectors.toList());
174
175 /*
176 * Perform the trace-specific trim operation. This should create
177 * the trace file(s) in the destination path.
178 */
c9694d54
AM
179 trimmableTrace.trim(tr, tracePath, mon);
180
d9c10be1
AM
181 /* Write the statedump files in the new trace's location. */
182 try {
183 for (TmfStateSystemAnalysisModule module : statesystemModules) {
184 Integer version = module.getProviderVersion();
185 ITmfStateSystem ss = module.getStateSystem();
186 if (version == null || ss == null) {
187 continue;
188 }
189 if (dumpTime > ss.getCurrentEndTime() || dumpTime < ss.getStartTime()) {
190 continue;
191 }
192
193 Statedump statedump = new Statedump(ss, dumpTime, version);
194 statedump.dumpState(tracePath, ss.getSSID());
195 }
196
197 } catch (IOException e) {
198 IStatus status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, "An error occured while attempting to save the initial state"); //$NON-NLS-1$
199 throw new CoreException(status);
200 }
201
c9694d54
AM
202 /* Import the new trace into the current project, at the top-level. */
203 TmfProjectElement currentProjectElement = traceElem.getProject();
204 TmfTraceFolder traceFolder =currentProjectElement.getTracesFolder();
205 TmfOpenTraceHelper.openTraceFromPath(traceFolder, tracePath.toString(), shell);
206 }
207 };
208
209 try {
210 PlatformUI.getWorkbench().getProgressService().run(true, true, trimOperation);
211 } catch (InterruptedException e) {
212 return null;
213 } catch (InvocationTargetException e) {
214 TraceUtils.displayErrorMsg(e.toString(), e.getTargetException().toString());
215 return null;
216 }
217
218 return null;
219 }
220
221}
This page took 0.034164 seconds and 5 git commands to generate.