/******************************************************************************* * Copyright (c) 2013, 2014 École Polytechnique de Montréal * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which * accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Geneviève Bastien - Initial implementation and API *******************************************************************************/ package fr.inria.linuxtools.internal.tmf.ui.project.handlers; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import fr.inria.linuxtools.internal.tmf.ui.Activator; import fr.inria.linuxtools.tmf.core.event.ITmfEvent; import fr.inria.linuxtools.tmf.core.exceptions.TmfTraceException; import fr.inria.linuxtools.tmf.core.synchronization.SynchronizationAlgorithm; import fr.inria.linuxtools.tmf.core.trace.ITmfTrace; import fr.inria.linuxtools.tmf.core.trace.TmfExperiment; import fr.inria.linuxtools.tmf.core.trace.TmfTraceManager; import fr.inria.linuxtools.tmf.ui.project.model.TmfExperimentElement; import fr.inria.linuxtools.tmf.ui.project.model.TmfTraceElement; import fr.inria.linuxtools.tmf.ui.project.model.TraceUtils; /** * Handles the synchronization of an experiment, when the user selects this * option in the menu */ public class SynchronizeTracesHandler extends AbstractHandler { // ------------------------------------------------------------------------ // Attributes // ------------------------------------------------------------------------ private TreeSelection fSelection = null; private static final String CR = System.getProperty("line.separator"); //$NON-NLS-1$ // ------------------------------------------------------------------------ // Validation // ------------------------------------------------------------------------ @Override public boolean isEnabled() { return true; } // ------------------------------------------------------------------------ // Execution // ------------------------------------------------------------------------ @Override public Object execute(ExecutionEvent event) throws ExecutionException { // Check if we are closing down IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); if (window == null) { return null; } // Get the selection IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); IWorkbenchPart part = page.getActivePart(); if (part == null) { return Boolean.FALSE; } ISelectionProvider selectionProvider = part.getSite().getSelectionProvider(); if (selectionProvider == null) { return Boolean.FALSE; } ISelection selection = selectionProvider.getSelection(); // Make sure selection contains only traces fSelection = null; final ArrayList<TmfTraceElement> tl = new ArrayList<>(); final ArrayList<TmfExperimentElement> uiexperiment = new ArrayList<>(); if (selection instanceof TreeSelection) { fSelection = (TreeSelection) selection; Iterator<Object> iterator = fSelection.iterator(); while (iterator.hasNext()) { Object element = iterator.next(); if (element instanceof TmfTraceElement) { tl.add((TmfTraceElement) element); } else if (element instanceof TmfExperimentElement) { TmfExperimentElement exp = (TmfExperimentElement) element; uiexperiment.add(exp); for (TmfTraceElement trace : exp.getTraces()) { tl.add(trace); } } } } if ((uiexperiment.size() != 1) || (tl.size() < 2)) { TraceUtils.displayErrorMsg(Messages.SynchronizeTracesHandler_Title, Messages.SynchronizeTracesHandler_WrongTraceNumber); return null; } Thread thread = new Thread() { @Override public void run() { final ITmfTrace[] traces = new ITmfTrace[tl.size()]; final TmfExperimentElement exp = uiexperiment.get(0); for (int i = 0; i < tl.size(); i++) { ITmfTrace trace = tl.get(i).instantiateTrace(); ITmfEvent traceEvent = tl.get(i).instantiateEvent(); if (trace == null) { TraceUtils.displayErrorMsg(Messages.SynchronizeTracesHandler_Title, Messages.SynchronizeTracesHandler_WrongType + tl.get(i).getName()); for (int j = 0; j < i; j++) { traces[j].dispose(); } return; } try { trace.initTrace(tl.get(i).getResource(), tl.get(i).getLocation().getPath(), traceEvent.getClass()); TmfTraceManager.refreshSupplementaryFiles(trace); } catch (TmfTraceException e) { TraceUtils.displayErrorMsg(Messages.SynchronizeTracesHandler_Title, Messages.SynchronizeTracesHandler_InitError + CR + CR + e); trace.dispose(); for (int j = 0; j < i; j++) { traces[j].dispose(); } return; } traces[i] = trace; } /* * FIXME Unlike traces, there is no instanceExperiment, so * we call this function here alone. Maybe it would be * better to do this on experiment's element constructor? */ exp.refreshSupplementaryFolder(); final TmfExperiment experiment = new TmfExperiment(ITmfEvent.class, exp.getName(), traces, exp.getResource()); try { final SynchronizationAlgorithm syncAlgo = experiment.synchronizeTraces(true); TmfTraceManager.refreshSupplementaryFiles(experiment); Display.getDefault().asyncExec(new Runnable() { @Override public void run() { List<TmfTraceElement> tracesToAdd = new ArrayList<>(); List<TmfTraceElement> tracesToRemove = new ArrayList<>(); /* * For each trace in the experiment, if there is * a transform equation, copy the original * trace, so that a new state system will be * generated with sync time. */ for (TmfTraceElement traceel : tl) { /* * Find the trace corresponding to this * element in the experiment */ ITmfTrace expTrace = null; for (ITmfTrace t : experiment.getTraces()) { if (t.getResource().equals(traceel.getResource())) { expTrace = t; break; } } if ((expTrace != null) && syncAlgo.isTraceSynced(expTrace.getHostId())) { /* Find the original trace */ TmfTraceElement origtrace = traceel.getElementUnderTraceFolder(); /* * Make sure a trace with the * new name does not exist */ String newname = traceel.getName(); IContainer parentFolder = origtrace.getResource().getParent(); boolean traceexists; do { traceexists = false; newname += "_"; //$NON-NLS-1$ if (parentFolder.findMember(newname) != null) { traceexists = true; } } while (traceexists); /* Copy the original trace */ TmfTraceElement newtrace = origtrace.copy(newname); if (newtrace == null) { TraceUtils.displayErrorMsg(Messages.SynchronizeTracesHandler_Title, Messages.SynchronizeTracesHandler_Error + CR + CR + String.format(Messages.SynchronizeTracesHandler_CopyProblem, origtrace.getName())); continue; } /* * Instantiate the new trace * and set its sync formula */ ITmfTrace trace = newtrace.instantiateTrace(); ITmfEvent traceEvent = newtrace.instantiateEvent(); try { trace.initTrace(newtrace.getResource(), newtrace.getLocation().getPath(), traceEvent.getClass()); } catch (TmfTraceException e) { Activator.getDefault().logError(String.format(Messages.SynchronizeTracesHandler_ErrorSynchingForTrace, exp.getName(), traceel.getName()), e); TraceUtils.displayErrorMsg(Messages.SynchronizeTracesHandler_Title, Messages.SynchronizeTracesHandler_Error + CR + CR + e.getMessage()); } trace.setTimestampTransform(syncAlgo.getTimestampTransform(trace)); TmfTraceManager.refreshSupplementaryFiles(trace); trace.dispose(); tracesToAdd.add(newtrace); tracesToRemove.add(traceel); } } experiment.dispose(); // Move synchronization file temporarily so that // it doesn't get deleted by the experiment change IFolder tmpFolder = exp.getTraceSupplementaryFolder("."); //$NON-NLS-1$ IResource syncFile = null; for (IResource resource : exp.getSupplementaryResources()) { if (resource.getName().equals(TmfExperiment.SYNCHRONIZATION_FILE_NAME)) { try { resource.move(tmpFolder.getFile(exp.getName() + '.' + TmfExperiment.SYNCHRONIZATION_FILE_NAME).getFullPath(), false, null); syncFile = resource; break; } catch (CoreException e) { Activator.getDefault().logError(String.format(Messages.SynchronizeTracesHandler_ErrorSynchingExperiment, exp.getName()), e); } } } for (TmfTraceElement trace : tracesToRemove) { try { exp.removeTrace(trace); } catch (CoreException e) { Activator.getDefault().logError(String.format(Messages.SynchronizeTracesHandler_ErrorSynchingForTrace, exp.getName(), trace.getName()), e); TraceUtils.displayErrorMsg(Messages.SynchronizeTracesHandler_Title, Messages.SynchronizeTracesHandler_Error + CR + CR + e.getMessage()); } } for (TmfTraceElement trace : tracesToAdd) { exp.addTrace(trace); } // Move synchronization file back IResource resource = tmpFolder.getFile(exp.getName() + '.' + TmfExperiment.SYNCHRONIZATION_FILE_NAME); if (resource.exists() && syncFile != null) { try { resource.move(syncFile.getFullPath(), false, null); } catch (CoreException e) { Activator.getDefault().logError(String.format(Messages.SynchronizeTracesHandler_ErrorSynchingExperiment, exp.getName()), e); } } } }); } catch (TmfTraceException e) { Activator.getDefault().logError(String.format(Messages.SynchronizeTracesHandler_ErrorSynchingExperiment, exp.getName()), e); TraceUtils.displayErrorMsg(Messages.SynchronizeTracesHandler_Title, Messages.SynchronizeTracesHandler_Error + CR + CR + e.getMessage()); } } }; thread.start(); return null; } }