private BaseNavigationFormat findFormat(String formatName) {
   List<NavigationFormat> formats = NavigationFormats.getWriteFormats();
   for (NavigationFormat format : formats)
     if (formatName.equals(format.getClass().getSimpleName()))
       return (BaseNavigationFormat) format;
   return null;
 }
  private void convert(File source, NavigationFormat format, File target) throws IOException {
    NavigationFileParser parser = new NavigationFileParser();
    if (!parser.read(source)) {
      log.severe("Could not read source '" + source.getAbsolutePath() + "'");
      logFormatNames(NavigationFormats.getReadFormatsSortedByName());
      System.exit(20);
    }

    if (format.isSupportsMultipleRoutes()) {
      parser.write(parser.getAllRoutes(), (MultipleRoutesFormat) format, target);
    } else {
      int fileCount =
          NavigationFileParser.getNumberOfFilesToWriteFor(parser.getTheRoute(), format, false);
      File[] targets =
          Files.createTargetFiles(
              target, fileCount, format.getExtension(), format.getMaximumFileNameLength());
      for (File t : targets) {
        if (t.exists()) {
          log.severe("Target '" + t.getAbsolutePath() + "' already exists; stopping.");
          System.exit(13);
        }
      }
      parser.write(parser.getTheRoute(), format, false, false, targets);
    }
  }
  @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);
 }
  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;
  }
  @SuppressWarnings("unchecked")
  private void internalRead(
      InputStream buffer, List<NavigationFormat> formats, ParserContext context)
      throws IOException {
    int routeCountBefore = context.getRoutes().size();
    NavigationFormat firstSuccessfulFormat = null;

    try {
      for (NavigationFormat<BaseRoute> format : formats) {
        notifyReading(format);

        log.fine(format("Trying to read with %s", format));
        try {
          format.read(buffer, context);

          // if no route has been read, take the first that didn't throw an exception
          if (firstSuccessfulFormat == null) firstSuccessfulFormat = format;
        } catch (Exception e) {
          log.severe(format("Error reading with %s: %s, %s", format, e.getClass(), e));
        }

        if (context.getRoutes().size() > routeCountBefore) {
          context.addFormat(format);
          break;
        }

        try {
          buffer.reset();
        } catch (IOException e) {
          log.severe("Cannot reset() stream to mark()");
          break;
        }
      }
    } finally {
      //noinspection ThrowFromFinallyBlock
      buffer.close();
    }

    if (context.getRoutes().size() == 0 && firstSuccessfulFormat != null)
      context.addFormat(firstSuccessfulFormat);
  }
 @SuppressWarnings("unchecked")
 private ParserResult createResult(ParserContext<BaseRoute> context) throws IOException {
   List<BaseRoute> source = context.getRoutes();
   // if (source != null && source.size() > 0) {
   if (source != null && context.getFormats().size() > 0) {
     NavigationFormat format = determineFormat(source, context.getFormats().get(0));
     List<BaseRoute> destination = convertRoute(source, format);
     log.info(
         "Detected '"
             + format.getName()
             + "' with "
             + destination.size()
             + " route(s) and "
             + getPositionCounts(destination)
             + " positions");
     if (destination.size() == 0)
       destination.add(format.createRoute(RouteCharacteristics.Route, null, new ArrayList<>()));
     commentRoutes(destination);
     return new ParserResult(new FormatAndRoutes(format, destination));
   } else return new ParserResult(null);
 }
 private void logFormatNames(List<NavigationFormat> formats) {
   log.info("Supported formats:");
   for (NavigationFormat format : formats)
     log.info(format.getClass().getSimpleName() + " for " + format.getName());
 }