public String getTokByNode(BioFuzzParseNode node) {

    assert (node != null);
    assert (node.getMyTree() == this);

    return getTokByIdx(node.getTokIdx());
  }
  public void addNtElem(String ntName, BioFuzzParseNode elem) {

    // logger.debug("add " + ntName + "to set of NTs");

    // root is a non-terminal but should not be in this set
    // since it is required for crossover
    if (elem.getAtagType() == TagType.ROOT
        || elem.getAtagType() == TagType.TERMINAL
        || elem.getAtagType() == TagType.TOK_TERMINAL) {
      return;
    }

    assert (elem != null);

    // this part is important for crossover
    if (elem.getTokIdx() > this.pfxBarrier) {
      this.ntSuffixSet.add(ntName);
    }

    this.ntSet.add(ntName);

    if (!this.ntDict.containsKey(ntName)) {
      this.ntDict.put(ntName, new ArrayList<BioFuzzParseNode>());
    }

    this.ntDict.get(ntName).add(elem);
  }
  private int getNodeCnt(BioFuzzParseNode node) {
    if (node == null) return 0;

    int s = 1;

    List<BioFuzzParseNode> children = null;

    if (node.hasChildren() && (children = node.getChildren()) != null) {
      Iterator<BioFuzzParseNode> iter = children.iterator();

      while (iter.hasNext()) {
        s += getNodeCnt(iter.next());
      }
    }
    return s;
  }
  /** Recursively determines all non-terminal nodes. */
  private void resetNtSet(BioFuzzParseNode node) {
    assert (node != null);
    BioFuzzAttackTag atag = node.getAtag();
    assert (atag != null);

    if ((atag.getTagType() == TagType.ROOT || atag.getTagType() == TagType.NON_TERMINAL)
        && node.getVal()) {
      addNtElem(node.getAtagName(), node);
    }

    assert (node.getChildren() != null);

    for (BioFuzzParseNode child : node.getChildren()) {
      resetNtSet(child);
    }
  }
  private BioFuzzParseNode getNodeByIdx(BioFuzzParseNode node, int tokIdx) {

    if (node.getTokIdx() == tokIdx) {
      return node;
    }

    List<BioFuzzParseNode> children = null;

    if ((children = node.getChildren()) != null && node.hasChildren()) {
      Iterator<BioFuzzParseNode> iter = children.iterator();
      while (iter.hasNext()) {
        BioFuzzParseNode ret = getNodeByIdx(iter.next(), tokIdx);
        if (ret != null) return ret;
      }
    }

    return null;
  }
  private BioFuzzParseNode getNodeById(BioFuzzParseNode node, int id) {

    BioFuzzParseNode res = null;

    if (node == null) return res;

    // logger.debug("node id: " + node.getId() + "id " + id);

    if (node.getId() == id) {
      // logger.debug("here");
      res = node;
    }

    if (node.hasChildren() && res == null) {
      for (BioFuzzParseNode child : node.getChildren()) {
        if ((res = getNodeById(child, id)) != null) {
          break;
        }
      }
    }

    return res;
  }
  private String genStr(BioFuzzParseNode node, int level) {
    String s = "";

    List<BioFuzzParseNode> children = null;

    // if ((children = node.getChildren()) != null) {
    if (node.hasChildren()) {
      children = node.getChildren();
      assert (children != null);
      Iterator<BioFuzzParseNode> iter = children.iterator();

      while (iter.hasNext()) {
        BioFuzzParseNode child = iter.next();
        s += StringUtils.repeat(" ", level) + "|--" + child.toString();
        s +=
            "[AttackTag: "
                + child.getAtagName()
                + "("
                + child.getAtagType().toString()
                + ")"
                + "("
                + child.getVal()
                + ")]\n"
                + genStr(child, level + 1);
      }
    } else {
      if (this.tokLst != null) {
        s += StringUtils.repeat(" ", level) + "|--" + node.toString();

        s +=
            "[Tok: "
                + this.tokLst.get(node.getTokIdx())
                + "("
                + node.getAtagType().toString()
                + ")"
                + "("
                + node.getVal()
                + ")]\n";
      }
    }
    // }
    return s;
  }