code: protected static void initCommunicationSummaryTreeNode(CommunicationSummaryStatistics node,
              Map<String, CommunicationSummaryStatistics> nodeMap, Set<String> usedIds) {
          for (String id : node.getOutbound().keySet()) {
              if (!usedIds.contains(id)) {
                  CommunicationSummaryStatistics orig = nodeMap.get(id);
                  CommunicationSummaryStatistics copy = null;
                  if (orig == null) {
                      log.fine("Node missing for id = " + id + " keySet = " + nodeMap.keySet());
                      // Create a placeholder for the invoked service
                      copy = new CommunicationSummaryStatistics();
                      copy.setId(id);
                  } else {
                      copy = new CommunicationSummaryStatistics(orig);
                  }
                  ConnectionStatistics cs = node.getOutbound().get(id);
                  cs.setNode(copy);
                  usedIds.add(id);
  
                  // Recusively process the added tree node
                  initCommunicationSummaryTreeNode(copy, nodeMap, usedIds);
              }
          }
      }
docs: This method recursively builds the communication summary tree, using the supplied node map,
  taking copies of each node to ensure the original list is not modified as some of the nodes
  may be shared between multiple trees. If a node is add to the tree, its id will be added to the
  'used' list, to ensure that repetitions are only handled by a link (not including the sub-tree
  multiple times).
  
  @param node The current node
  @param nodeMap The map of possible nodes
  @param usedIds The list of node ids already included in the tree