class SimpleDominatorsFinder<N> implements DominatorsFinder<N> {
  private static final Logger logger = LoggerFactory.getLogger(SimpleDominatorsFinder.class);

  protected final DirectedGraph<N> graph;
  protected final Map<N, FlowSet<N>> nodeToDominators;

  /**
   * Compute dominators for provided singled-headed directed graph.
   **/
  public SimpleDominatorsFinder(DirectedGraph<N> graph) {
    // if(Options.v().verbose())
    // logger.debug("[" + graph.getBody().getMethod().getName() +
    // "] Finding Dominators...");

    this.graph = graph;
    this.nodeToDominators = new HashMap<N, FlowSet<N>>(graph.size() * 2 + 1, 0.7f);

    // build node to dominators map
    SimpleDominatorsAnalysis<N> analysis = new SimpleDominatorsAnalysis<N>(graph);
    for (N node : graph) {
      this.nodeToDominators.put(node, analysis.getFlowAfter(node));
    }
  }

  @Override
  public DirectedGraph<N> getGraph() {
    return graph;
  }

  @Override
  public List<N> getDominators(N node) {
    // non-backed list since FlowSet is an ArrayPackedFlowSet
    return nodeToDominators.get(node).toList();
  }

  @Override
  public N getImmediateDominator(N node) {
    // root node
    if (getGraph().getHeads().contains(node)) {
      return null;
    }

    // avoid the creation of temp-lists
    FlowSet<N> head = nodeToDominators.get(node).clone();
    head.remove(node);

    for (N dominator : head) {
      if (nodeToDominators.get(dominator).isSubSet(head)) {
        return dominator;
      }
    }
    return null;
  }

  @Override
  public boolean isDominatedBy(N node, N dominator) {
    // avoid the creation of temp-lists
    return nodeToDominators.get(node).contains(dominator);
  }

  @Override
  public boolean isDominatedByAll(N node, Collection<N> dominators) {<FILL_FUNCTION_BODY>}
}

    FlowSet<N> f = nodeToDominators.get(node);
    for (N n : dominators) {
      if (!f.contains(n)) {
        return false;
      }
    }
    return true;
  
<no_super_class>