/**
  * Return a view of an {@link IClassHierarchy} as a {@link Graph}, with edges from classes to
  * immediate subtypes
  */
 public static Graph<IClass> typeHierarchy2Graph(IClassHierarchy cha) throws WalaException {
   Graph<IClass> result = SlowSparseNumberedGraph.make();
   for (IClass c : cha) {
     result.addNode(c);
   }
   for (IClass c : cha) {
     for (IClass x : cha.getImmediateSubclasses(c)) {
       result.addEdge(c, x);
     }
     if (c.isInterface()) {
       for (IClass x : cha.getImplementors(c.getReference())) {
         result.addEdge(c, x);
       }
     }
   }
   return result;
 }
  /**
   * Returns all concrete classes implementing the given interface or any subinterfaces
   *
   * @param iRoot
   * @return
   */
  public Collection<IClass> concreteClassesForInterface(IClass iRoot) {
    Set<IClass> clazzes = HashSetFactory.make();
    Set<IClass> done = HashSetFactory.make();
    Deque<IClass> todo = Queues.newArrayDeque();
    todo.push(iRoot);

    while (!todo.isEmpty()) {
      IClass i = todo.pop();
      for (IClass clazz : cha.getImplementors(i.getReference())) {
        if (clazz.isInterface() && !done.contains(clazz)) {
          done.add(i);
          todo.push(clazz);
        } else if (!clazz.isAbstract()) {
          clazzes.add(clazz);
        }
      }
    }

    return clazzes;
  }
  public static Iterable<Entrypoint> makePrimordialPublicEntrypoints(
      AnalysisScope scope, ClassHierarchy cha, String pkg) {
    final HashSet<Entrypoint> result = HashSetFactory.make();
    for (IClass clazz : cha) {

      if (clazz.getName().toString().indexOf(pkg) != -1
          && !clazz.isInterface()
          && !clazz.isAbstract()) {
        for (IMethod method : clazz.getDeclaredMethods()) {
          if (method.isPublic() && !method.isAbstract()) {
            System.out.println("Entry:" + method.getReference());
            result.add(new DefaultEntrypoint(method, cha));
          }
        }
      }
    }
    return new Iterable<Entrypoint>() {
      @Override
      public Iterator<Entrypoint> iterator() {
        return result.iterator();
      }
    };
  }