docs: public List<Path> calcPaths(GHRequest request, GHResponse ghRsp) {
          if (ghStorage == null || !fullyLoaded)
              throw new IllegalStateException("Do a successful call to load or importOrLoad before routing");
  
          if (ghStorage.isClosed())
              throw new IllegalStateException("You need to create a new GraphHopper instance as it is already closed");
  
          // default handling
          String vehicle = request.getVehicle();
          if (vehicle.isEmpty()) {
              vehicle = getDefaultVehicle().toString();
              request.setVehicle(vehicle);
          }
  
          Lock readLock = readWriteLock.readLock();
          readLock.lock();
          try {
              if (!encodingManager.hasEncoder(vehicle))
                  throw new IllegalArgumentException("Vehicle not supported: " + vehicle + ". Supported are: " + encodingManager.toString());
  
              HintsMap hints = request.getHints();
              String tModeStr = hints.get("traversal_mode", traversalMode.toString());
              TraversalMode tMode = TraversalMode.fromString(tModeStr);
              if (hints.has(Routing.EDGE_BASED))
                  tMode = hints.getBool(Routing.EDGE_BASED, false) ? TraversalMode.EDGE_BASED_2DIR : TraversalMode.NODE_BASED;
  
              FlagEncoder encoder = encodingManager.getEncoder(vehicle);
  
              boolean disableCH = hints.getBool(CH.DISABLE, false);
              if (!chFactoryDecorator.isDisablingAllowed() && disableCH)
                  throw new IllegalArgumentException("Disabling CH not allowed on the server-side");
  
              boolean disableLM = hints.getBool(Landmark.DISABLE, false);
              if (!lmFactoryDecorator.isDisablingAllowed() && disableLM)
                  throw new IllegalArgumentException("Disabling LM not allowed on the server-side");
  
              String algoStr = request.getAlgorithm();
              if (algoStr.isEmpty())
                  algoStr = chFactoryDecorator.isEnabled() && !disableCH ? DIJKSTRA_BI : ASTAR_BI;
  
              List<GHPoint> points = request.getPoints();
              // TODO Maybe we should think about a isRequestValid method that checks all that stuff that we could do to fail fast
              // For example see #734
              checkIfPointsAreInBounds(points);
  
              RoutingTemplate routingTemplate;
              if (ROUND_TRIP.equalsIgnoreCase(algoStr))
                  routingTemplate = new RoundTripRoutingTemplate(request, ghRsp, locationIndex, encodingManager, maxRoundTripRetries);
              else if (ALT_ROUTE.equalsIgnoreCase(algoStr))
                  routingTemplate = new AlternativeRoutingTemplate(request, ghRsp, locationIndex, encodingManager);
              else
                  routingTemplate = new ViaRoutingTemplate(request, ghRsp, locationIndex, encodingManager);
  
              List<Path> altPaths = null;
              int maxRetries = routingTemplate.getMaxRetries();
              Locale locale = request.getLocale();
              Translation tr = trMap.getWithFallBack(locale);
              for (int i = 0; i < maxRetries; i++) {
                  StopWatch sw = new StopWatch().start();
                  List<QueryResult> qResults = routingTemplate.lookup(points, encoder);
                  ghRsp.addDebugInfo("idLookup:" + sw.stop().getSeconds() + "s");
                  if (ghRsp.hasErrors())
                      return Collections.emptyList();
  
                  RoutingAlgorithmFactory tmpAlgoFactory = getAlgorithmFactory(hints);
                  Weighting weighting;
                  QueryGraph queryGraph;
  
                  if (chFactoryDecorator.isEnabled() && !disableCH) {
                      boolean forceCHHeading = hints.getBool(CH.FORCE_HEADING, false);
                      if (!forceCHHeading && request.hasFavoredHeading(0))
                          throw new IllegalArgumentException("Heading is not (fully) supported for CHGraph. See issue #483");
  
                      // if LM is enabled we have the LMFactory with the CH algo!
                      RoutingAlgorithmFactory chAlgoFactory = tmpAlgoFactory;
                      if (tmpAlgoFactory instanceof LMAlgoFactoryDecorator.LMRAFactory)
                          chAlgoFactory = ((LMAlgoFactoryDecorator.LMRAFactory) tmpAlgoFactory).getDefaultAlgoFactory();
  
                      if (chAlgoFactory instanceof PrepareContractionHierarchies)
                          weighting = ((PrepareContractionHierarchies) chAlgoFactory).getWeighting();
                      else
                          throw new IllegalStateException("Although CH was enabled a non-CH algorithm factory was returned " + tmpAlgoFactory);
  
                      queryGraph = new QueryGraph(ghStorage.getGraph(CHGraph.class, weighting));
                      queryGraph.lookup(qResults);
                  } else {
                      checkNonChMaxWaypointDistance(points);
                      queryGraph = new QueryGraph(ghStorage);
                      queryGraph.lookup(qResults);
                      weighting = createWeighting(hints, encoder, queryGraph);
                  }
                  ghRsp.addDebugInfo("tmode:" + tMode.toString());
  
                  int maxVisitedNodesForRequest = hints.getInt(Routing.MAX_VISITED_NODES, maxVisitedNodes);
                  if (maxVisitedNodesForRequest > maxVisitedNodes)
                      throw new IllegalArgumentException("The max_visited_nodes parameter has to be below or equal to:" + maxVisitedNodes);
  
                  weighting = createTurnWeighting(queryGraph, weighting, tMode);
  
                  AlgorithmOptions algoOpts = AlgorithmOptions.start().
                          algorithm(algoStr).traversalMode(tMode).weighting(weighting).
                          maxVisitedNodes(maxVisitedNodesForRequest).
                          hints(hints).
                          build();
  
                  // do the actual route calculation !
                  altPaths = routingTemplate.calcPaths(queryGraph, tmpAlgoFactory, algoOpts);
  
                  boolean tmpEnableInstructions = hints.getBool(Routing.INSTRUCTIONS, getEncodingManager().isEnableInstructions());
                  boolean tmpCalcPoints = hints.getBool(Routing.CALC_POINTS, calcPoints);
                  double wayPointMaxDistance = hints.getDouble(Routing.WAY_POINT_MAX_DISTANCE, 1d);
  
                  DouglasPeucker peucker = new DouglasPeucker().setMaxDistance(wayPointMaxDistance);
                  PathMerger pathMerger = new PathMerger().
                          setCalcPoints(tmpCalcPoints).
                          setDouglasPeucker(peucker).
                          setEnableInstructions(tmpEnableInstructions).
                          setPathDetailsBuilders(pathBuilderFactory, request.getPathDetails()).
                          setSimplifyResponse(simplifyResponse && wayPointMaxDistance > 0);
  
                  if (request.hasFavoredHeading(0))
                      pathMerger.setFavoredHeading(request.getFavoredHeading(0));
  
                  if (routingTemplate.isReady(pathMerger, tr))
                      break;
              }
  
              return altPaths;
  
          } catch (IllegalArgumentException ex) {
              ghRsp.addError(ex);
              return Collections.emptyList();
          } finally {
              readLock.unlock();
          }
      }