/**
   * Requires vn to point to a relation element. From there it iterates over all matches of the ap.
   * Puts an empty list for each referenced way.
   */
  private List<Tuple2<WayRole, Long>> extractWayRefs(VTDNav vn, Hashtable<Long, List<Long>> ways)
      throws NavException, XPathEvalException {
    vn.push();

    List<Tuple2<WayRole, Long>> refs = new ArrayList<>();
    for (int j = MEMBER_WAY_PATH.evalXPath(); j != -1; j = MEMBER_WAY_PATH.evalXPath()) {
      long ref = Long.parseLong(vn.toString(vn.getAttrVal("ref")));
      String roleAsString = vn.toString(vn.getAttrVal("role")).toLowerCase();
      WayRole role;
      switch (roleAsString) {
        case "inner":
          role = WayRole.INNER;
          break;
        case "outer":
          role = WayRole.OUTER;
          break;
        default:
          continue;
      }
      refs.add(Tuple.tuple(role, ref));
      ways.put(ref, Collections.emptyList());
    }
    MEMBER_WAY_PATH.resetXPath();

    vn.pop();

    return refs;
  }
  private void extractReferencedWays(
      VTDNav vn, Hashtable<Long, List<Long>> ways, Hashtable<Long, Point2D> nodes)
      throws XPathEvalException, NavException {
    vn.push();

    for (int i = WAY_PATH.evalXPath(); i != -1; i = WAY_PATH.evalXPath()) {
      long id = Long.parseLong(vn.toString(vn.getAttrVal("id")));
      // By checking that we already referenced the id we can reduce memory pressure
      if (ways.containsKey(id)) {
        ways.put(id, extractNodeRefs(vn, nodes));
      }
    }

    vn.pop();
  }
  /**
   * Requires vn to point to a way element. From there it iterates over all matches of the ap. Puts
   * a dummy point into nodes for every node it finds.
   */
  private List<Long> extractNodeRefs(VTDNav vn, Hashtable<Long, Point2D> nodes)
      throws NavException, XPathEvalException {
    vn.push();

    List<Long> refs = new ArrayList<>();
    for (int j = NODE_REF_PATH.evalXPath(); j != -1; j = NODE_REF_PATH.evalXPath()) {
      long ref = Long.parseLong(vn.toString(j + 1));
      refs.add(ref);
      nodes.put(ref, new Point2D(0, 0));
    }
    NODE_REF_PATH.resetXPath();

    vn.pop();

    return refs;
  }
  private void extractReferencedNodes(VTDNav vn, Hashtable<Long, Point2D> nodes)
      throws XPathEvalException, NavException {
    vn.push();

    for (int i = NODE_PATH.evalXPath(); i != -1; i = NODE_PATH.evalXPath()) {
      long id = Long.parseLong(vn.toString(vn.getAttrVal("id")));
      // By checking that we already referenced the id we can reduce memory pressure
      if (nodes.containsKey(id)) {
        nodes.put(
            id,
            new Point2D(
                Double.parseDouble(vn.toString(vn.getAttrVal("lon"))) * (1 << 10),
                Double.parseDouble(vn.toString(vn.getAttrVal("lat"))) * (1 << 10)));
      }
    }

    // Make sure we have all referenced nodes extracted
    // assert !nodes.containsValue(DUMMY_POINT);

    vn.pop();
  }