diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/project/model/TmfTraceType.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/project/model/TmfTraceType.java index 433d820a4e..bae12836bd 100644 --- a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/project/model/TmfTraceType.java +++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/project/model/TmfTraceType.java @@ -46,6 +46,7 @@ import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomXmlTraceDefinition; import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager; import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment; import org.eclipse.tracecompass.tmf.core.util.Pair; /** @@ -610,4 +611,100 @@ private static boolean isUnique(TraceTypeHelper trace, Collection selectExperimentType(List traces, String experimentTypeHint) { + Comparator> comparator = (o1, o2) -> { + int res = o2.getFirst().compareTo(o1.getFirst()); // invert so that highest confidence is first + if (res == 0) { + res = o1.getSecond().getName().compareTo(o2.getSecond().getName()); + } + return res; + }; + + TreeSet> validCandidates = new TreeSet<>(comparator); + final Iterable traceTypeHelpers = TmfTraceType.getTraceTypeHelpers(); + for (TraceTypeHelper traceTypeHelper : traceTypeHelpers) { + // Skip if it is not enabled or it is not an experiment + if (!traceTypeHelper.isEnabled() || !traceTypeHelper.isExperimentType()) { + continue; + } + int confidence = traceTypeHelper.validateExperimentWithTraces(traces); + if (confidence >= 0) { + if (traceTypeHelper.getTraceTypeId().equals(experimentTypeHint)) { + // if the trace type hint is valid, return it immediately + return Collections.singletonList(traceTypeHelper); + } + // insert in the tree map, ordered by confidence (highest + // confidence first) then name + Pair element = new Pair<>(confidence, traceTypeHelper); + validCandidates.add(element); + } + } + List returned = new ArrayList<>(); + // If no valid candidates are found, then add generic experiment type + if (validCandidates.isEmpty()) { + Activator.logInfo("No valid candidates were found, selecting generic TMF experiment type"); //$NON-NLS-1$ + returned.add(getTraceType(DEFAULT_EXPERIMENT_TYPE)); + return returned; + } + + if (validCandidates.size() != 1) { + List> reducedCandidates = reduce(validCandidates); + if (reducedCandidates.isEmpty()) { + Activator.logInfo("Error reducing experiment type candidates, selecting generic TMF experiment type"); //$NON-NLS-1$ + returned.add(getTraceType(DEFAULT_EXPERIMENT_TYPE)); + return returned; + } else if (reducedCandidates.size() == 1) { + // Don't select the exp type if it has the lowest confidence + if (reducedCandidates.get(0).getFirst() > 0) { + returned.add(reducedCandidates.get(0).getSecond()); + } + } else { + for (Pair candidatePair : reducedCandidates) { + // Don't select the exp type if it has the lowest confidence + if (candidatePair.getFirst() > 0) { + returned.add(candidatePair.getSecond()); + } + } + } + } else { + // Don't select the exp type if it has the lowest confidence + if (validCandidates.first().getFirst() > 0) { + returned.add(validCandidates.first().getSecond()); + } + } + return returned; + } + + /** + * Instantiate an experiment based on the provided type ID + * + * @param typeID + * the ID of the experiment (like "o.e.l.specificexperiment" ) + * @return {@link TmfExperiment} instance or null if experiment type Id + * doesn't exist + * @throws CoreException + * if trace cannot be instantiated + * @since 8.4 + */ + public static TmfExperiment instantiateExperiment(String typeID) throws CoreException { + IConfigurationElement ce = TRACE_TYPE_ATTRIBUTES.get(typeID); + if (ce == null) { + return null; + } + return (TmfExperiment) ce.createExecutableExtension(TmfTraceType.EXPERIMENT_TYPE_ATTR); + } } diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/project/model/TraceTypeHelper.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/project/model/TraceTypeHelper.java index 9bd33af888..8ad06457e8 100644 --- a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/project/model/TraceTypeHelper.java +++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/project/model/TraceTypeHelper.java @@ -17,11 +17,14 @@ package org.eclipse.tracecompass.tmf.core.project.model; +import java.util.List; + import org.eclipse.core.runtime.IStatus; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType.TraceElementType; import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; import org.eclipse.tracecompass.tmf.core.trace.TraceValidationStatus; +import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment; /** * TraceTypeHelper, a helper that can link a few names to a configuration element @@ -127,8 +130,30 @@ public IStatus validate(String path) { * @return the confidence level (0 is lowest) or -1 if validation fails */ public int validateWithConfidence(String path) { - int result = -1; IStatus status = fTrace.validate(null, path); + return getConfidenceFromStatus(status); + } + + /** + * Validate an experiment against this experiment type with confidence level + * + * @param traces + * list of traces belonging to the experiment + * @return the confidence level (0 is lowest), or -1 if validation fails or + * trace is not an experiment + * @since 8.4 + */ + public int validateExperimentWithTraces(List traces) { + if (!isExperimentType()) { + return -1; + } + TmfExperiment exp = (TmfExperiment) fTrace; + IStatus status = exp.validateWithTraces(traces); + return getConfidenceFromStatus(status); + } + + private static int getConfidenceFromStatus(IStatus status) { + int result = -1; if (status.getSeverity() != IStatus.ERROR) { result = 0; if (status instanceof TraceValidationStatus) { @@ -198,5 +223,4 @@ public void setEnabled(boolean enable) { public String toString() { return fName; } - } diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/trace/experiment/TmfExperiment.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/trace/experiment/TmfExperiment.java index 05c1fe1a6f..44a292bb9d 100644 --- a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/trace/experiment/TmfExperiment.java +++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/trace/experiment/TmfExperiment.java @@ -70,6 +70,7 @@ import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; import org.eclipse.tracecompass.tmf.core.trace.TmfTrace; import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; +import org.eclipse.tracecompass.tmf.core.trace.TraceValidationStatus; import org.eclipse.tracecompass.tmf.core.trace.indexer.ITmfPersistentlyIndexable; import org.eclipse.tracecompass.tmf.core.trace.indexer.ITmfTraceIndexer; import org.eclipse.tracecompass.tmf.core.trace.indexer.TmfBTreeTraceIndexer; @@ -120,6 +121,11 @@ public class TmfExperiment extends TmfTrace implements ITmfPersistentlyIndexable */ private static final long CLOCK_OFFSET_THRESHOLD_NS = 500000; + /** + * The default confidence for the generic Tmf experiment + */ + private static final int DEFAULT_GENERIC_EXPERIMENT_CONFIDENCE = 1; + // ------------------------------------------------------------------------ // Attributes // ------------------------------------------------------------------------ @@ -369,6 +375,29 @@ public IStatus validate(final IProject project, final String path) { return Status.OK_STATUS; } + /** + * Validates the experiment based on the traces provided. All subclasses of + * TmfExperiment should override this method to compute its own validation. + * If the experiment type is valid based on the provided traces, the + * method should return TraceValidationStatus with confidence. If it is not + * valid, an ERROR status should be returned. Note that the generic Tmf + * experiment reserves the confidence value of 1, therefore all extending + * classes should return a confidence level accordingly. + * + * @param traces + * list of ITmfTraces that is used to validate this experiment + * @return status an IStatus object with validation result. Use ERROR status + * to indicate an error, otherwise use TraceValidationStatus with a + * confidence. + * @since 8.4 + */ + public IStatus validateWithTraces(List traces) { + if (getClass() == TmfExperiment.class) { + return new TraceValidationStatus(DEFAULT_GENERIC_EXPERIMENT_CONFIDENCE, Activator.PLUGIN_ID); + } + return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "class extends TmfExperiment"); //$NON-NLS-1$ + } + // ------------------------------------------------------------------------ // Accessors // ------------------------------------------------------------------------