/**
   * Computes Abusive information metrics from collected access information.
   *
   * @param requests access informations
   * @param top number of max values to be retained
   * @return the metrics of abusive accesses.
   */
  static AbuseMetrics computeAbuseMetricsFromAccess(
      Map<UUID, AccessInformation> requests, int skip, int top) {
    AbuseMetrics abuse = new AbuseMetrics();
    Map<String, Long> user_map = new TreeMap<String, Long>();
    Map<String, Long> ip_map = new TreeMap<String, Long>();
    Map<String, Long> requests_map = new TreeMap<String, Long>();

    SortedSet<Entry<UUID, AccessInformation>> accesses = entriesSortedByValues(requests);
    Iterator<Map.Entry<UUID, AccessInformation>> iterator = accesses.iterator();

    long newest = Long.MIN_VALUE;
    long oldest = Long.MAX_VALUE;
    long longest_request = Long.MIN_VALUE;
    long count = 0;

    while (iterator.hasNext()) {
      if (skip-- > 0) continue;

      Map.Entry<UUID, AccessInformation> entry = iterator.next();
      AccessInformation ai = entry.getValue();
      // Case of eviction happened.
      if (ai == null) continue;

      // Keep track of the delay
      Long timestamp = ai.getStartTimestamp();
      long delay = ai.getDurationNs();
      if (timestamp > newest) newest = timestamp;
      if (timestamp < oldest) oldest = timestamp;
      if (longest_request < delay) longest_request = delay;
      // Keep track of the record number
      count++;

      // Keep track of the user list
      long user_count = 1;
      String username = ai.getUsername();
      if (username == null) username = UNKNOWN_USER;
      if (user_map.containsKey(username)) user_count += user_map.get(username);
      user_map.put(username, user_count);

      // Keep track of the Ip List
      long ip_count = 1;
      String ip = ai.getRemoteAddress();
      if (ip == null) ip = UNKNOWN_IP;
      if (ip_map.containsKey(ip)) ip_count += ip_map.get(ip);
      ip_map.put(ip, ip_count);

      // Keep track of the request time spent.
      String request = ai.getRequest();
      Long old_request = Long.MIN_VALUE;
      if (request == null) continue;
      if (requests_map.containsKey(request)) old_request = requests_map.get(request);
      if (delay > old_request) requests_map.put(request, delay);
    }

    // report the period nanoseconds
    abuse.setPeriod(newest - oldest);
    abuse.setCalls(count);

    // Sort Abusive users
    SortedSet<Map.Entry<String, Long>> sorted_users_calls = entriesSortedByValues(user_map);
    Iterator<Map.Entry<String, Long>> user_it = sorted_users_calls.iterator();
    abuse.setAbusiveUsers(new LinkedHashMap<String, Long>());
    int top_count = 0;
    while (user_it.hasNext() && top_count++ < top) {
      Map.Entry<String, Long> entry = user_it.next();
      abuse.getAbusiveUsers().put(entry.getKey(), entry.getValue());
    }
    // Sort Abusive IP usage
    SortedSet<Map.Entry<String, Long>> sorted_ip_calls = entriesSortedByValues(ip_map);
    Iterator<Map.Entry<String, Long>> ip_it = sorted_ip_calls.iterator();
    abuse.setAbusiveIp(new LinkedHashMap<String, Long>());
    top_count = 0;
    while (ip_it.hasNext() && top_count++ < top) {
      Map.Entry<String, Long> entry = ip_it.next();
      abuse.getAbusiveIp().put(entry.getKey(), entry.getValue());
    }

    // Sort Abusive IP usage
    SortedSet<Map.Entry<String, Long>> sorted_requests_calls = entriesSortedByValues(requests_map);
    Iterator<Map.Entry<String, Long>> requests_it = sorted_requests_calls.iterator();
    abuse.setAbusiveRequests(new LinkedHashMap<String, Long>());
    top_count = 0;
    while (requests_it.hasNext() && top_count++ < top) {
      Map.Entry<String, Long> entry = requests_it.next();
      abuse.getAbusiveRequests().put(entry.getKey(), entry.getValue());
    }

    return abuse;
  }