public StateEditor(State parent, Edge e) {
   child = parent.clone();
   child.backState = parent;
   child.backEdge = e;
   // We clear child.next here, since it could have already been set in the
   // parent
   child.next = null;
   if (e == null) {
     child.backState = null;
     child.hops = 0;
     child.vertex = parent.vertex;
     child.stateData = child.stateData.clone();
   } else {
     child.hops = parent.hops + 1;
     // be clever
     // Note that we use equals(), not ==, here to allow for dynamically
     // created vertices
     if (e.getFromVertex().equals(e.getToVertex()) && parent.vertex.equals(e.getFromVertex())) {
       // TODO LG: We disable this test: the assumption that
       // the from and to vertex of an edge are not the same
       // is not true anymore: bike rental on/off edges.
       traversingBackward = parent.getOptions().isArriveBy();
       child.vertex = e.getToVertex();
     } else if (parent.vertex.equals(e.getFromVertex())) {
       traversingBackward = false;
       child.vertex = e.getToVertex();
     } else if (parent.vertex.equals(e.getToVertex())) {
       traversingBackward = true;
       child.vertex = e.getFromVertex();
     } else {
       // Parent state is not at either end of edge.
       LOG.warn("Edge is not connected to parent state: {}", e);
       LOG.warn("   from   vertex: {}", e.getFromVertex());
       LOG.warn("   to     vertex: {}", e.getToVertex());
       LOG.warn("   parent vertex: {}", parent.vertex);
       defectiveTraversal = true;
     }
     if (traversingBackward != parent.getOptions().isArriveBy()) {
       LOG.error(
           "Actual traversal direction does not match traversal direction in TraverseOptions.");
       defectiveTraversal = true;
     }
     if (parent.stateData.noThruTrafficState == NoThruTrafficState.INIT
         && !(e instanceof FreeEdge)) {
       setNoThruTrafficState(NoThruTrafficState.BETWEEN_ISLANDS);
     }
   }
 }
 public StateEditor(RoutingRequest options, Vertex v) {
   child = new State(v, options);
   child.stateData = new StateData(options);
 }
 /**
  * To be called before modifying anything in the child's StateData. Makes sure that changes are
  * applied to a copy of StateData rather than the same one that is still referenced in existing,
  * older states.
  */
 private void cloneStateDataAsNeeded() {
   if (child.backState != null && child.stateData == child.backState.stateData)
     child.stateData = child.stateData.clone();
 }