class EdgeFilter extends Filter {
    protected EdgeFilter() {
      super(new EdgePredicate() {
        @Override
        public boolean want(Edge e) {
          return e.kind().isExplicit() || e.kind().isFake() || e.kind().isClinit()
              || (includeReflectiveCalls && e.kind().isReflection());
        }
      });
    }

    public EdgeFilter(EdgePredicate p) {
      super(p);
    }
  }

  @DontSynchronize("readonly")
  protected final CallGraph cg;

  protected CacheLoader<Unit, Collection<SootMethod>> loaderUnitToCallees = new CacheLoader<Unit, Collection<SootMethod>>() {
    @Override
    public Collection<SootMethod> load(Unit u) throws Exception {
      ArrayList<SootMethod> res = null;
      // only retain callers that are explicit call sites or
      // Thread.start()
      Iterator<Edge> edgeIter = createEdgeFilter().wrap(cg.edgesOutOf(u));
      while (edgeIter.hasNext()) {
        Edge edge = edgeIter.next();
        SootMethod m = edge.getTgt().method();
        if (includePhantomCallees || m.hasActiveBody()) {
          if (res == null) {
            res = new ArrayList<SootMethod>();
          }
          res.add(m);
        } else if (IDESolver.DEBUG) {
          logger.error(String.format("Method %s is referenced but has no body!", m.getSignature(), new Exception()));
        }
      }

      if (res != null) {
        res.trimToSize();
        return res;
      } else {
        if (fallbackToImmediateCallees && u instanceof Stmt) {
          Stmt s = (Stmt) u;
          if (s.containsInvokeExpr()) {
            SootMethod immediate = s.getInvokeExpr().getMethod();
            if (includePhantomCallees || immediate.hasActiveBody()) {
              return Collections.singleton(immediate);
            }
          }
        }
        return Collections.emptySet();
      }
    }

  };

  @SynchronizedBy("by use of synchronized LoadingCache class")
  protected final LoadingCache<Unit, Collection<SootMethod>> unitToCallees
      = IDESolver.DEFAULT_CACHE_BUILDER.build(loaderUnitToCallees);

  protected CacheLoader<SootMethod, Collection<Unit>> loaderMethodToCallers
      = new CacheLoader<SootMethod, Collection<Unit>>() {
        @Override
        public Collection<Unit> load(SootMethod m) throws Exception {<FILL_FUNCTION_BODY>

          ArrayList<Unit> res = new ArrayList<Unit>();
          // only retain callers that are explicit call sites or
          // Thread.start()
          Iterator<Edge> edgeIter = createEdgeFilter().wrap(cg.edgesInto(m));
          while (edgeIter.hasNext()) {
            Edge edge = edgeIter.next();
            res.add(edge.srcUnit());
          }
          res.trimToSize();
          return res;
        
<methods>public void <init>() ,public void <init>(boolean) ,public Set<soot.Unit> allNonCallEndNodes() ,public Set<soot.Unit> allNonCallStartNodes() ,public soot.Body getBodyOf(soot.Unit) ,public Set<soot.Unit> getCallsFromWithin(soot.SootMethod) ,public Collection<soot.Unit> getEndPointsOf(soot.SootMethod) ,public soot.SootMethod getMethodOf(soot.Unit) ,public DirectedGraph<soot.Unit> getOrCreateUnitGraph(soot.SootMethod) ,public DirectedGraph<soot.Unit> getOrCreateUnitGraph(soot.Body) ,public List<soot.Value> getParameterRefs(soot.SootMethod) ,public List<soot.Unit> getPredsOf(soot.Unit) ,public List<soot.Unit> getPredsOfCallAt(soot.Unit) ,public Collection<soot.Unit> getReturnSitesOfCallAt(soot.Unit) ,public Collection<soot.Unit> getStartPointsOf(soot.SootMethod) ,public List<soot.Unit> getSuccsOf(soot.Unit) ,public void initializeUnitToOwner(soot.SootMethod) ,public void initializeUnitToOwner(soot.Body) ,public boolean isBranchTarget(soot.Unit, soot.Unit) ,public boolean isCallStmt(soot.Unit) ,public boolean isExitStmt(soot.Unit) ,public boolean isFallThroughSuccessor(soot.Unit, soot.Unit) ,public boolean isReachable(soot.Unit) ,public boolean isReturnSite(soot.Unit) ,public boolean isStartPoint(soot.Unit) ,public boolean setOwnerStatement(soot.Unit, soot.Body) <variables>protected LoadingCache<soot.Body,DirectedGraph<soot.Unit>> bodyToUnitGraph,protected final non-sealed boolean enableExceptions,protected LoadingCache<soot.SootMethod,Set<soot.Unit>> methodToCallsFromWithin,protected LoadingCache<soot.SootMethod,List<soot.Value>> methodToParameterRefs,private final Map<soot.Unit,soot.Body> unitToOwner