tmf: Show all trace analysis and views under the experiment
authorBernd Hufmann <Bernd.Hufmann@ericsson.com>
Mon, 10 Apr 2017 13:27:13 +0000 (09:27 -0400)
committerBernd Hufmann <bernd.hufmann@ericsson.com>
Thu, 18 May 2017 15:52:14 +0000 (11:52 -0400)
This patch introduces an aggregate analysis element in the project
explorer that aggregates all common trace analysis elements for each
contained trace in the experiment

Change-Id: I4956be83e4d3be05ca4ff2aba44ceac7f1475788
Signed-off-by: Bernd Hufmann <Bernd.Hufmann@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/95842
Reviewed-by: Hudson CI
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Tested-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-by: Genevieve Bastien <gbastien+lttng@versatic.net>
Tested-by: Genevieve Bastien <gbastien+lttng@versatic.net>
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/project/model/TmfAggregateAnalysisElement.java [new file with mode: 0644]
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/project/model/TmfAnalysisElement.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/project/model/TmfCommonProjectElement.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/project/model/TmfExperimentElement.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/project/model/TmfViewsElement.java

diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/project/model/TmfAggregateAnalysisElement.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/project/model/TmfAggregateAnalysisElement.java
new file mode 100644 (file)
index 0000000..4f55210
--- /dev/null
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Ericsson
+ *
+ * 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.tmf.ui.project.model;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.eclipse.jdt.annotation.NonNull;
+
+import com.google.common.base.Joiner;
+
+/**
+ * Class for project elements of type compound analysis modules.
+ *
+ * This element aggregates analyses with the same type that come from various
+ * traces contained in an experiment. This allows to show trace analyses and
+ * their views under the experiment's view element.
+ *
+ * @author Bernd Hufmann
+ * @since 3.0
+ */
+public class TmfAggregateAnalysisElement extends TmfAnalysisElement {
+
+    private final @NonNull Set<TmfAnalysisElement> fContainedAnalyses = new HashSet<>();
+    private final @NonNull TmfCommonProjectElement fExperimentParent;
+
+    /**
+     * Constructor
+     *
+     * @param experiment
+     *            The element to use for experiment activation.
+     *
+     * @param module
+     *            The analysis module helper.
+     *            This helper is used in super and acts as a delegate
+     *            helper representing all contained analyses elements.
+     */
+    protected TmfAggregateAnalysisElement(@NonNull TmfCommonProjectElement experiment, @NonNull TmfAnalysisElement module) {
+        super (module.getName(), module.getResource(), module.getParent(), module.getAnalysisHelper());
+        fExperimentParent = experiment;
+        fContainedAnalyses.add(module);
+    }
+    @Override
+    protected void refreshChildren() {
+        // refresh all children analysis as well
+        for (TmfAnalysisElement analysis : fContainedAnalyses) {
+            analysis.refreshChildren();
+        }
+        super.refreshChildren();
+    }
+
+    @Override
+    public boolean canExecute() {
+        for (TmfAnalysisElement analysis : fContainedAnalyses) {
+            if (analysis.canExecute()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Add an analysis element that is combined in the compound element.
+     *
+     * @param element
+     *          analysis element to add
+     */
+    public void addAnalyses(@NonNull TmfAnalysisElement element) {
+        fContainedAnalyses.add(element);
+    }
+
+    /**
+     * Remove an analysis element that is combined in the compound element.
+     *
+     * @param element
+     *            analysis element to remove
+     */
+    public void removeAnalyses(@NonNull TmfAnalysisElement element) {
+        fContainedAnalyses.remove(element);
+    }
+
+    /**
+     * Checks if aggregated list is empty or not
+     *
+     * @return <code>true<code> if empty else <code>false</code>
+     */
+    public boolean isEmpty() {
+        return fContainedAnalyses.isEmpty();
+    }
+
+    // ------------------------------------------------------------------------
+    // Operations
+    // ------------------------------------------------------------------------
+    /**
+     * Gets the help message for this analysis
+     *
+     * @return The help message
+     */
+    @Override
+    public String getHelpMessage() {
+        Set<String> messages = new HashSet<>();
+        for (TmfAnalysisElement analysis : fContainedAnalyses) {
+            messages.add(analysis.getHelpMessage());
+        }
+        if (messages.size() > 0) {
+            return Joiner.on(',').join(messages.stream().collect(Collectors.toList()));
+        }
+        return super.getHelpMessage();
+    }
+
+    /**
+     * Make sure the trace this analysis is associated to is the currently
+     * selected one
+     */
+    @Override
+    public void activateParentTrace() {
+        TmfOpenTraceHelper.openTraceFromElement(fExperimentParent);
+    }
+}
index b94a37ac0f20890e8b893208c913a736b8db5aa4..392db349cbb7a9c28bf267e0b2143af9ce65deef 100644 (file)
@@ -53,7 +53,7 @@ public class TmfAnalysisElement extends TmfProjectModelElement implements ITmfSt
     };
 
     private final @NonNull IAnalysisModuleHelper fAnalysisHelper;
-    private boolean fCanExecute = true;
+    private volatile boolean fCanExecute = true;
 
     private static final String ANALYSIS_PROPERTIES_CATEGORY = Messages.TmfAnalysisElement_AnalysisProperties;
     private static final String HELPER_PROPERTIES_CATEGORY = Messages.TmfAnalysisElement_HelperProperties;
@@ -177,7 +177,7 @@ public class TmfAnalysisElement extends TmfProjectModelElement implements ITmfSt
 
     @Override
     public Styler getStyler() {
-        if (!fCanExecute) {
+        if (!canExecute()) {
             return ANALYSIS_CANT_EXECUTE_STYLER;
         }
         return null;
@@ -278,6 +278,27 @@ public class TmfAnalysisElement extends TmfProjectModelElement implements ITmfSt
         }
     }
 
+    /**
+     * Checks whether the analysis can be executed or not.
+     *
+     * @return <code>true</code> if analysis can be executed else
+     *         <code>false</code>
+     * @since 3.0
+     */
+    public boolean canExecute() {
+        return fCanExecute;
+    }
+
+    /**
+     * Gets the analysis helper for this analysis.
+     *
+     * @return the analysis module helper
+     * @since 3.0
+     */
+    @NonNull protected IAnalysisModuleHelper getAnalysisHelper() {
+        return fAnalysisHelper;
+    }
+
     // ------------------------------------------------------------------------
     // IPropertySource2
     // ------------------------------------------------------------------------
index 26d95f4617df7b69f63bd3232b829c554aefd432..10268c9279e11985e26a7efa90099ae7b11a612f 100644 (file)
@@ -21,6 +21,7 @@ import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -122,6 +123,10 @@ public abstract class TmfCommonProjectElement extends TmfProjectModelElement {
         IPath tracePath = getResource().getFullPath();
         IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
 
+        if (this.getParent() instanceof TmfExperimentElement) {
+            return;
+        }
+
         if (fViewsElement == null) {
             /* Add the "Views" node */
             IFolder viewsNodeRes = root.getFolder(tracePath.append(TmfViewsElement.PATH_ELEMENT));
@@ -281,8 +286,10 @@ public abstract class TmfCommonProjectElement extends TmfProjectModelElement {
      */
     public ITmfTrace getTrace() {
         for (ITmfTrace trace : TmfTraceManager.getInstance().getOpenedTraces()) {
-            if (trace.getResource().equals(getResource())) {
-                return trace;
+            for (ITmfTrace t : TmfTraceManager.getTraceSetWithExperiment(trace)) {
+                if (getResource().equals(t.getResource())) {
+                    return t;
+                }
             }
         }
         return null;
@@ -429,6 +436,14 @@ public abstract class TmfCommonProjectElement extends TmfProjectModelElement {
             .collect(Collectors.toList());
     }
 
+    /**
+     * @since 3.0
+     * @return list of children analysis elements
+     */
+    public List<TmfAnalysisElement> getChildrenAvailableAnalysis() {
+        return Collections.EMPTY_LIST;
+    }
+
     // ------------------------------------------------------------------------
     // Supplementary files operations
     // ------------------------------------------------------------------------
index c6810a1d27437268e094017f125e1c48fd898336..c48e7b769558053ea1b5d8b6907e67d8e7cff715 100644 (file)
@@ -15,8 +15,6 @@
 
 package org.eclipse.tracecompass.tmf.ui.project.model;
 
-import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -24,6 +22,7 @@ import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFile;
@@ -212,11 +211,15 @@ public class TmfExperimentElement extends TmfCommonProjectElement implements IPr
         }
 
         /* super.refreshChildren() above should have set this */
-        TmfViewsElement viewsElement = checkNotNull(getChildElementViews());
+        TmfViewsElement viewsElement = getChildElementViews();
+        if (viewsElement == null) {
+            return;
+        }
 
         Map<String, TmfAnalysisElement> analysisMap = new HashMap<>();
         for (TmfAnalysisElement analysis : getAvailableAnalysis()) {
             analysisMap.put(analysis.getAnalysisId(), analysis);
+            analysis.refreshChildren();
         }
         for (IAnalysisModuleHelper module : TmfAnalysisManager.getAnalysisModules().values()) {
             if (!analysisMap.containsKey(module.getId()) && module.appliesToExperiment() && (experiment.getAnalysisModule(module.getId()) != null)) {
@@ -229,6 +232,22 @@ public class TmfExperimentElement extends TmfCommonProjectElement implements IPr
         }
     }
 
+    @Override
+    public List<TmfAnalysisElement> getChildrenAvailableAnalysis() {
+        List<TmfTraceElement> traces = getChildren().stream()
+                        .filter(elem -> (elem instanceof TmfTraceElement))
+                        .map(elem -> ((TmfTraceElement) elem).getElementUnderTraceFolder())
+                        .collect(Collectors.toList());
+
+        List<TmfAnalysisElement> analyses = new ArrayList<>();
+        for (TmfTraceElement traceElem : traces) {
+            if (traceElem.getChildElementViews() != null) {
+                analyses.addAll(traceElem.getAvailableAnalysis());
+            }
+        }
+        return analyses;
+    }
+
     private List<IResource> getTraceResources() {
         IFolder folder = getResource();
         final List<IResource> list = new ArrayList<>();
@@ -395,6 +414,14 @@ public class TmfExperimentElement extends TmfCommonProjectElement implements IPr
             }
         });
 
+        /* Remove all trace analyses from experiment view */
+        List<TmfAnalysisElement> analysisElements = trace.getElementUnderTraceFolder().getAvailableAnalysis();
+        TmfViewsElement view = getChildElementViews();
+
+        if (view != null) {
+            view.removeChildrenAnalysis(analysisElements);
+        }
+
         /* Finally, remove the trace from experiment */
         removeChild(trace);
         deleteTraceResource(trace.getResource());
index a49e8ffc79940e2fab5ce0847d847494f9ff23fb..368c1395d37d7f4d1f13ab7ce07727baebf4ff0e 100644 (file)
 package org.eclipse.tracecompass.tmf.ui.project.model;
 
 import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 
 import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.resources.IResource;
@@ -28,8 +31,11 @@ import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
  * Project model element for the "Views" node.
  *
  * For now it contains the list of the standard analyses, with their outputs
- * (views) under each. The plan is to eventually only show the views under this
- * node, since the user cannot really interact with the analyses themselves.
+ * (views) under each. For experiments all analyses from children traces are
+ * aggregated and shown under the "Views" node.
+ *
+ * The plan is to eventually only show the views under this node, since the
+ * user cannot really interact with the analyses themselves.
  *
  * @author Alexandre Montplaisir
  * @since 2.0
@@ -91,22 +97,79 @@ public class TmfViewsElement extends TmfProjectModelElement {
 
         IPath nodePath = getResource().getFullPath();
 
-        /* Add all new analysis modules or refresh outputs of existing ones */
-        for (IAnalysisModuleHelper module : TmfAnalysisManager.getAnalysisModules(traceClass).values()) {
+        TmfCommonProjectElement parent = getParent();
+
+        if (parent instanceof TmfTraceElement) {
+            /* Add all new analysis modules or refresh outputs of existing ones */
+            for (IAnalysisModuleHelper module : TmfAnalysisManager.getAnalysisModules(traceClass).values()) {
 
-            /* If the analysis is not a child of the trace, create it */
-            TmfAnalysisElement analysis = childrenMap.remove(module.getId());
-            if (analysis == null) {
-                IFolder analysisRes = ResourcesPlugin.getWorkspace().getRoot().getFolder(nodePath.append(module.getId()));
-                analysis = new TmfAnalysisElement(module.getName(), analysisRes, this, module);
-                addChild(analysis);
+                /* If the analysis is not a child of the trace, create it */
+                TmfAnalysisElement analysis = childrenMap.remove(module.getId());
+                if (analysis == null) {
+                    IFolder analysisRes = ResourcesPlugin.getWorkspace().getRoot().getFolder(nodePath.append(module.getId()));
+                    analysis = new TmfAnalysisElement(module.getName(), analysisRes, this, module);
+                    addChild(analysis);
+                }
+                analysis.refreshChildren();
+            }
+
+            /* Remove analysis that are not children of this trace anymore */
+            for (TmfAnalysisElement analysis : childrenMap.values()) {
+                removeChild(analysis);
+            }
+        } else if (parent != null) {
+            /* In experiment case collect trace analyses in the aggregate analyses element */
+            Map<String, TmfAggregateAnalysisElement> analysisMap = new LinkedHashMap<>();
+
+            /* Add all new analysis modules or refresh outputs of existing ones */
+            for (IAnalysisModuleHelper module : TmfAnalysisManager.getAnalysisModules(traceClass).values()) {
+
+                /* If the analysis is not a child of the trace, create it */
+                TmfAnalysisElement analysis = childrenMap.remove(module.getId());
+                TmfAggregateAnalysisElement aggregateAnalysisElement = null;
+                if (analysis == null) {
+                    IFolder analysisRes = ResourcesPlugin.getWorkspace().getRoot().getFolder(nodePath.append(module.getId()));
+                    analysis = new TmfAnalysisElement(module.getName(), analysisRes, this, module);
+                    aggregateAnalysisElement = new TmfAggregateAnalysisElement(parent, analysis);
+                    addChild(aggregateAnalysisElement);
+                } else {
+                    if (analysis instanceof TmfAggregateAnalysisElement) {
+                        aggregateAnalysisElement = (TmfAggregateAnalysisElement) analysis;
+                    } else {
+                        aggregateAnalysisElement = new TmfAggregateAnalysisElement(parent, analysis);
+                    }
+                    removeChild(analysis);
+                    addChild(aggregateAnalysisElement);
+                }
+                analysisMap.put(analysis.getAnalysisId(), aggregateAnalysisElement);
+            }
+
+            /* Now add available all trace analyses */
+            for (TmfAnalysisElement analysis : getParent().getChildrenAvailableAnalysis()) {
+                /* If the analysis is not a child of the trace, create it */
+                TmfAnalysisElement a = childrenMap.remove(analysis.getAnalysisId());
+
+                TmfAggregateAnalysisElement childAnalysis = null;
+
+                if (a instanceof TmfAggregateAnalysisElement) {
+                    childAnalysis = (TmfAggregateAnalysisElement) a;
+                } else {
+                    childAnalysis = analysisMap.get(analysis.getAnalysisId());
+                }
+
+                if (childAnalysis == null) {
+                    childAnalysis = new TmfAggregateAnalysisElement(parent, analysis);
+                    addChild(childAnalysis);
+                } else {
+                    childAnalysis.addAnalyses(analysis);
+                }
+                analysisMap.put(analysis.getAnalysisId(), childAnalysis);
             }
-            analysis.refreshChildren();
-        }
 
-        /* Remove analysis that are not children of this trace anymore */
-        for (TmfAnalysisElement analysis : childrenMap.values()) {
-            removeChild(analysis);
+            /* Remove analysis that are not children of this trace anymore */
+            for (TmfAnalysisElement analysis : childrenMap.values()) {
+                removeChild(analysis);
+            }
         }
     }
 
@@ -114,4 +177,38 @@ public class TmfViewsElement extends TmfProjectModelElement {
     public Image getIcon() {
         return TmfProjectModelIcons.VIEWS_ICON;
     }
+
+    /**
+     * Remove children analysis from aggregated traces
+     *
+     * @param analysisElements
+     *              list of analysis elements to remove
+     *
+     * @since 3.0
+     */
+    public void removeChildrenAnalysis(List<TmfAnalysisElement> analysisElements) {
+        for (TmfAnalysisElement tmfAnalysisElement : analysisElements) {
+            if (tmfAnalysisElement != null) {
+                TmfAggregateAnalysisElement aggrElement = getAggregateAnalysisElement(tmfAnalysisElement);
+                if (aggrElement != null) {
+                    aggrElement.removeAnalyses(tmfAnalysisElement);
+                    if (aggrElement.isEmpty()) {
+                        removeChild(aggrElement);
+                    }
+                }
+            }
+        }
+    }
+
+    private TmfAggregateAnalysisElement getAggregateAnalysisElement(TmfAnalysisElement element) {
+        Optional<TmfAggregateAnalysisElement> aggrElem = getChildren().stream()
+                .filter(elem -> (elem instanceof TmfAggregateAnalysisElement))
+                .map(elem -> ((TmfAggregateAnalysisElement) elem))
+                .filter(elem -> elem.getAnalysisHelper().getId().equals(element.getAnalysisHelper().getId()))
+                .findFirst();
+        if (aggrElem.isPresent()) {
+            return aggrElem.get();
+        }
+        return null;
+    }
 }
This page took 0.029904 seconds and 5 git commands to generate.