extensions/grapher/src/com/google/inject/grapher/AbstractInjectorGrapher.java
private Map<NodeId, NodeId> resolveAliases(Iterable<Alias> aliases) {
    Map<NodeId, NodeId> resolved = Maps.newHashMap();
    SetMultimap<NodeId, NodeId> inverse = HashMultimap.create();

    for (Alias alias : aliases) {
      NodeId from = alias.getFromId();
      NodeId to = alias.getToId();
      if (resolved.containsKey(to)) {
        to = resolved.get(to);
      }
      resolved.put(from, to);
      inverse.put(to, from);

      Set<NodeId> prev = inverse.get(from);
      if (prev != null) {
        for (NodeId id : prev) {
          resolved.remove(id);
          inverse.remove(from, id);
          resolved.put(id, to);
          inverse.put(to, id);
        }
      }
    }

    return resolved;
  }
private Map<NodeId, NodeId> resolveAliases(Iterable<Alias> aliases) {
    Map<NodeId, NodeId> resolved = Maps.newHashMap();
    SetMultimap<NodeId, NodeId> inverse = HashMultimap.create();

    for (Alias alias : aliases) {
      NodeId from = alias.getFromId();
      NodeId to = alias.getToId();
      if (resolved.containsKey(to)) {
        to = resolved.get(to);
      }
      resolved.put(from, to);
      inverse.put(to, from);

      Set<NodeId> prev = inverse.get(from);
      if (prev != null) {
        for (NodeId id : prev) {
          resolved.remove(id);
          inverse.remove(from, id);
          resolved.put(id, to);
          inverse.put(to, id);
        }
      }
    }

    return resolved;
  }
Transitively resolves aliases. Given aliases (X to Y) and (Y to Z), it will return mappings (X
to Z) and (Y to Z).