diff --git a/src/de/schildbach/pte/AbstractHafasProvider.java b/src/de/schildbach/pte/AbstractHafasProvider.java index 549ae72b..35ca9120 100644 --- a/src/de/schildbach/pte/AbstractHafasProvider.java +++ b/src/de/schildbach/pte/AbstractHafasProvider.java @@ -547,7 +547,7 @@ public abstract class AbstractHafasProvider implements NetworkProvider throw new IllegalArgumentException("cannot parse duration: " + str); } - private final String location(final Location location) + private static final String location(final Location location) { if (location.type == LocationType.STATION && location.id != 0) return ""; @@ -559,6 +559,34 @@ public abstract class AbstractHafasProvider implements NetworkProvider throw new IllegalArgumentException("cannot handle: " + location.toDebugString()); } + protected static final String locationId(final Location location) + { + final StringBuilder builder = new StringBuilder(); + builder.append("A=").append(locationType(location)); + if (location.lat != 0 || location.lon != 0) + builder.append("@X=" + location.lon + "@Y=" + location.lat); + if (location.name != null) + builder.append("@G=" + location.name); + if (location.type == LocationType.STATION && location.id != 0) + builder.append("@L=").append(location.id); + return builder.toString(); + } + + protected static final int locationType(final Location location) + { + if (location.type == LocationType.STATION) + return 1; + if (location.type == LocationType.POI) + return 4; + if (location.type == LocationType.ADDRESS && (location.lat != 0 || location.lon != 0)) + return 16; + if (location.type == LocationType.ADDRESS && location.name != null) + return 2; + if (location.type == LocationType.ANY) + return 255; + throw new IllegalArgumentException(location.type.toString()); + } + private static final Pattern P_LINE_S = Pattern.compile("SN?\\d+"); private final String _normalizeLine(final String type, final String name, final String longCategory) diff --git a/src/de/schildbach/pte/BahnProvider.java b/src/de/schildbach/pte/BahnProvider.java index 5dc51f62..681259ee 100644 --- a/src/de/schildbach/pte/BahnProvider.java +++ b/src/de/schildbach/pte/BahnProvider.java @@ -24,9 +24,7 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -39,19 +37,23 @@ import de.schildbach.pte.dto.NearbyStationsResult; import de.schildbach.pte.dto.QueryConnectionsResult; import de.schildbach.pte.dto.QueryDeparturesResult; import de.schildbach.pte.dto.Station; -import de.schildbach.pte.util.Color; import de.schildbach.pte.util.ParserUtils; /** * @author Andreas Schildbach */ -public final class BahnProvider implements NetworkProvider +public final class BahnProvider extends AbstractHafasProvider { public static final String NETWORK_ID = "mobile.bahn.de"; private static final String API_BASE = "http://mobile.bahn.de/bin/mobil/"; private static final long PARSER_DAY_ROLLOVER_THRESHOLD_MS = 12 * 60 * 60 * 1000; + public BahnProvider() + { + super(null, null); + } + public boolean hasCapabilities(final Capability... capabilities) { return true; @@ -62,6 +64,7 @@ public final class BahnProvider implements NetworkProvider Pattern.DOTALL); private static final Pattern P_MULTI_NAME = Pattern.compile("", Pattern.DOTALL); + @Override public List autocompleteStations(final CharSequence constraint) throws IOException { final CharSequence page = ParserUtils.scrape(NAME_URL + ParserUtils.urlEncode(constraint.toString())); @@ -87,6 +90,13 @@ public final class BahnProvider implements NetworkProvider private final static Pattern P_NEARBY_STATIONS = Pattern .compile("(.+?)"); + @Override + protected String nearbyStationUri(final String stationId) + { + throw new UnsupportedOperationException(); + } + + @Override public NearbyStationsResult nearbyStations(final String stationId, final int lat, final int lon, final int maxDistance, final int maxStations) throws IOException { @@ -127,15 +137,10 @@ public final class BahnProvider implements NetworkProvider uri.append(API_BASE).append("query.exe/dox"); uri.append("?REQ0HafasOptimize1=0:1"); - uri.append("&REQ0JourneyStopsS0G=").append(ParserUtils.urlEncode(locationValue(from))); - uri.append("&REQ0JourneyStopsS0A=").append(locationTypeValue(from)); + uri.append("&REQ0JourneyStopsS0ID=").append(ParserUtils.urlEncode(locationId(from))); if (via != null) - { - uri.append("&REQ0JourneyStops1.0G=").append(ParserUtils.urlEncode(locationValue(via))); - uri.append("&REQ0JourneyStops1.0A=").append(locationTypeValue(via)); - } - uri.append("&REQ0JourneyStopsZ0G=").append(ParserUtils.urlEncode(locationValue(to))); - uri.append("&REQ0JourneyStopsZ0A=").append(locationTypeValue(to)); + uri.append("&REQ0JourneyStops1.0ID=").append(ParserUtils.urlEncode(locationId(via))); + uri.append("&REQ0JourneyStopsZ0ID=").append(ParserUtils.urlEncode(locationId(to))); uri.append("&REQ0HafasSearchForw=").append(dep ? "1" : "0"); uri.append("&REQ0JourneyDate=").append(ParserUtils.urlEncode(DATE_FORMAT.format(date))); uri.append("&REQ0JourneyTime=").append(ParserUtils.urlEncode(TIME_FORMAT.format(date))); @@ -149,32 +154,13 @@ public final class BahnProvider implements NetworkProvider return uri.toString(); } - private static final int locationTypeValue(final Location location) - { - final LocationType type = location.type; - if (type == LocationType.STATION) - return 1; - if (type == LocationType.ADDRESS) - return 2; - if (type == LocationType.ANY) - return 255; - throw new IllegalArgumentException(type.toString()); - } - - private static final String locationValue(final Location location) - { - if (location.type == LocationType.STATION && location.id != 0) - return Integer.toString(location.id); - else - return location.name; - } - private static final Pattern P_PRE_ADDRESS = Pattern.compile( "", Pattern.DOTALL); private static final Pattern P_ADDRESSES = Pattern.compile("]*>\\s*(.*?)\\s*", Pattern.DOTALL); private static final Pattern P_CHECK_CONNECTIONS_ERROR = Pattern .compile("(zu dicht beieinander|mehrfach vorhanden oder identisch)|(leider konnte zu Ihrer Anfrage keine Verbindung gefunden werden)|(derzeit nur Auskünfte vom)"); + @Override public QueryConnectionsResult queryConnections(final Location from, final Location via, final Location to, final Date date, final boolean dep, final String products, final WalkSpeed walkSpeed) throws IOException { @@ -227,6 +213,7 @@ public final class BahnProvider implements NetworkProvider return queryConnections(uri, page); } + @Override public QueryConnectionsResult queryMoreConnections(final String uri) throws IOException { final CharSequence page = ParserUtils.scrape(uri); @@ -285,7 +272,7 @@ public final class BahnProvider implements NetworkProvider else line = null; final Connection connection = new Connection(AbstractHafasProvider.extractConnectionId(link), link, departureTime, arrivalTime, - line, line != null ? LINES.get(line.charAt(0)) : null, 0, from.name, 0, to.name, null); + line, line != null ? lineColors(line) : null, 0, from.name, 0, to.name, null); connections.add(connection); } else @@ -325,6 +312,7 @@ public final class BahnProvider implements NetworkProvider private static final Pattern P_CONNECTION_DETAILS_MESSAGES = Pattern .compile("Dauer: \\d+:\\d+|(Anschlusszug nicht mehr rechtzeitig)|(Anschlusszug jedoch erreicht werden)|(nur teilweise dargestellt)|(Längerer Aufenthalt)|(äquivalentem Bahnhof)|(Bahnhof wird mehrfach durchfahren)"); + @Override public GetConnectionDetailsResult getConnectionDetails(final String uri) throws IOException { final CharSequence page = ParserUtils.scrape(uri); @@ -377,7 +365,7 @@ public final class BahnProvider implements NetworkProvider final Date departureDateTime = ParserUtils.joinDateTime(departureDate, departureTime); final Date arrivalDateTime = ParserUtils.joinDateTime(arrivalDate, arrivalTime); - lastTrip = new Connection.Trip(line, line != null ? LINES.get(line.charAt(0)) : null, 0, null, departureDateTime, + lastTrip = new Connection.Trip(line, line != null ? lineColors(line) : null, 0, null, departureDateTime, departurePosition, 0, departure, arrivalDateTime, arrivalPosition, 0, arrival); parts.add(lastTrip); @@ -506,8 +494,8 @@ public final class BahnProvider implements NetworkProvider final String message = ParserUtils.resolveEntities(mDepFine.group(9)); - departures.add(new Departure(plannedTime, predictedTime, line, line != null ? LINES.get(line.charAt(0)) : null, null, position, - 0, destination, message)); + departures.add(new Departure(plannedTime, predictedTime, line, line != null ? lineColors(line) : null, null, position, 0, + destination, message)); } } else @@ -519,6 +507,12 @@ public final class BahnProvider implements NetworkProvider return new QueryDeparturesResult(new Location(LocationType.STATION, Integer.parseInt(stationId), 0, 0, null), departures); } + @Override + protected char normalizeType(String type) + { + throw new UnsupportedOperationException(); + } + private static final Pattern P_NORMALIZE_LINE_NUMBER = Pattern.compile("\\d{2,5}"); private static final Pattern P_NORMALIZE_LINE = Pattern.compile("([A-Za-zÄÖÜäöüßáàâéèêíìîóòôúùû]+)[\\s-]*(.*)"); private static final Pattern P_NORMALIZE_LINE_RUSSIA = Pattern.compile("(?:D\\s*)?(\\d{1,3}[A-Z]{2})"); @@ -849,23 +843,4 @@ public final class BahnProvider implements NetworkProvider throw new IllegalStateException("cannot normalize line " + line); } - - private static final Map LINES = new HashMap(); - - static - { - LINES.put('I', new int[] { Color.WHITE, Color.RED, Color.RED }); - LINES.put('R', new int[] { Color.GRAY, Color.WHITE }); - LINES.put('S', new int[] { Color.parseColor("#006e34"), Color.WHITE }); - LINES.put('U', new int[] { Color.parseColor("#003090"), Color.WHITE }); - LINES.put('T', new int[] { Color.parseColor("#cc0000"), Color.WHITE }); - LINES.put('B', new int[] { Color.parseColor("#993399"), Color.WHITE }); - LINES.put('F', new int[] { Color.BLUE, Color.WHITE }); - LINES.put('?', new int[] { Color.DKGRAY, Color.WHITE }); - } - - public int[] lineColors(final String line) - { - return LINES.get(line.charAt(0)); - } } diff --git a/src/de/schildbach/pte/OebbProvider.java b/src/de/schildbach/pte/OebbProvider.java index 0f4cd9ae..835ef7bb 100644 --- a/src/de/schildbach/pte/OebbProvider.java +++ b/src/de/schildbach/pte/OebbProvider.java @@ -159,18 +159,10 @@ public class OebbProvider extends AbstractHafasProvider uri.append("&start.x=0"); uri.append("&start.y=0"); uri.append("&start=Suchen"); - uri.append("&REQ0JourneyStopsS0A=").append(locationTypeValue(from)); - uri.append("&REQ0JourneyStopsS0G=").append(ParserUtils.urlEncode(locationValue(from))); - uri.append("&REQ0JourneyStopsS0ID="); // "tupel"? + uri.append("&REQ0JourneyStopsS0ID=").append(ParserUtils.urlEncode(locationId(from))); if (via != null) - { - uri.append("&REQ0JourneyStops1.0A=").append(locationTypeValue(via)); - uri.append("&REQ0JourneyStops1.0G=").append(ParserUtils.urlEncode(locationValue(via))); - uri.append("&REQ0JourneyStops1.0ID="); - } - uri.append("&REQ0JourneyStopsZ0A=").append(locationTypeValue(to)); - uri.append("&REQ0JourneyStopsZ0G=").append(ParserUtils.urlEncode(locationValue(to))); - uri.append("&REQ0JourneyStopsZ0ID="); + uri.append("&REQ0JourneyStops1.0ID=").append(ParserUtils.urlEncode(locationId(via))); + uri.append("&REQ0JourneyStopsZ0ID=").append(ParserUtils.urlEncode(locationId(to))); uri.append("&REQ0JourneyDate=").append(ParserUtils.urlEncode(DATE_FORMAT.format(date))); uri.append("&wDayExt0=").append(ParserUtils.urlEncode("Mo|Di|Mi|Do|Fr|Sa|So")); uri.append("&REQ0JourneyTime=").append(ParserUtils.urlEncode(TIME_FORMAT.format(date))); @@ -202,28 +194,6 @@ public class OebbProvider extends AbstractHafasProvider return uri.toString(); } - private static int locationTypeValue(final Location location) - { - final LocationType type = location.type; - if (type == LocationType.STATION) - return 1; - if (type == LocationType.ADDRESS) - return 2; - if (type == LocationType.POI) - return 4; - if (type == LocationType.ANY) - return 255; - throw new IllegalArgumentException(type.toString()); - } - - private static String locationValue(final Location location) - { - if ((location.type == LocationType.STATION || location.type == LocationType.POI) && location.id != 0) - return Integer.toString(location.id); - else - return location.name; - } - private static final String QUERY_CONNECTIONS_FORM_URL = API_BASE + "query.exe/dn?"; private static final Pattern P_QUERY_CONNECTIONS_FORM_ACTION = Pattern .compile("