@SuppressWarnings("unchecked")
 private void preprocessRoute(
     BaseRoute routeToWrite,
     NavigationFormat format,
     boolean duplicateFirstPosition,
     ParserCallback parserCallback) {
   if (format instanceof NmnFormat) routeToWrite.removeDuplicates();
   if (format instanceof NmnFormat && duplicateFirstPosition)
     routeToWrite.add(0, ((NmnFormat) format).getDuplicateFirstPosition(routeToWrite));
   if (format instanceof CoPilotFormat && duplicateFirstPosition)
     routeToWrite.add(0, ((CoPilotFormat) format).getDuplicateFirstPosition(routeToWrite));
   if (format instanceof TcxFormat) routeToWrite.ensureIncreasingTime();
   if (parserCallback != null) parserCallback.preprocess(routeToWrite, format);
 }
  @SuppressWarnings("unchecked")
  private void write(
      BaseRoute route,
      NavigationFormat format,
      boolean duplicateFirstPosition,
      boolean ignoreMaximumPositionCount,
      ParserCallback parserCallback,
      OutputStream... targets)
      throws IOException {
    log.info(
        "Writing '"
            + format.getName()
            + "' position lists with 1 route and "
            + route.getPositionCount()
            + " positions");

    BaseRoute routeToWrite = asFormat(route, format);
    commentRoute(routeToWrite);
    preprocessRoute(routeToWrite, format, duplicateFirstPosition, parserCallback);

    int positionsToWrite = routeToWrite.getPositionCount();
    int writeInOneChunk = format.getMaximumPositionCount();

    // check if the positions to write fit within the given files
    if (positionsToWrite > targets.length * writeInOneChunk) {
      if (ignoreMaximumPositionCount) writeInOneChunk = positionsToWrite;
      else
        throw new IOException(
            "Found "
                + positionsToWrite
                + " positions, "
                + format.getName()
                + " format may only contain "
                + writeInOneChunk
                + " positions in one position list.");
    }

    int startIndex = 0;
    for (int i = 0; i < targets.length; i++) {
      OutputStream target = targets[i];
      int endIndex = min(startIndex + writeInOneChunk, positionsToWrite);
      renameRoute(route, routeToWrite, startIndex, endIndex, i, targets);
      format.write(routeToWrite, target, startIndex, endIndex);
      log.info("Wrote position list from " + startIndex + " to " + endIndex);
      startIndex += writeInOneChunk;
    }

    postProcessRoute(routeToWrite, format, duplicateFirstPosition);
  }
 public static int getNumberOfFilesToWriteFor(
     BaseRoute route, NavigationFormat format, boolean duplicateFirstPosition) {
   return ceiling(
       route.getPositionCount() + (duplicateFirstPosition ? 1 : 0),
       format.getMaximumPositionCount(),
       true);
 }
 @SuppressWarnings("unchecked")
 private void renameRoute(
     BaseRoute route,
     BaseRoute routeToWrite,
     int startIndex,
     int endIndex,
     int trackIndex,
     OutputStream... targets) {
   // gives splitted TomTomRoute and SimpleRoute routes a more useful name for the fragment
   if (route.getFormat() instanceof TomTomRouteFormat
       || route.getFormat() instanceof SimpleFormat
       || route.getFormat() instanceof GpxFormat
           && routeToWrite.getFormat() instanceof BcrFormat) {
     String name = createRouteName(routeToWrite.getPositions().subList(startIndex, endIndex));
     if (targets.length > 1) name = "Track" + (trackIndex + 1) + ": " + name;
     routeToWrite.setName(name);
   }
 }
  private NavigationFormat determineFormat(
      List<BaseRoute> routes, NavigationFormat preferredFormat) {
    NavigationFormat result = preferredFormat;
    for (BaseRoute route : routes) {
      // more than one route: the same result
      if (result.equals(route.getFormat())) continue;

      // result is capable of storing multiple routes
      if (result.isSupportsMultipleRoutes()) continue;

      // result from GPSBabel-based format which allows only one route but is represented by GPX 1.0
      if (result instanceof BabelFormat) continue;

      // default for multiple routes is GPX 1.1
      result = new Gpx11Format();
    }
    return result;
  }
 private List<Integer> getPositionCounts(List<BaseRoute> routes) {
   List<Integer> positionCounts = new ArrayList<>();
   for (BaseRoute route : routes) positionCounts.add(route.getPositionCount());
   return positionCounts;
 }
 private void postProcessRoute(
     BaseRoute routeToWrite, NavigationFormat format, boolean duplicateFirstPosition) {
   if ((format instanceof NmnFormat || format instanceof CoPilotFormat) && duplicateFirstPosition)
     routeToWrite.remove(0);
 }
 @SuppressWarnings("unchecked")
 private void commentRoute(BaseRoute route) {
   commentPositions(route.getPositions());
   commentRouteName(route);
 }