Basicamente você precisa inverter uma "call tree" (árvore de chamadas).
Digamos que você tenha uma lista de métodos (para simplificar, vou representar os métodos pelos seus nomes):
List <String> metodos;
E a seguir, um mapa nome do método -> nomes dos métodos chamados:
Map <String, List ><String> > metodo2chamados;
Para você determinar quais são os métodos "chamadores" (é o que você quer, na verdade), basta percorrer o mapa metodo2chamados, mais ou menos assim:
import java.util.*;
class ExemploCallTree {
// utilitário
// Usamos a chave "s" para inserir em "m" o valor "t".
private void insert (Map < String, Set < String > > m, String s, String t) {
Set < String> v;
if (m.containsKey (s)) {
v = m.get (s);
} else {
v = new TreeSet < String>();
m.put (s, v);
}
v.add (t);
}
public Map < String, Set < String > > carregarMetodosChamados() {
Map < String, Set < String > > m = new TreeMap < String, Set < String > > ();
// O método a chama b
insert (m, "a", "b");
// O método b chama c ou m
insert (m, "b", "c");
insert (m, "b", "m");
return m;
}
// note que aqui estamos invertendo a árvore mas determinando apenas o
// primeiro nivel de chamadas. Para termos mais niveis, temos de tomar cuidado
// com rotinas recursivas ou mutuamente recursivas.
public Map < String, Set < String > > determinarMetodosChamadores(Map < String, Set < String > > metodo2chamados) {
Map < String, Set < String > > metodo2chamadores = new TreeMap < String, Set < String > > ();
for (Map.Entry< String, Set < String > > entry : metodo2chamados.entrySet()) {
String chamador = entry.getKey();
for (String chamado : entry.getValue()) {
insert (metodo2chamadores, chamado, chamador);
}
}
return metodo2chamadores;
}
public static void main (String[] args) {
ExemploCallTree ect = new ExemploCallTree();
Map < String, Set < String > > metodo2chamados = ect.carregarMetodosChamados();
System.out.println ("Metodo -> metodos chamados");
System.out.println (metodo2chamados);
System.out.println ("Metodo -> metodos chamadores (1 nivel apenas)");
Map < String, Set < String > > metodo2chamadores = ect.determinarMetodosChamadores(metodo2chamados);
System.out.println (metodo2chamadores);
}
}
Se você olhar a saída, vai ver que é um pouco diferente do que você está esperando. É que eu estou percorrendo apenas o primeiro nível (ou seja, eu sei que quem chama diretamente c é b, mas não mostro que a chama indiretamente c. Para fazer isso direito, eu precisaria levar em conta que rotinas podem ser recursivas ou mutuamente recursivas, senão o programa entraria em loop.