weighted tree: Add a weighted tree set to structure data

A WeightedTreeSet is a structure that keeps elements and their weighted
trees together, so that different treesets can be used for different
purposes, like for selection ranges, or with elements grouped together.

[changed] Put weighted tree data in a separate structure from provider

Change-Id: I6c505edecc4f507e924939690e6b2a573e3dfaa5
Signed-off-by: Geneviève Bastien <gbastien+lttng@versatic.net>
Reviewed-on: https://git.eclipse.org/r/149803
Tested-by: CI Bot
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Tested-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
diff --git a/callstack/org.eclipse.tracecompass.incubator.analysis.core/src/org/eclipse/tracecompass/incubator/analysis/core/weighted/tree/IWeightedTreeProvider.java b/callstack/org.eclipse.tracecompass.incubator.analysis.core/src/org/eclipse/tracecompass/incubator/analysis/core/weighted/tree/IWeightedTreeProvider.java
index 4cee4a3..232b017 100644
--- a/callstack/org.eclipse.tracecompass.incubator.analysis.core/src/org/eclipse/tracecompass/incubator/analysis/core/weighted/tree/IWeightedTreeProvider.java
+++ b/callstack/org.eclipse.tracecompass.incubator.analysis.core/src/org/eclipse/tracecompass/incubator/analysis/core/weighted/tree/IWeightedTreeProvider.java
@@ -12,17 +12,16 @@
 import java.text.FieldPosition;
 import java.text.Format;
 import java.text.ParsePosition;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.tracecompass.common.core.format.DecimalUnitFormat;
-import org.eclipse.tracecompass.common.core.format.SubSecondTimeWithUnitFormat;
 import org.eclipse.tracecompass.common.core.format.DataSizeWithUnitFormat;
 import org.eclipse.tracecompass.common.core.format.DataSpeedWithUnitFormat;
+import org.eclipse.tracecompass.common.core.format.DecimalUnitFormat;
+import org.eclipse.tracecompass.common.core.format.SubSecondTimeWithUnitFormat;
 import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
 
 /**
@@ -34,14 +33,14 @@
  * elements can implement the {@link ITree} class if there is a hierarchy in the
  * groupings.
  *
- * @author Geneviève Bastien
- *
  * @param <N>
  *            The type of objects represented by each node in the tree
  * @param <E>
  *            The type of elements used to group the trees
  * @param <T>
  *            The type of the tree provided
+ *
+ * @author Geneviève Bastien
  */
 public interface IWeightedTreeProvider<@NonNull N, E, @NonNull T extends WeightedTree<N>> {
 
@@ -177,38 +176,29 @@
     MetricType WEIGHT_TYPE = new MetricType("Weight", DataType.NUMBER, null); //$NON-NLS-1$
 
     /**
-     * Get the trees provided by this analysis. This should return all the trees
-     * for the whole trace
+     * Get a weighted tree set for a time selection. It should be a subset of
+     * the complete tree, ie the elements, and weights of the weighted trees
+     * should be included in full tree, but its range should cover only the
+     * requested time range. If this provider does not support selection range,
+     * <code>null</code> should be returned.
      *
-     * @param element
-     *            The element for which to get the trees
-     * @return A collection of trees provided by this class
-     */
-    Collection<T> getTreesFor(E element);
-
-    /**
-     * Get the trees for a certain time range. If a provider does not support
-     * ranged trees, this method can just return an empty collection
-     *
-     * @param element
-     *            The element for which to get the trees
      * @param start
      *            The timestamp of the start of the range
      * @param end
      *            The timestamp of the end of the range
-     * @return A collection of trees whose values span from start to end
+     * @return A weighted tree set that spans the selected range, or
+     *         <code>null</code> if range is not supported.
      */
-    default Collection<T> getTrees(E element, ITmfTimestamp start, ITmfTimestamp end) {
-        return Collections.emptySet();
+    default @Nullable IWeightedTreeSet<N, E, T> getSelection(ITmfTimestamp start, ITmfTimestamp end) {
+        return null;
     }
 
     /**
-     * Get the elements under which are the trees. It can be a single constant
-     * element if this provider does not have the concept of grouping the trees.
+     * Get the complete tree set provided by this object.
      *
-     * @return The elements used to group the trees
+     * @return The complete weighted tree set
      */
-    Collection<E> getElements();
+    IWeightedTreeSet<N, E, T> getTreeSet();
 
     /**
      * Get the metric type for the weight value. The default metric is called
diff --git a/callstack/org.eclipse.tracecompass.incubator.analysis.core/src/org/eclipse/tracecompass/incubator/analysis/core/weighted/tree/IWeightedTreeSet.java b/callstack/org.eclipse.tracecompass.incubator.analysis.core/src/org/eclipse/tracecompass/incubator/analysis/core/weighted/tree/IWeightedTreeSet.java
new file mode 100644
index 0000000..2ecce20
--- /dev/null
+++ b/callstack/org.eclipse.tracecompass.incubator.analysis.core/src/org/eclipse/tracecompass/incubator/analysis/core/weighted/tree/IWeightedTreeSet.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2019 É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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.incubator.analysis.core.weighted.tree;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNull;
+
+/**
+ * A structure that keeps elements and their weighted trees together for a given
+ * time range or grouping. It is the class that contains the actual data that
+ * the {@link IWeightedTreeProvider} provides.
+ *
+ * The tree set contains the data, but a {@link IWeightedTreeProvider} object
+ * is necessary to describe it, its format, their names, etc.
+ *
+ * @author Geneviève Bastien
+ *
+ * @param <N>
+ *            The type of objects represented by each node in the tree
+ * @param <E>
+ *            The type of elements used to group the trees
+ * @param <T>
+ *            The type of the tree provided
+ */
+public interface IWeightedTreeSet<@NonNull N, E, @NonNull T extends WeightedTree<N>> {
+
+    /**
+     * Get the elements under which are the weighted trees. It can be a single
+     * constant element if this treeset does not have the concept of grouping
+     * the trees.
+     *
+     * @return The elements used to group the trees
+     */
+    Collection<E> getElements();
+
+    /**
+     * Get the weighted trees for a given element
+     *
+     * @param element
+     *            The element for which to get the trees
+     * @return A collection of weighted trees for the requested element
+     */
+    Collection<T> getTreesFor(E element);
+
+    /**
+     * Return a list of additional data sets' titles. These sets will be
+     * available by calling {@link WeightedTree#getExtraDataTrees(int)} on the
+     * trees, where the index in the list is the parameter that the children set
+     * should match
+     *
+     * @return The title of each child set
+     */
+    default List<String> getExtraDataSets() {
+        return Collections.emptyList();
+    }
+}
diff --git a/callstack/org.eclipse.tracecompass.incubator.analysis.core/src/org/eclipse/tracecompass/incubator/analysis/core/weighted/tree/diff/DifferentialWeightedTreeProvider.java b/callstack/org.eclipse.tracecompass.incubator.analysis.core/src/org/eclipse/tracecompass/incubator/analysis/core/weighted/tree/diff/DifferentialWeightedTreeProvider.java
index e540c1e..e0f3bbb 100644
--- a/callstack/org.eclipse.tracecompass.incubator.analysis.core/src/org/eclipse/tracecompass/incubator/analysis/core/weighted/tree/diff/DifferentialWeightedTreeProvider.java
+++ b/callstack/org.eclipse.tracecompass.incubator.analysis.core/src/org/eclipse/tracecompass/incubator/analysis/core/weighted/tree/diff/DifferentialWeightedTreeProvider.java
@@ -20,6 +20,7 @@
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.IWeightedTreeProvider;
+import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.IWeightedTreeSet;
 import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.WeightedTree;
 
 /**
@@ -65,9 +66,31 @@
 
     };
 
+    private class DifferentialWeightedTreeSet implements IWeightedTreeSet<Object, String, DifferentialWeightedTree<Object>> {
+
+        private final Collection<DifferentialWeightedTree<Object>> fTrees;
+
+        DifferentialWeightedTreeSet(Collection<DifferentialWeightedTree<Object>> trees) {
+            fTrees = trees;
+        }
+
+        @Override
+        public Collection<DifferentialWeightedTree<Object>> getTreesFor(String element) {
+            if (element.equals(DEFAULT_ELEMENT)) {
+                return fTrees;
+            }
+            return Collections.emptyList();
+        }
+
+        @Override
+        public Collection<String> getElements() {
+            return Collections.singleton(DEFAULT_ELEMENT);
+        }
+    }
+
     private static final List<MetricType> WEIGHT_TYPES = Collections.singletonList(new MetricType("Differential", DataType.OTHER, DIFFERENTIAL_FORMAT)); //$NON-NLS-1$
 
-    private final Collection<DifferentialWeightedTree<Object>> fTrees;
+    private final IWeightedTreeSet<Object, String, DifferentialWeightedTree<Object>> fTreeSet;
 
     private final IWeightedTreeProvider<Object, ?, WeightedTree<Object>> fOriginalTree;
 
@@ -80,24 +103,11 @@
      *            The differential tree
      */
     public DifferentialWeightedTreeProvider(IWeightedTreeProvider<Object, ?, WeightedTree<Object>> originalTree, Collection<DifferentialWeightedTree<Object>> trees) {
-        fTrees = trees;
+        fTreeSet = new DifferentialWeightedTreeSet(trees);
         fOriginalTree = originalTree;
     }
 
     @Override
-    public Collection<DifferentialWeightedTree<Object>> getTreesFor(String element) {
-        if (element.equals(DEFAULT_ELEMENT)) {
-            return fTrees;
-        }
-        return Collections.emptyList();
-    }
-
-    @Override
-    public Collection<String> getElements() {
-        return Collections.singleton(DEFAULT_ELEMENT);
-    }
-
-    @Override
     public String getTitle() {
         return "Differential tree"; //$NON-NLS-1$
     }
@@ -125,5 +135,9 @@
         return StringUtils.EMPTY;
     }
 
+    @Override
+    public IWeightedTreeSet<Object, String, DifferentialWeightedTree<Object>> getTreeSet() {
+        return fTreeSet;
+    }
 
 }
diff --git a/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/callstack/core/callgraph/CallGraph.java b/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/callstack/core/callgraph/CallGraph.java
index 3a5a0a4..f71dac2 100644
--- a/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/callstack/core/callgraph/CallGraph.java
+++ b/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/callstack/core/callgraph/CallGraph.java
@@ -13,7 +13,10 @@
 import java.util.HashSet;
 import java.util.Set;
 
+import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.tracecompass.incubator.analysis.core.concepts.AggregatedCallSite;
+import org.eclipse.tracecompass.incubator.analysis.core.concepts.ICallStackSymbol;
+import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.IWeightedTreeSet;
 import org.eclipse.tracecompass.incubator.callstack.core.base.ICallStackElement;
 
 import com.google.common.collect.HashMultimap;
@@ -27,7 +30,7 @@
  *
  * @author Geneviève Bastien
  */
-public class CallGraph {
+public class CallGraph implements IWeightedTreeSet<@NonNull ICallStackSymbol, ICallStackElement, AggregatedCallSite> {
 
     /**
      * An empty graph that can be returned when there is no other call graph
@@ -89,8 +92,14 @@
      *
      * @return The root elements of the call graph
      */
+    @Override
     public Collection<ICallStackElement> getElements() {
         return ImmutableSet.copyOf(fRootElements);
     }
 
+    @Override
+    public Collection<AggregatedCallSite> getTreesFor(ICallStackElement element) {
+        return getCallingContextTree(element);
+    }
+
 }
diff --git a/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/callstack/core/callgraph/ICallGraphProvider.java b/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/callstack/core/callgraph/ICallGraphProvider.java
index ddd722c..48ce631 100644
--- a/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/callstack/core/callgraph/ICallGraphProvider.java
+++ b/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/callstack/core/callgraph/ICallGraphProvider.java
@@ -12,9 +12,11 @@
 import java.util.Collection;
 
 import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.tracecompass.incubator.analysis.core.concepts.AggregatedCallSite;
 import org.eclipse.tracecompass.incubator.analysis.core.concepts.ICallStackSymbol;
 import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.IWeightedTreeProvider;
+import org.eclipse.tracecompass.incubator.analysis.core.weighted.tree.IWeightedTreeSet;
 import org.eclipse.tracecompass.incubator.callstack.core.base.ICallStackElement;
 import org.eclipse.tracecompass.incubator.callstack.core.base.ICallStackGroupDescriptor;
 import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
@@ -63,23 +65,14 @@
     CallGraph getCallGraph();
 
     @Override
-    default Collection<AggregatedCallSite> getTreesFor(ICallStackElement element) {
-        CallGraph callGraph = getCallGraph();
-        return callGraph.getCallingContextTree(element);
+    default @Nullable IWeightedTreeSet<@NonNull ICallStackSymbol, ICallStackElement, AggregatedCallSite> getSelection(ITmfTimestamp start, ITmfTimestamp end) {
+        CallGraph callGraph = getCallGraph(start, end);
+        return callGraph;
     }
 
     @Override
-    default Collection<AggregatedCallSite> getTrees(ICallStackElement element, ITmfTimestamp start, ITmfTimestamp end) {
-       CallGraph callGraph = getCallGraph(start, end);
-       return callGraph.getCallingContextTree(element);
-    }
-
-
-
-    @Override
-    default Collection<ICallStackElement> getElements() {
-        CallGraph callGraph = getCallGraph();
-        return callGraph.getElements();
+    default IWeightedTreeSet<@NonNull ICallStackSymbol, ICallStackElement, AggregatedCallSite> getTreeSet() {
+        return getCallGraph();
     }
 
     /**
diff --git a/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/callstack/core/instrumented/statesystem/InstrumentedCallStackAnalysis.java b/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/callstack/core/instrumented/statesystem/InstrumentedCallStackAnalysis.java
index 1974587..ba996d5 100644
--- a/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/callstack/core/instrumented/statesystem/InstrumentedCallStackAnalysis.java
+++ b/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/callstack/core/instrumented/statesystem/InstrumentedCallStackAnalysis.java
@@ -346,6 +346,11 @@
     }
 
     @Override
+    public @NonNull List<@NonNull String> getExtraDataSets() {
+        return fCallGraph.getExtraDataSets();
+    }
+
+    @Override
     public MetricType getWeightType() {
         return fCallGraph.getWeightType();
     }
diff --git a/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/internal/callstack/core/instrumented/callgraph/CallGraphAnalysis.java b/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/internal/callstack/core/instrumented/callgraph/CallGraphAnalysis.java
index c2b5701..1e7add1 100644
--- a/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/internal/callstack/core/instrumented/callgraph/CallGraphAnalysis.java
+++ b/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/internal/callstack/core/instrumented/callgraph/CallGraphAnalysis.java
@@ -93,6 +93,7 @@
     private final CallGraph fCallGraph = new CallGraph();
 
     private @Nullable Collection<ISymbolProvider> fSymbolProviders = null;
+    private boolean fHasKernelStatuses = false;
 
     // Keep a very small cache of selection callgraphs, to avoid having to
     // compute again
@@ -238,6 +239,7 @@
         if (callStack.getMaxDepth() == 0) {
             return;
         }
+        fHasKernelStatuses |= callStack.hasKernelStatuses();
         // Start with the first function
         AbstractCalledFunction nextFunction = (AbstractCalledFunction) callStack.getNextFunction(callStack.getStartTime(), 1, null, model, start, end);
         while (nextFunction != null) {
@@ -334,6 +336,14 @@
     }
 
     @Override
+    public List<String> getExtraDataSets() {
+        if (fHasKernelStatuses) {
+            return Collections.singletonList(String.valueOf(org.eclipse.tracecompass.incubator.internal.callstack.core.instrumented.provider.Messages.FlameChartDataProvider_KernelStatusTitle));
+        }
+        return ICallGraphProvider.super.getExtraDataSets();
+    }
+
+    @Override
     public MetricType getWeightType() {
         return DURATION_METRIC;
     }
diff --git a/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/internal/callstack/core/xml/callstack/CallstackXmlAnalysis.java b/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/internal/callstack/core/xml/callstack/CallstackXmlAnalysis.java
index 74f3b45..81b3a3f 100644
--- a/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/internal/callstack/core/xml/callstack/CallstackXmlAnalysis.java
+++ b/callstack/org.eclipse.tracecompass.incubator.callstack.core/src/org/eclipse/tracecompass/incubator/internal/callstack/core/xml/callstack/CallstackXmlAnalysis.java
@@ -384,4 +384,9 @@
         return iterator.next().waitUntilBuilt(0);
     }
 
+    @Override
+    public List<String> getExtraDataSets() {
+        return fCallGraph.getExtraDataSets();
+    }
+
 }
diff --git a/callstack/org.eclipse.tracecompass.incubator.callstack.ui/src/org/eclipse/tracecompass/incubator/internal/callstack/ui/views/weightedtree/WeightedTreeViewer.java b/callstack/org.eclipse.tracecompass.incubator.callstack.ui/src/org/eclipse/tracecompass/incubator/internal/callstack/ui/views/weightedtree/WeightedTreeViewer.java
index 2fb6411..73ef1c5 100644
--- a/callstack/org.eclipse.tracecompass.incubator.callstack.ui/src/org/eclipse/tracecompass/incubator/internal/callstack/ui/views/weightedtree/WeightedTreeViewer.java
+++ b/callstack/org.eclipse.tracecompass.incubator.callstack.ui/src/org/eclipse/tracecompass/incubator/internal/callstack/ui/views/weightedtree/WeightedTreeViewer.java
@@ -462,7 +462,7 @@
 
         private List<ITmfTreeViewerEntry> getChildrenTreeNodes() {
             List<ITmfTreeViewerEntry> list = new ArrayList<>();
-            for (WeightedTree<?> callsite : fTreeProvider.getTreesFor(fThisElement)) {
+            for (WeightedTree<?> callsite : fTreeProvider.getTreeSet().getTreesFor(fThisElement)) {
                 list.add(new TreeNodeEntry(callsite, this, fTreeProvider));
             }
             return list;
@@ -576,7 +576,7 @@
 
     private <@NonNull E> void setGlobalData(List<ITmfTreeViewerEntry> entryList, IWeightedTreeProvider<?, E, WeightedTree<?>> module) {
 
-        Collection<E> elements = module.getElements();
+        Collection<E> elements = module.getTreeSet().getElements();
 
         for (E element : elements) {
             ElementEntry<E> entry = new ElementEntry<>(element, module);