| /******************************************************************************* |
| * Copyright (c) 2017 É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.Objects; |
| |
| import org.eclipse.jdt.annotation.NonNull; |
| |
| /** |
| * A class containing helper methods to group aggregated callgraph data by the |
| * different available groups |
| * |
| * @author Geneviève Bastien |
| */ |
| public final class WeightedTreeGroupBy { |
| |
| private WeightedTreeGroupBy() { |
| // Nothing to do |
| } |
| |
| /** |
| * Group callgraph groups by one of the descriptor. |
| * |
| * @param <N> |
| * The type of objects represented by each node in the tree |
| * @param <E> |
| * The type of elements used to group the trees. If this type |
| * extends {@link ITree}, then the elements and their associated |
| * weighted trees will be grouped in a hierarchical style |
| * @param <T> |
| * The type of the tree provided |
| * |
| * @param groupBy |
| * The group descriptor by which to group the call graph |
| * elements. |
| * @param weightedTreeSet |
| * The weighted tree set to group trees for |
| * @param provider |
| * The weighted tree provider |
| * @return A weighted tree set that is the result of the grouping by the |
| * descriptor |
| */ |
| public static <@NonNull N, E, T extends WeightedTree<N>> WeightedTreeSet<N, Object> groupWeightedTreeBy(IWeightedTreeGroupDescriptor groupBy, IWeightedTreeSet<N, E, T> weightedTreeSet, IWeightedTreeProvider<N, E, T> provider) { |
| // Fast return: just aggregated all groups together |
| if (groupBy.equals(AllGroupDescriptor.getInstance())) { |
| return groupWeightedTreeByAll(weightedTreeSet); |
| } |
| |
| WeightedTreeSet<N, Object> wts = new WeightedTreeSet<>(); |
| searchForGroups(groupBy, weightedTreeSet, provider, wts); |
| return wts; |
| } |
| |
| private static <@NonNull N, E, T extends WeightedTree<N>> void searchForGroups(IWeightedTreeGroupDescriptor groupBy, IWeightedTreeSet<N, E, T> callGraph, IWeightedTreeProvider<N, E, T> provider, |
| WeightedTreeSet<N, Object> newCg) { |
| IWeightedTreeGroupDescriptor groupDescriptor = provider.getGroupDescriptor(); |
| int level = 0; |
| while (groupDescriptor != null && !groupDescriptor.equals(groupBy)) { |
| groupDescriptor = groupDescriptor.getNextGroup(); |
| level++; |
| } |
| |
| Collection<E> elements = callGraph.getElements(); |
| for (E element : elements) { |
| Object groupElement = (element instanceof ITree) ? ((ITree) element).copyElement() : Objects.requireNonNull(element); |
| recurseAddElementData(element, groupElement, callGraph, newCg, 0, level); |
| } |
| } |
| |
| /** |
| * @param originalElement |
| * The element to get the trees for |
| * @param groupElement |
| * The last group element |
| * @param treeSet |
| * The original weighted tree set |
| * @param newTreeSet |
| * The new weighted tree set to fill |
| * @param elDepth |
| * The current element depth |
| * @param groupDepth |
| * The depth from which elements will be aggregated. When elDepht |
| * < groupDepth, the element's tree are added as is in the new |
| * treeset, otherwise, they are merged with the trees for the |
| * element at the group depth |
| */ |
| private static <@NonNull N, E, T extends WeightedTree<N>> void recurseAddElementData(E originalElement, Object groupElement, IWeightedTreeSet<@NonNull N, E, T> treeSet, WeightedTreeSet<@NonNull N, Object> newTreeSet, int elDepth, int groupDepth) { |
| |
| // Add the current level of trees to the new tree set |
| for (T tree : treeSet.getTreesFor(originalElement)) { |
| newTreeSet.addWeightedTree(groupElement, tree.copyOf()); |
| } |
| |
| // Recursively add the next level of elements |
| if (originalElement instanceof ITree) { |
| ITree treeEl = (ITree) originalElement; |
| Collection<ITree> children = treeEl.getChildren(); |
| for (@NonNull ITree child : children) { |
| ITree nextGroupEl = (ITree) groupElement; |
| if (elDepth < groupDepth) { |
| nextGroupEl = child.copyElement(); |
| ((ITree) groupElement).addChild(nextGroupEl); |
| } |
| recurseAddElementData((E) child, nextGroupEl, treeSet, newTreeSet, elDepth + 1, groupDepth); |
| } |
| } |
| |
| } |
| |
| private static <@NonNull N, E, T extends WeightedTree<N>> WeightedTreeSet<N, Object> groupWeightedTreeByAll(IWeightedTreeSet<N, E, T> weightedTree) { |
| WeightedTreeSet<N, Object> newTreeSet = new WeightedTreeSet<>(); |
| Collection<E> elements = weightedTree.getElements(); |
| String mainGroup = "All"; //$NON-NLS-1$ |
| for (E element : elements) { |
| recurseAddElementData(element, mainGroup, weightedTree, newTreeSet); |
| } |
| return newTreeSet; |
| } |
| |
| /** |
| * @param element |
| * The element to get the trees for |
| * @param groupElement |
| * The last group element |
| * @param treeSet |
| * The original weighted tree set |
| * @param newTreeSet |
| * The new weighted tree set to fill |
| */ |
| private static <@NonNull N, E, T extends WeightedTree<N>> void recurseAddElementData(E element, String group, IWeightedTreeSet<@NonNull N, E, T> treeSet, WeightedTreeSet<@NonNull N, Object> newTreeSet) { |
| |
| // Add the current level of trees to the new tree set |
| for (T tree : treeSet.getTreesFor(element)) { |
| newTreeSet.addWeightedTree(group, tree.copyOf()); |
| } |
| |
| // Recursively add the next level of elements |
| if (element instanceof ITree) { |
| ITree treeEl = (ITree) element; |
| Collection<?> children = treeEl.getChildren(); |
| for (Object child : children) { |
| recurseAddElementData((E) child, group, treeSet, newTreeSet); |
| } |
| } |
| } |
| |
| } |