/* This file is part of RouteConverter. RouteConverter is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. RouteConverter is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RouteConverter; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Copyright (C) 2007 Christian Pesch. All Rights Reserved. */ package slash.navigation.base; import slash.navigation.babel.BabelFormat; import slash.navigation.common.NavigationPosition; import java.io.IOException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import static slash.common.io.Transfer.trim; /** * Converts between different {@link NavigationFormat}. * * @author Christian Pesch */ public class NavigationFormatConverter { private static String removeDigits(String string) { StringBuilder buffer = new StringBuilder(string); for (int i = 0; i < buffer.length(); i++) { char c = buffer.charAt(i); if (Character.isDigit(c)) { buffer.deleteCharAt(i); i--; } } return buffer.toString(); } private static String getFormatName(NavigationFormat format) { Class<? extends NavigationFormat> formatClass = format.getClass(); String formatName = formatClass.getSimpleName(); if (trim(formatName) == null && formatClass.getSuperclass() != null) formatName = formatClass.getSuperclass().getSimpleName(); // shortcut to prevent lots of as... methods if (format instanceof BabelFormat) formatName = "Gpx10Format"; if (format instanceof GarbleNavigationFormat) formatName = formatName.substring("Garble".length()); formatName = formatName.replaceAll("LittleEndian", ""); return formatName; } /* package local for tests */static BaseNavigationPosition asFormat(NavigationPosition position, NavigationFormat format) throws IOException { BaseNavigationPosition result; String formatName = getFormatName(format); formatName = formatName.replace("Format", "Position"); formatName = removeDigits(formatName); try { Method method = position.getClass().getMethod("as" + formatName); result = (BaseNavigationPosition) method.invoke(position); } catch (Exception e) { throw new IOException("Cannot call as" + formatName + "() on " + position, e); } return result; } @SuppressWarnings("unchecked") public static BaseRoute<BaseNavigationPosition, BaseNavigationFormat> asFormat(BaseRoute route, NavigationFormat format) throws IOException { BaseRoute<BaseNavigationPosition, BaseNavigationFormat> result; String formatName = getFormatName(format); try { Method method = route.getClass().getMethod("as" + formatName); result = (BaseRoute<BaseNavigationPosition, BaseNavigationFormat>) method.invoke(route); } catch (Exception e) { throw new IOException("Cannot call as" + formatName + "() on " + route, e); } return result; } public static List<BaseNavigationPosition> convertPositions(List<NavigationPosition> positions, NavigationFormat format) throws IOException { List<BaseNavigationPosition> result = new ArrayList<>(positions.size()); for (NavigationPosition position : positions) { result.add(asFormat(position, format)); } return result; } public static List<BaseRoute> convertRoute(List<BaseRoute> routes, NavigationFormat format) throws IOException { List<BaseRoute> result = new ArrayList<>(routes.size()); for (BaseRoute route : routes) { result.add(asFormat(route, format)); } return result; } }