package com.insightfullogic.honest_profiler.core.aggregation.aggregator;
import static java.util.stream.Collector.of;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
import java.util.Map;
import com.insightfullogic.honest_profiler.core.aggregation.AggregationProfile;
import com.insightfullogic.honest_profiler.core.aggregation.grouping.CombinedGrouping;
import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Entry;
import com.insightfullogic.honest_profiler.core.aggregation.result.straight.Flat;
import com.insightfullogic.honest_profiler.core.profiles.lean.LeanNode;
import com.insightfullogic.honest_profiler.core.profiles.lean.LeanProfile;
/**
* Aggregator which takes an {@link AggregationProfile}, and uses the data to aggregate the values into a {@link Flat}
* aggregation.
*/
public class FlatProfileAggregator implements ProfileAggregator<Entry>
{
/**
* Aggregates an {@link AggregationProfile} into a {@link Flat}. The {@link CombinedGrouping} specifies which
* {@link LeanNode}s are aggregated together.
*
* @see ProfileAggregator#aggregate(AggregationProfile, CombinedGrouping)
*/
@Override
public Flat aggregate(AggregationProfile input, CombinedGrouping grouping)
{
// Prepare result.
Flat result = new Flat(input, grouping);
LeanProfile source = input.getSource();
// Flatten all LeanNodes into a Stream, then collect it into a Map where the key is calculated by the groupings,
// and the value is the aggregation of the LeanNodes corresponding to the key.
Map<String, Entry> entryMap = source.getThreads().values().stream()
// Stream all LeanNodes in the profile
.flatMap(LeanNode::flatten)
// Filter out the LeanThreadNodes
.filter(node -> !node.isThreadNode()).collect(
groupingBy(
// Group LeanNodes by calculated key
node -> grouping.apply(input, node),
// Downstream collector, aggregates LeanNodes in a single group
of(
// Supplier, creates an empty Entry
() -> new Entry(result),
// Accumulator, aggregates a LeanNode into the Entry accumulator
(entry, leanNode) -> entry.add(leanNode),
// Combiner, combines two Entries with the same key
(entry1, entry2) -> entry1.combine(entry2))));
// Add the aggregated Entries to the result list, after setting their key and reference.
result.getData().addAll(entryMap.entrySet().stream().map(mapEntry ->
{
Entry entry = mapEntry.getValue();
// The key must be set explicitly here because it isn't set in the collector.
entry.setKey(mapEntry.getKey());
// Set the reference by default for all nodes to the global aggregation.
entry.setReference(input.getGlobalData());
return entry;
}).collect(toList()));
return result;
}
}