package com.insightfullogic.honest_profiler.core.aggregation; import com.insightfullogic.honest_profiler.core.aggregation.result.diff.TreeDiff; import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Node; import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Tree; import com.insightfullogic.honest_profiler.core.profiles.lean.info.NumericInfo; public final class ReferenceUtil { /** * Set the reference of all {@link Node}s contained in the provided {@link Tree} according to the specified * {@link ReferenceMode}. The reference of a {@link Node} is used for calculating the percentage values. * <p> * Please consult the {@link ReferenceMode} documentation for more information about the meaning of the reference * modes. * <p> * WARNING : the {@link ReferenceMode#THREAD} mode can only be used for {@link Tree}s or {@link TreeDiff}s where the * top-level children represent thread-level aggregations. Similarly, the {@link ReferenceMode#PARENT} mode can only * be used in {@link Tree}s or {@link TreeDiff}s. * <p> * @param tree the {@link Tree} whose references are to be changed * @param mode the strategy for setting the references */ public static void switchReference(Tree tree, ReferenceMode mode) { switch (mode) { case GLOBAL: NumericInfo global = tree.getSource().getGlobalData(); tree.flatten().forEach(node -> node.setReference(global)); return; case THREAD: tree.getData().forEach(rootNode -> { // The root nodes are presumed to be thread-level aggregations. If not, the results are unspecified. NumericInfo reference = rootNode.getData(); rootNode.getChildren().forEach( child -> child.flatten().forEach(node -> node.setReference(reference))); }); return; case PARENT: tree.getData().forEach(node -> setReferenceToParent(null, node)); return; } } /** * Set the reference of all {@link Node}s contained in the base and new {@link Tree}s in the provided Diff according * to the specified {@link ReferenceMode}. The reference of a {@link Node} is used for calculating the percentage * values. * <p> * @param treeDiff the {@link TreeDiff} whose references are to be changed * @param mode the strategy for setting the references */ public static void switchReference(TreeDiff treeDiff, ReferenceMode mode) { switchReference(treeDiff.getBaseAggregation(), mode); switchReference(treeDiff.getNewAggregation(), mode); } // Helper Methods /** * Recursively sets the reference in the child {@link Node} to the data from the parent {@link Node} for the * specified child {@link Node} as well as its descendants. If the child has no parent, i.e. the specified parent * {@link Node} is null, the child uses its own data for reference. * <p> * @param parent the parent {@link Node} * @param child the child {@link Node} */ private static void setReferenceToParent(Node parent, Node child) { if (parent == null) { child.setReference(child.getData()); } else { child.setReference(parent.getData()); } child.getChildren().forEach(grandChild -> setReferenceToParent(child, grandChild)); } /** * Private Constructor for utility class. */ private ReferenceUtil() { // Private Constructor for utility class } }