/**
 * Copyright (c) 2014 Richard Warburton (richard.warburton@gmail.com)
 * <p/>
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 * <p/>
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 * <p/>
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 **/
package com.insightfullogic.honest_profiler.core.collector;

import com.insightfullogic.honest_profiler.core.parser.Method;

import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;

import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.toList;

public class CallCountAggregator<T>
{
    private static final Comparator<Entry<?, CallCounts>> sortBySelfCount
        = comparing((Entry<?, CallCounts> entry) -> entry.getValue().timeInvokingThis).reversed();

    private final Map<T, CallCounts> callCountsByKey = new HashMap<>();
    private final Map<Long, Method> methodByMethodId;
    private final Function<T, Long> getMethodId;

    public CallCountAggregator(
        final Map<Long, Method> methodByMethodId, final Function<T, Long> getMethodId)
    {
        this.methodByMethodId = methodByMethodId;
        this.getMethodId = getMethodId;
    }

    public void onFrameAppearance(final T key, final boolean endOfTrace)
    {
        callCountsByKey
            .computeIfAbsent(key, ignore -> new CallCounts())
            .onAppearance(endOfTrace);
    }

    public List<FlatProfileEntry> aggregate(final double traceCount)
    {
        return callCountsByKey
            .entrySet()
            .stream()
            .sorted(sortBySelfCount)
            .map((entry) -> toFlatProfileEntry(entry.getKey(), entry.getValue(), traceCount))
            .collect(toList());
    }

    private FlatProfileEntry toFlatProfileEntry(
        final T key, final CallCounts callCounts, final double traceCount)
    {
        final Long methodId = getMethodId.apply(key);
        Method method = methodByMethodId.get(methodId);
        if (method == null)
        {
            method = new Method(methodId, "UNKNOWN", "UNKNOWN", String.valueOf(methodId));
        }
        double totalTimeShare = (double) callCounts.timeAppeared / traceCount;
        double selfTimeShare = (double) callCounts.timeInvokingThis / traceCount;
        return new FlatProfileEntry(method, totalTimeShare, selfTimeShare);
    }
}

@@ -1285,16 +1285,83 @@
 .Method;
+%0Aimport com.insightfullogic.honest_profiler.core.parser.StackFrame;
 %0A%0Aimport
@@ -2881,32 +2881,216 @@
 aceCount)%0A    %7B%0A
+        double totalTimeShare = (double) callCounts.timeAppeared / traceCount;%0A        double selfTimeShare = (double) callCounts.timeInvokingThis / traceCount;%0A        Method method;%0A
         final Lo
@@ -3131,31 +3131,24 @@
 y);%0A        
-Method 
 method = met
@@ -3327,160 +3327,185 @@
     
-double totalTimeShare = (double) callCounts.timeAppeared / traceCount;%0A        double selfTimeShare = (double) callCounts.timeInvokingThis / traceCount;
+Frame frame;%0A        if (key instanceof StackFrame) %7B%0A            frame = new FullFrame(method, (StackFrame) key);%0A        %7D%0A        else %7B%0A            frame = method;%0A        %7D
 %0A   
@@ -3537,22 +3537,21 @@
 leEntry(
-method
+frame
 , totalT

Fix broken aggregation of full info frames.