private void cleanSchedule() {
   for (TransitLine line : this.schedule.getTransitLines().values()) {
     Set<TransitRoute> toRemove = new HashSet<>();
     for (TransitRoute transitRoute : line.getRoutes().values()) {
       boolean removeRoute = false;
       NetworkRoute networkRoute = transitRoute.getRoute();
       if (networkRoute.getStartLinkId() == null || networkRoute.getEndLinkId() == null) {
         removeRoute = true;
       }
       for (Id<Link> linkId : transitRoute.getRoute().getLinkIds()) {
         if (linkId == null) {
           removeRoute = true;
         }
       }
       if (removeRoute) {
         log.error(
             "NetworkRoute for " + transitRoute.getId().toString() + " incomplete. Remove route.");
         toRemove.add(transitRoute);
       }
     }
     if (!toRemove.isEmpty()) {
       for (TransitRoute transitRoute : toRemove) {
         line.removeRoute(transitRoute);
       }
     }
   }
 }
 private void removeNonUsedStopFacilities() {
   // Collect all used stop facilities:
   Set<Id<TransitStopFacility>> usedStopFacilities = new HashSet<>();
   for (TransitLine line : this.schedule.getTransitLines().values()) {
     for (TransitRoute route : line.getRoutes().values()) {
       for (TransitRouteStop stop : route.getStops()) {
         usedStopFacilities.add(stop.getStopFacility().getId());
       }
     }
   }
   // Check all stop facilities if not used:
   Set<TransitStopFacility> unusedStopFacilites = new HashSet<>();
   for (Id<TransitStopFacility> facilityId : this.schedule.getFacilities().keySet()) {
     if (!usedStopFacilities.contains(facilityId)) {
       unusedStopFacilites.add(this.schedule.getFacilities().get(facilityId));
     }
   }
   // Remove all stop facilities not used:
   for (TransitStopFacility facility : unusedStopFacilites) {
     this.schedule.removeStopFacility(facility);
   }
 }
 /**
  * Add to any link that is passed by any route a "pt" in the modes, if it hasn't already one...
  */
 private void prepareNetwork() {
   Map<Id<Link>, ? extends Link> networkLinks = network.getLinks();
   Set<Id<Link>> transitLinks = new HashSet<>();
   for (TransitLine line : this.schedule.getTransitLines().values()) {
     for (TransitRoute transitRoute : line.getRoutes().values()) {
       NetworkRoute networkRoute = transitRoute.getRoute();
       transitLinks.add(networkRoute.getStartLinkId());
       for (Id<Link> linkId : transitRoute.getRoute().getLinkIds()) {
         transitLinks.add(linkId);
       }
       transitLinks.add(networkRoute.getEndLinkId());
     }
   }
   for (Id<Link> transitLinkId : transitLinks) {
     Link transitLink = networkLinks.get(transitLinkId);
     if (!transitLink.getAllowedModes().contains(TransportMode.pt)) {
       Set<String> modes = new HashSet<>();
       modes.addAll(transitLink.getAllowedModes());
       modes.add(TransportMode.pt);
       transitLink.setAllowedModes(modes);
     }
   }
 }
  private void assignRoute(TransitRoute route) {

    List<Id<Link>> links = new ArrayList<>();
    int i = 0;
    while (i < (route.getStops().size())) {
      TransitRouteStop presentStop = route.getStops().get(i);
      TransitRouteStop nextStop =
          (i < route.getStops().size() - 1) ? route.getStops().get(i + 1) : null;

      if (nextStop != null) {

        // 	Case 1: For both stops a link assigned, then just route between the two.
        if (linkedStopFacilities.contains(presentStop.getStopFacility().getId())
            && linkedStopFacilities.contains(nextStop.getStopFacility().getId())) {
          links.add(presentStop.getStopFacility().getLinkId());

          Node startNode =
              this.network.getLinks().get(presentStop.getStopFacility().getLinkId()).getToNode();
          LeastCostPathCalculator.Path path = getShortestPath(startNode, nextStop);
          if (path != null) {
            for (Link link : path.links) {
              links.add(link.getId());
            }
          } else {
            Node fromNode =
                network.getLinks().get(presentStop.getStopFacility().getLinkId()).getToNode();
            Node toNode =
                network.getLinks().get(nextStop.getStopFacility().getLinkId()).getFromNode();
            Link artificialLink =
                (artificiallyAddedLinks.containsKey(new Tuple<>(fromNode, toNode)))
                    ? artificiallyAddedLinks.get(new Tuple<>(fromNode, toNode))
                    : getNewLink(fromNode, toNode);
            links.add(artificialLink.getId());
            artificiallyAddedLinks.put(new Tuple<>(fromNode, toNode), artificialLink);
          }

          // Case 2: PresentStop has no link, but NextStop has link then create link to closest
          // network node and route between that node and link of follow-stop.
        } else if (!linkedStopFacilities.contains(presentStop.getStopFacility().getId())
            && linkedStopFacilities.contains(nextStop.getStopFacility().getId())) {

          ArtificiallyConnectedStopFacility thisStopFacility =
              getArtificiallyConnectedStopFacility(presentStop.getStopFacility());
          Node toNode =
              network.getLinks().get(nextStop.getStopFacility().getLinkId()).getFromNode();

          links.add(thisStopFacility.myLink.getId());
          links.add(thisStopFacility.getLinkToNode(toNode).getId());

          // Case 3: PresentStop has link, but NextStop has no link then create link to closest
          // network node for follow stop and then route between the two.
        } else if (linkedStopFacilities.contains(presentStop.getStopFacility().getId())
            && !linkedStopFacilities.contains(nextStop.getStopFacility().getId())) {

          ArtificiallyConnectedStopFacility nextStopFacility =
              getArtificiallyConnectedStopFacility(nextStop.getStopFacility());
          Node fromNode =
              network.getLinks().get(presentStop.getStopFacility().getLinkId()).getToNode();

          links.add(presentStop.getStopFacility().getLinkId());
          links.add(nextStopFacility.getLinkFromNode(fromNode).getId());

          // Case 4: Neither PresentStop nor NextStop has link then standard link creation as with
          // Marcel's network creator.
        } else {
          ArtificiallyConnectedStopFacility thisStopFacility =
              getArtificiallyConnectedStopFacility(presentStop.getStopFacility());
          ArtificiallyConnectedStopFacility nextStopFacility =
              getArtificiallyConnectedStopFacility(nextStop.getStopFacility());

          links.add(thisStopFacility.myLink.getId());
          links.add(nextStopFacility.getLinkFromNode(thisStopFacility.myNode).getId());
        }

        // If nextStop was null, this means we have reached the end of the route and just add the
        // final link.
      } else {
        if (linkedStopFacilities.contains(presentStop.getStopFacility().getId())) {
          links.add(presentStop.getStopFacility().getLinkId());
        } else {
          ArtificiallyConnectedStopFacility thisStopFacility =
              getArtificiallyConnectedStopFacility(presentStop.getStopFacility());
          links.add(thisStopFacility.myLink.getId());
        }
      }

      i++;
    }
    if (links.size() > 0) {
      route.setRoute(RouteUtils.createNetworkRoute(links, this.network));
    } else {
      log.warn("No route found for transit route " + route.toString() + ". No route assigned.");
    }
  }