*
* Contributors:
* Alexandre Montplaisir - Initial API and implementation
+ * Patrick Tasse - Add support for folder elements
*******************************************************************************/
package org.eclipse.linuxtools.tmf.ui.project.model;
-import java.io.File;
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
-import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.TreeSet;
import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
-import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
-import org.eclipse.linuxtools.internal.tmf.ui.Activator;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.linuxtools.tmf.core.TmfCommonConstants;
import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceImportException;
import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceType;
+import org.eclipse.linuxtools.tmf.core.project.model.TmfTraceType.TraceElementType;
import org.eclipse.linuxtools.tmf.core.project.model.TraceTypeHelper;
import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
+import org.eclipse.linuxtools.tmf.core.util.Pair;
+import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.dialogs.FileSystemElement;
/**
* Utils class for the UI-specific parts of @link {@link TmfTraceType}.
*/
public final class TmfTraceTypeUIUtils {
- private static final String DEFAULT_TRACE_ICON_PATH = "icons" + File.separator + "elcl16" + File.separator + "trace.gif"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ /** Extension point ID */
+ public static final String TMF_TRACE_TYPE_UI_ID = "org.eclipse.linuxtools.tmf.ui.tracetypeui"; //$NON-NLS-1$
- private static final char SEPARATOR = ':';
+ /** Extension point element 'type' (should match the type in TmfTraceType) */
+ public static final String TYPE_ELEM = "type"; //$NON-NLS-1$
- private TmfTraceTypeUIUtils() {}
+ /**
+ * Extension point element 'experiment' (should match the type in
+ * TmfTraceType)
+ */
+ public static final String EXPERIMENT_ELEM = "experiment"; //$NON-NLS-1$
- private static List<File> isolateTraces(List<FileSystemElement> selectedResources) {
- List<File> traces = new ArrayList<>();
+ /** Extension point element 'Default editor' */
+ public static final String DEFAULT_EDITOR_ELEM = "defaultEditor"; //$NON-NLS-1$
- // Get the selection
- Iterator<FileSystemElement> resources = selectedResources.iterator();
+ /** Extension point element 'Events table type' */
+ public static final String EVENTS_TABLE_TYPE_ELEM = "eventsTableType"; //$NON-NLS-1$
- // Get the sorted list of unique entries
- Map<String, File> fileSystemObjects = new HashMap<>();
- while (resources.hasNext()) {
- File resource = (File) resources.next().getFileSystemObject();
- String key = resource.getAbsolutePath();
- fileSystemObjects.put(key, resource);
- }
- List<String> files = new ArrayList<>(fileSystemObjects.keySet());
- Collections.sort(files);
-
- // After sorting, traces correspond to the unique prefixes
- String prefix = null;
- for (int i = 0; i < files.size(); i++) {
- File file = fileSystemObjects.get(files.get(i));
- String name = file.getAbsolutePath();
- if (prefix == null || !name.startsWith(prefix)) {
- prefix = name; // new prefix
- traces.add(file);
- }
- }
+ /** Extension point attribute 'tracetype' */
+ public static final String TRACETYPE_ATTR = "tracetype"; //$NON-NLS-1$
+
+ /** Extension point attribute 'icon' */
+ public static final String ICON_ATTR = "icon"; //$NON-NLS-1$
- return traces;
+ /** Extension point attribute 'class' (attribute of eventsTableType) */
+ public static final String CLASS_ATTR = "class"; //$NON-NLS-1$
+
+ private static final char SEPARATOR = ':';
+
+ private TmfTraceTypeUIUtils() {
}
- private static List<TraceTypeHelper> reduce(List<TraceTypeHelper> candidates) {
- List<TraceTypeHelper> retVal = new ArrayList<>();
+ private static List<Pair<Integer, TraceTypeHelper>> reduce(List<Pair<Integer, TraceTypeHelper>> candidates) {
+ List<Pair<Integer, TraceTypeHelper>> retVal = new ArrayList<>();
// get all the tracetypes that are unique in that stage
- for (TraceTypeHelper trace : candidates) {
- if (isUnique(trace, candidates)) {
- retVal.add(trace);
+ for (Pair<Integer, TraceTypeHelper> candidatePair : candidates) {
+ TraceTypeHelper candidate = candidatePair.getSecond();
+ if (isUnique(candidate, candidates)) {
+ retVal.add(candidatePair);
}
}
return retVal;
/*
* Only return the leaves of the trace types. Ignore custom trace types.
*/
- private static boolean isUnique(TraceTypeHelper trace, List<TraceTypeHelper> set) {
+ private static boolean isUnique(TraceTypeHelper trace, List<Pair<Integer, TraceTypeHelper>> set) {
if (isCustomTraceId(trace.getCanonicalName())) {
return true;
}
// type and if it is only an instance of itself, it is a leaf
final ITmfTrace tmfTrace = trace.getTrace();
int count = -1;
- for (TraceTypeHelper child : set) {
- final ITmfTrace traceCandidate = child.getTrace();
+ for (Pair<Integer, TraceTypeHelper> child : set) {
+ final ITmfTrace traceCandidate = child.getSecond().getTrace();
if (tmfTrace.getClass().isInstance(traceCandidate)) {
count++;
}
return false;
}
- private static TraceTypeHelper getTraceTypeToSet(TmfTraceType type, List<TraceTypeHelper> candidates, Shell shell) {
+ private static TraceTypeHelper getTraceTypeToSet(TmfTraceType type, List<Pair<Integer, TraceTypeHelper>> candidates, Shell shell) {
final Map<String, String> names = new HashMap<>();
Shell shellToShow = new Shell(shell);
shellToShow.setText(Messages.TmfTraceType_SelectTraceType);
final String candidatesToSet[] = new String[1];
- for (TraceTypeHelper candidate : candidates) {
+ for (Pair<Integer, TraceTypeHelper> candidatePair : candidates) {
+ TraceTypeHelper candidate = candidatePair.getSecond();
Button b = new Button(shellToShow, SWT.RADIO);
final String displayName = candidate.getCategoryName() + ':' + candidate.getName();
b.setText(displayName);
return type.getTraceTypeHelper(candidatesToSet[0]);
}
- /**
- * validate list of traces with a tracetype
- *
- * @param type
- * The TmfTraceType instance
- * @param traceTypeName
- * the trace category (canonical name)
- * @param selectedResources
- * List of traces to validate
- * @return true if all the traces are valid
- */
- public static boolean validateTrace(TmfTraceType type, String traceTypeName, List<FileSystemElement> selectedResources) {
- List<File> traces = isolateTraces(selectedResources);
- return type.validateTraceFiles(traceTypeName, traces);
- }
-
/**
* This member figures out the trace type of a given file. It will prompt
* the user if it needs more information to properly pick the trace type.
*/
public static TraceTypeHelper selectTraceType(String path, Shell shell, String traceTypeHint) throws TmfTraceImportException {
TmfTraceType type = TmfTraceType.getInstance();
- List<TraceTypeHelper> validCandidates = new ArrayList<>();
- final Iterable<String> traceTypes = type.getTraceTypeIDs();
- for (String traceType : traceTypes) {
- if (type.validate(traceType, path)) {
- validCandidates.add(type.getTraceTypeHelper(traceType));
+
+ Comparator<Pair<Integer, TraceTypeHelper>> comparator = new Comparator<Pair<Integer, TraceTypeHelper>>() {
+ @Override
+ public int compare(Pair<Integer, TraceTypeHelper> o1, Pair<Integer, TraceTypeHelper> o2) {
+ int res = -o1.getFirst().compareTo(o2.getFirst()); // invert so that highest confidence is first
+ if (res == 0) {
+ res = o1.getSecond().getName().compareTo(o2.getSecond().getName());
+ }
+ return res;
+ }
+ };
+ TreeSet<Pair<Integer, TraceTypeHelper>> validCandidates = new TreeSet<>(comparator);
+ final Iterable<TraceTypeHelper> traceTypeHelpers = type.getTraceTypeHelpers();
+ for (TraceTypeHelper traceTypeHelper : traceTypeHelpers) {
+ if (traceTypeHelper.isExperimentType()) {
+ continue;
+ }
+ int confidence = traceTypeHelper.validateWithConfidence(path);
+ if (confidence >= 0) {
+ // insert in the tree map, ordered by confidence (highest confidence first) then name
+ Pair<Integer, TraceTypeHelper> element = new Pair<>(confidence, traceTypeHelper);
+ validCandidates.add(element);
}
}
TraceTypeHelper traceTypeToSet = null;
if (validCandidates.isEmpty()) {
- final String errorMsg = Messages.TmfOpenTraceHelper_NoTraceTypeMatch + path;
+ final String errorMsg = NLS.bind(Messages.TmfOpenTraceHelper_NoTraceTypeMatch, path);
throw new TmfTraceImportException(errorMsg);
} else if (validCandidates.size() != 1) {
- List<TraceTypeHelper> reducedCandidates = reduce(validCandidates);
- for (TraceTypeHelper tth : reducedCandidates) {
- if (tth.getCanonicalName().equals(traceTypeHint)) {
- traceTypeToSet = tth;
+ List<Pair<Integer, TraceTypeHelper>> candidates = new ArrayList<>(validCandidates);
+ List<Pair<Integer, TraceTypeHelper>> reducedCandidates = reduce(candidates);
+ for (Pair<Integer, TraceTypeHelper> candidatePair : reducedCandidates) {
+ TraceTypeHelper candidate = candidatePair.getSecond();
+ if (candidate.getCanonicalName().equals(traceTypeHint)) {
+ traceTypeToSet = candidate;
+ break;
}
}
if (traceTypeToSet == null) {
if (reducedCandidates.size() == 0) {
throw new TmfTraceImportException(Messages.TmfOpenTraceHelper_ReduceError);
} else if (reducedCandidates.size() == 1) {
- traceTypeToSet = reducedCandidates.get(0);
- } else {
- if (shell == null) {
- return null;
+ traceTypeToSet = reducedCandidates.get(0).getSecond();
+ } else if (shell == null) {
+ Pair<Integer, TraceTypeHelper> candidate = reducedCandidates.get(0);
+ // if the best match has lowest confidence, don't select it
+ if (candidate.getFirst() > 0) {
+ traceTypeToSet = candidate.getSecond();
}
+ } else {
traceTypeToSet = getTraceTypeToSet(type, reducedCandidates, shell);
}
}
} else {
- traceTypeToSet = validCandidates.get(0);
+ traceTypeToSet = validCandidates.first().getSecond();
}
return traceTypeToSet;
}
-
/**
* Set the trace type of a {@Link TraceTypeHelper}. Should only be
* used internally by this project.
*
- * @param path
- * the {@link IPath} path of the resource to set
+ * @param resource
+ * the resource to set
* @param traceType
* the {@link TraceTypeHelper} to set the trace type to.
* @return Status.OK_Status if successful, error is otherwise.
* @throws CoreException
* An exception caused by accessing eclipse project items.
*/
- public static IStatus setTraceType(IPath path, TraceTypeHelper traceType) throws CoreException {
- IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
- String traceBundle = null, traceTypeId = traceType.getCanonicalName(), traceIcon = null;
- if (isCustomTraceId(traceTypeId)) {
- traceBundle = Activator.getDefault().getBundle().getSymbolicName();
- traceIcon = DEFAULT_TRACE_ICON_PATH;
- } else {
- IConfigurationElement ce = TmfTraceType.getInstance().getTraceAttributes(traceTypeId);
- traceBundle = ce.getContributor().getName();
- traceIcon = ce.getAttribute(TmfTraceType.ICON_ATTR);
- }
+ public static IStatus setTraceType(IResource resource, TraceTypeHelper traceType) throws CoreException {
+ String traceTypeId = traceType.getCanonicalName();
- resource.setPersistentProperty(TmfCommonConstants.TRACEBUNDLE, traceBundle);
resource.setPersistentProperty(TmfCommonConstants.TRACETYPE, traceTypeId);
- resource.setPersistentProperty(TmfCommonConstants.TRACEICON, traceIcon);
TmfProjectElement tmfProject = TmfProjectRegistry.getProject(resource.getProject(), true);
- final TmfTraceFolder tracesFolder = tmfProject.getTracesFolder();
- List<TmfTraceElement> traces = tracesFolder.getTraces();
- for (TmfTraceElement traceElement : traces) {
- if (traceElement.getName().equals(resource.getName())) {
- traceElement.refreshTraceType();
- break;
+ if (tmfProject.getTracesFolder().getPath().isPrefixOf(resource.getFullPath())) {
+ String elementPath = resource.getFullPath().makeRelativeTo(tmfProject.getTracesFolder().getPath()).toString();
+ refreshTraceElement(tmfProject.getTracesFolder().getTraces(), elementPath);
+ } else if (resource.getParent().equals(tmfProject.getExperimentsFolder().getResource())) {
+ /* The trace type to set is for an experiment */
+ for (TmfExperimentElement experimentElement : tmfProject.getExperimentsFolder().getExperiments()) {
+ if (resource.equals(experimentElement.getResource())) {
+ experimentElement.refreshTraceType();
+ break;
+ }
+ }
+ } else {
+ for (TmfExperimentElement experimentElement : tmfProject.getExperimentsFolder().getExperiments()) {
+ if (experimentElement.getPath().isPrefixOf(resource.getFullPath())) {
+ String elementPath = resource.getFullPath().makeRelativeTo(experimentElement.getPath()).toString();
+ refreshTraceElement(experimentElement.getTraces(), elementPath);
+ break;
+ }
}
}
tmfProject.refresh();
return Status.OK_STATUS;
}
+
+ private static void refreshTraceElement(List<TmfTraceElement> traceElements, String elementPath) {
+ for (TmfTraceElement traceElement : traceElements) {
+ if (traceElement.getElementPath().equals(elementPath)) {
+ traceElement.refreshTraceType();
+ break;
+ }
+ }
+ }
+
+ /**
+ * Retrieves all configuration elements from the platform extension registry
+ * for the trace type UI extension.
+ *
+ * @param elType
+ * The type of trace type requested, either TRACE or EXPERIMENT
+ * @return An array of trace type configuration elements
+ */
+ public static IConfigurationElement[] getTypeUIElements(TraceElementType elType) {
+ String elementName = TYPE_ELEM;
+ if (elType == TraceElementType.EXPERIMENT) {
+ elementName = EXPERIMENT_ELEM;
+ }
+ IConfigurationElement[] elements =
+ Platform.getExtensionRegistry().getConfigurationElementsFor(TMF_TRACE_TYPE_UI_ID);
+ List<IConfigurationElement> typeElements = new LinkedList<>();
+ for (IConfigurationElement element : elements) {
+ if (element.getName().equals(elementName)) {
+ typeElements.add(element);
+ }
+ }
+ return typeElements.toArray(new IConfigurationElement[typeElements.size()]);
+ }
+
+ /**
+ * Get the UI elements for the given trace type
+ *
+ * @param traceType
+ * The tracetype ID
+ * @param elType
+ * The type of trace type requested, either TRACE or EXPERIMENT
+ * @return The top-level configuration element (access its children with
+ * .getChildren()). Or null if there is no such element.
+ */
+ @Nullable
+ public static IConfigurationElement getTraceUIAttributes(String traceType, TraceElementType elType) {
+ IConfigurationElement[] elements = getTypeUIElements(elType);
+ for (IConfigurationElement ce : elements) {
+ if (traceType.equals(ce.getAttribute(TRACETYPE_ATTR))) {
+ return ce;
+ }
+ }
+ return null;
+ }
}