use common line parser for efa based apis

git-svn-id: https://public-transport-enabler.googlecode.com/svn/trunk@213 0924bc21-9374-b0fa-ee44-9ff1593b38f0
This commit is contained in:
andreas.schildbach 2010-09-30 17:08:17 +00:00
parent e8d2d60919
commit 8419822b30
4 changed files with 242 additions and 331 deletions

View file

@ -123,7 +123,198 @@ public abstract class AbstractEfaProvider implements NetworkProvider
return (double) value / 1000000; return (double) value / 1000000;
} }
protected abstract String parseLine(String number, String symbol, String mot); private static final Pattern P_LINE_RE = Pattern.compile("RE\\d+");
private static final Pattern P_LINE_RB = Pattern.compile("RB\\d+");
private static final Pattern P_LINE_U = Pattern.compile("U\\d+");
protected String parseLine(final String number, final String symbol, final String mot)
{
if (!number.equals(symbol))
throw new IllegalStateException("number " + number + ", symbol " + symbol);
final int t = Integer.parseInt(mot);
if (t == 0)
{
final String[] parts = number.split(" ", 3);
final String type = parts[0];
final String num = parts.length >= 2 ? parts[1] : null;
final String str = type + (num != null ? num : "");
if (type.equals("EC")) // Eurocity
return 'I' + str;
if (type.equals("EN")) // Euronight
return 'I' + str;
if (type.equals("IC")) // Intercity
return 'I' + str;
if (type.equals("ICE")) // Intercity Express
return 'I' + str;
if (type.equals("CNL")) // City Night Line
return 'I' + str;
if (type.equals("THA")) // Thalys
return 'I' + str;
if (type.equals("TGV")) // TGV
return 'I' + str;
if (type.equals("RJ")) // railjet
return 'I' + str;
if (type.equals("IR")) // Interregio
return 'R' + str;
if (type.equals("IRE")) // Interregio-Express
return 'R' + str;
if (type.equals("RE")) // Regional-Express
return 'R' + str;
if (P_LINE_RE.matcher(type).matches())
return 'R' + str;
if (type.equals("RB")) // Regionalbahn
return 'R' + str;
if (P_LINE_RB.matcher(type).matches())
return 'R' + str;
if (type.equals("R")) // Regionalzug
return 'R' + str;
if (type.equals("D")) // Schnellzug
return 'R' + str;
if (type.equals("WFB")) // Westfalenbahn
return 'R' + str;
if (type.equals("NWB")) // NordWestBahn
return 'R' + str;
if (type.equals("ME")) // Metronom
return 'R' + str;
if (type.equals("ERB")) // eurobahn
return 'R' + str;
if (type.equals("CAN")) // cantus
return 'R' + str;
if (type.equals("HEX")) // Veolia Verkehr Sachsen-Anhalt
return 'R' + str;
if (type.equals("EB")) // Erfurter Bahn
return 'R' + str;
if (type.equals("MRB")) // Mittelrheinbahn
return 'R' + str;
if (type.equals("ABR")) // ABELLIO Rail NRW
return 'R' + str;
if (type.equals("NEB")) // Niederbarnimer Eisenbahn
return 'R' + str;
if (type.equals("OE")) // Ostdeutsche Eisenbahn
return 'R' + str;
if (type.equals("MR")) // Märkische Regiobahn
return 'R' + str;
if (type.equals("OLA")) // Ostseeland Verkehr
return 'R' + str;
if (type.equals("UBB")) // Usedomer Bäderbahn
return 'R' + str;
if (type.equals("EVB")) // Elbe-Weser
return 'R' + str;
if (type.equals("PEG")) // Prignitzer Eisenbahngesellschaft
return 'R' + str;
if (type.equals("RTB")) // Rurtalbahn
return 'R' + str;
if (type.equals("STB")) // Süd-Thüringen-Bahn
return 'R' + str;
if (type.equals("HTB")) // Hellertalbahn
return 'R' + str;
if (type.equals("VBG")) // Vogtlandbahn
return 'R' + str;
if (type.equals("VX")) // Vogtland Express
return 'R' + str;
if (type.equals("CB")) // City-Bahn Chemnitz
return 'R' + str;
if (type.equals("VEC")) // VECTUS Verkehrsgesellschaft
return 'R' + str;
if (type.equals("HzL")) // Hohenzollerische Landesbahn
return 'R' + str;
if (type.equals("OSB")) // Ortenau-S-Bahn
return 'R' + str;
if (type.equals("SBB")) // SBB
return 'R' + str;
if (type.equals("MBB")) // Mecklenburgische Bäderbahn Molli
return 'R' + str;
if (type.equals("OS")) // Regionalbahn
return 'R' + str;
if (type.equals("SP"))
return 'R' + str;
if (type.equals("Dab")) // Daadetalbahn
return 'R' + str;
if (type.equals("FEG")) // Freiberger Eisenbahngesellschaft
return 'R' + str;
if (type.equals("ARR")) // ARRIVA
return 'R' + str;
if (type.equals("HSB")) // Harzer Schmalspurbahn
return 'R' + str;
if (type.equals("SBE")) // Sächsisch-Böhmische Eisenbahngesellschaft
return 'R' + str;
if (type.equals("ALX")) // Arriva-Länderbahn-Express
return 'R' + str;
if (type.equals("MEr")) // metronom regional
return 'R' + str;
if (type.equals("AKN")) // AKN Eisenbahn
return 'R' + str;
if (type.equals("ZUG")) // Regionalbahn
return 'R' + str;
if (type.equals("SOE")) // Sächsisch-Oberlausitzer Eisenbahngesellschaft
return 'R' + str;
if (type.equals("VIA")) // VIAS
return 'R' + str;
if (type.equals("BRB")) // Bayerische Regiobahn
return 'R' + str;
if (type.equals("BLB")) // Berchtesgadener Land Bahn
return 'R' + str;
if (type.equals("HLB")) // Hessische Landesbahn
return 'R' + str;
if (type.equals("NOB")) // NordOstseeBahn
return 'R' + str;
if (type.equals("WEG")) // Wieslauftalbahn
return 'R' + str;
if (type.equals("NBE")) // Nordbahn Eisenbahngesellschaft
return 'R' + str;
if (type.equals("VEN")) // Rhenus Veniro
return 'R' + str;
if (type.equals("DPN")) // Nahreisezug
return 'R' + str;
if (type.equals("SHB")) // Schleswig-Holstein-Bahn
return 'R' + str;
if (type.equals("RBG")) // Regental Bahnbetriebs GmbH
return 'R' + str;
if (type.equals("BOB")) // Bayerische Oberlandbahn
return 'R' + str;
if (type.equals("SWE")) // Südwestdeutsche Verkehrs AG
return 'R' + str;
if (type.equals("VE")) // Vetter
return 'R' + str;
if (type.equals("SDG")) // Sächsische Dampfeisenbahngesellschaft
return 'R' + str;
if (type.equals("PRE")) // Pressnitztalbahn
return 'R' + str;
if (type.equals("BSB")) // Breisgau-S-Bahn
return 'S' + str;
if (P_LINE_U.matcher(type).matches())
return 'U' + str;
if (type.equals("RT")) // RegioTram
return 'T' + str;
if (type.equals("STR")) // Nordhausen
return 'T' + str;
throw new IllegalArgumentException("cannot normalize: " + number);
}
if (t == 1)
return 'S' + number;
if (t == 2)
return 'U' + number;
if (t == 3 || t == 4)
return 'T' + number;
if (t == 5 || t == 6 || t == 7 || t == 10)
return 'B' + number;
if (t == 8)
return 'C' + number;
if (t == 9)
return 'F' + number;
if (t == 11)
return '?' + number;
throw new IllegalStateException("cannot normalize mot '" + mot + "' number '" + number + "'");
}
public QueryDeparturesResult queryDepartures(final String uri) throws IOException public QueryDeparturesResult queryDepartures(final String uri) throws IOException
{ {
@ -142,7 +333,7 @@ public abstract class AbstractEfaProvider implements NetworkProvider
XmlPullUtil.jumpToStartTag(pp, null, "odvNameElem"); XmlPullUtil.jumpToStartTag(pp, null, "odvNameElem");
final int locationId = Integer.parseInt(pp.getAttributeValue(null, "stopID")); final int locationId = Integer.parseInt(pp.getAttributeValue(null, "stopID"));
final String location = pp.nextText(); final String location = normalizeLocationName(pp.nextText());
final Calendar departureTime = new GregorianCalendar(); final Calendar departureTime = new GregorianCalendar();
final List<Departure> departures = new ArrayList<Departure>(8); final List<Departure> departures = new ArrayList<Departure>(8);
@ -178,7 +369,7 @@ public abstract class AbstractEfaProvider implements NetworkProvider
final String line = parseLine(pp.getAttributeValue(null, "number"), pp.getAttributeValue(null, "symbol"), pp final String line = parseLine(pp.getAttributeValue(null, "number"), pp.getAttributeValue(null, "symbol"), pp
.getAttributeValue(null, "motType")); .getAttributeValue(null, "motType"));
final boolean isRealtime = pp.getAttributeValue(null, "realtime").equals("1"); final boolean isRealtime = pp.getAttributeValue(null, "realtime").equals("1");
final String destination = pp.getAttributeValue(null, "direction"); final String destination = normalizeLocationName(pp.getAttributeValue(null, "direction"));
final int destinationId = Integer.parseInt(pp.getAttributeValue(null, "destID")); final int destinationId = Integer.parseInt(pp.getAttributeValue(null, "destID"));
XmlPullUtil.skipRestOfTree(pp); XmlPullUtil.skipRestOfTree(pp);
@ -220,4 +411,11 @@ public abstract class AbstractEfaProvider implements NetworkProvider
calendar.set(Calendar.HOUR, Integer.parseInt(pp.getAttributeValue(null, "hour"))); calendar.set(Calendar.HOUR, Integer.parseInt(pp.getAttributeValue(null, "hour")));
calendar.set(Calendar.MINUTE, Integer.parseInt(pp.getAttributeValue(null, "minute"))); calendar.set(Calendar.MINUTE, Integer.parseInt(pp.getAttributeValue(null, "minute")));
} }
private static final Pattern P_STATION_NAME_WHITESPACE = Pattern.compile("\\s+");
private static String normalizeLocationName(final String name)
{
return P_STATION_NAME_WHITESPACE.matcher(name).replaceAll(" ");
}
} }

View file

@ -21,7 +21,6 @@ import java.io.IOException;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.regex.Pattern;
/** /**
* @author Andreas Schildbach * @author Andreas Schildbach
@ -82,194 +81,6 @@ public class GvhProvider extends AbstractEfaProvider
return uri.toString(); return uri.toString();
} }
private static final Pattern P_LINE_RE = Pattern.compile("RE\\d+");
private static final Pattern P_LINE_RB = Pattern.compile("RB\\d+");
private static final Pattern P_LINE_U = Pattern.compile("U\\d+");
@Override
protected String parseLine(final String number, final String symbol, final String mot)
{
if (!number.equals(symbol))
throw new IllegalStateException("number " + number + ", symbol " + symbol);
final int t = Integer.parseInt(mot);
if (t == 0)
{
final String[] parts = number.split(" ", 3);
final String type = parts[0];
final String num = parts.length >= 2 ? parts[1] : null;
final String str = type + (num != null ? num : "");
if (type.equals("EC")) // Eurocity
return 'I' + str;
if (type.equals("EN")) // Euronight
return 'I' + str;
if (type.equals("IC")) // Intercity
return 'I' + str;
if (type.equals("ICE")) // Intercity Express
return 'I' + str;
if (type.equals("CNL")) // City Night Line
return 'I' + str;
if (type.equals("THA")) // Thalys
return 'I' + str;
if (type.equals("TGV")) // TGV
return 'I' + str;
if (type.equals("RJ")) // railjet
return 'I' + str;
if (type.equals("IR")) // Interregio
return 'R' + str;
if (type.equals("IRE")) // Interregio-Express
return 'R' + str;
if (type.equals("RE")) // Regional-Express
return 'R' + str;
if (P_LINE_RE.matcher(type).matches())
return 'R' + str;
if (type.equals("RB")) // Regionalbahn
return 'R' + str;
if (P_LINE_RB.matcher(type).matches())
return 'R' + str;
if (type.equals("R")) // Regionalzug
return 'R' + str;
if (type.equals("D")) // Schnellzug
return 'R' + str;
if (type.equals("WFB")) // Westfalenbahn
return 'R' + str;
if (type.equals("NWB")) // NordWestBahn
return 'R' + str;
if (type.equals("ME")) // Metronom
return 'R' + str;
if (type.equals("ERB")) // eurobahn
return 'R' + str;
if (type.equals("CAN")) // cantus
return 'R' + str;
if (type.equals("HEX")) // Veolia Verkehr Sachsen-Anhalt
return 'R' + str;
if (type.equals("EB")) // Erfurter Bahn
return 'R' + str;
if (type.equals("MRB")) // Mittelrheinbahn
return 'R' + str;
if (type.equals("ABR")) // ABELLIO Rail NRW
return 'R' + str;
if (type.equals("NEB")) // Niederbarnimer Eisenbahn
return 'R' + str;
if (type.equals("OE")) // Ostdeutsche Eisenbahn
return 'R' + str;
if (type.equals("MR")) // Märkische Regiobahn
return 'R' + str;
if (type.equals("OLA")) // Ostseeland Verkehr
return 'R' + str;
if (type.equals("UBB")) // Usedomer Bäderbahn
return 'R' + str;
if (type.equals("EVB")) // Elbe-Weser
return 'R' + str;
if (type.equals("PEG")) // Prignitzer Eisenbahngesellschaft
return 'R' + str;
if (type.equals("RTB")) // Rurtalbahn
return 'R' + str;
if (type.equals("STB")) // Süd-Thüringen-Bahn
return 'R' + str;
if (type.equals("HTB")) // Hellertalbahn
return 'R' + str;
if (type.equals("VBG")) // Vogtlandbahn
return 'R' + str;
if (type.equals("VX")) // Vogtland Express
return 'R' + str;
if (type.equals("CB")) // City-Bahn Chemnitz
return 'R' + str;
if (type.equals("VEC")) // VECTUS Verkehrsgesellschaft
return 'R' + str;
if (type.equals("HzL")) // Hohenzollerische Landesbahn
return 'R' + str;
if (type.equals("OSB")) // Ortenau-S-Bahn
return 'R' + str;
if (type.equals("SBB")) // SBB
return 'R' + str;
if (type.equals("MBB")) // Mecklenburgische Bäderbahn Molli
return 'R' + str;
if (type.equals("OS")) // Regionalbahn
return 'R' + str;
if (type.equals("SP"))
return 'R' + str;
if (type.equals("Dab")) // Daadetalbahn
return 'R' + str;
if (type.equals("FEG")) // Freiberger Eisenbahngesellschaft
return 'R' + str;
if (type.equals("ARR")) // ARRIVA
return 'R' + str;
if (type.equals("HSB")) // Harzer Schmalspurbahn
return 'R' + str;
if (type.equals("SBE")) // Sächsisch-Böhmische Eisenbahngesellschaft
return 'R' + str;
if (type.equals("ALX")) // Arriva-Länderbahn-Express
return 'R' + str;
if (type.equals("MEr")) // metronom regional
return 'R' + str;
if (type.equals("AKN")) // AKN Eisenbahn
return 'R' + str;
if (type.equals("ZUG")) // Regionalbahn
return 'R' + str;
if (type.equals("SOE")) // Sächsisch-Oberlausitzer Eisenbahngesellschaft
return 'R' + str;
if (type.equals("VIA")) // VIAS
return 'R' + str;
if (type.equals("BRB")) // Bayerische Regiobahn
return 'R' + str;
if (type.equals("BLB")) // Berchtesgadener Land Bahn
return 'R' + str;
if (type.equals("HLB")) // Hessische Landesbahn
return 'R' + str;
if (type.equals("NOB")) // NordOstseeBahn
return 'R' + str;
if (type.equals("WEG")) // Wieslauftalbahn
return 'R' + str;
if (type.equals("NBE")) // Nordbahn Eisenbahngesellschaft
return 'R' + str;
if (type.equals("VEN")) // Rhenus Veniro
return 'R' + str;
if (type.equals("DPN")) // Nahreisezug
return 'R' + str;
if (type.equals("SHB")) // Schleswig-Holstein-Bahn
return 'R' + str;
if (type.equals("RBG")) // Regental Bahnbetriebs GmbH
return 'R' + str;
if (type.equals("BOB")) // Bayerische Oberlandbahn
return 'R' + str;
if (type.equals("SWE")) // Südwestdeutsche Verkehrs AG
return 'R' + str;
if (type.equals("VE")) // Vetter
return 'R' + str;
if (type.equals("SDG")) // Sächsische Dampfeisenbahngesellschaft
return 'R' + str;
if (type.equals("BSB")) // Breisgau-S-Bahn
return 'S' + str;
if (P_LINE_U.matcher(type).matches())
return 'U' + str;
if (type.equals("RT")) // RegioTram
return 'T' + str;
if (type.equals("STR")) // Nordhausen
return 'T' + str;
throw new IllegalArgumentException("cannot normalize: " + number);
}
if (t == 1)
return 'S' + number;
if (t == 3 || t == 4)
return 'T' + number;
if (t == 5 || t == 6 || t == 7 || t == 10)
return 'B' + number;
if (t == 9)
return 'F' + number;
if (t == 11)
return '?' + number;
throw new IllegalStateException("cannot normalize mot '" + mot + "' number '" + number + "'");
}
public QueryConnectionsResult queryConnections(LocationType fromType, String from, LocationType viaType, String via, LocationType toType, public QueryConnectionsResult queryConnections(LocationType fromType, String from, LocationType viaType, String via, LocationType toType,
String to, Date date, boolean dep, WalkSpeed walkSpeed) throws IOException String to, Date date, boolean dep, WalkSpeed walkSpeed) throws IOException
{ {

View file

@ -103,24 +103,6 @@ public class LinzProvider extends AbstractEfaProvider
return uri.toString(); return uri.toString();
} }
@Override
protected String parseLine(final String number, final String symbol, final String mot)
{
if (!number.equals(symbol))
throw new IllegalStateException("number " + number + ", symbol " + symbol);
int t = Integer.parseInt(mot);
if (t == 4)
return 'T' + number;
if (t == 5 || t == 6 || t == 7 || t == 10)
return 'B' + number;
if (t == 8)
return 'C' + number;
throw new IllegalStateException("cannot normalize mot '" + mot + "' number '" + number + "'");
}
private static final Map<Character, int[]> LINES = new HashMap<Character, int[]>(); private static final Map<Character, int[]> LINES = new HashMap<Character, int[]>();
static static

View file

@ -30,14 +30,13 @@ import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import de.schildbach.pte.QueryDeparturesResult.Status;
/** /**
* @author Andreas Schildbach * @author Andreas Schildbach
*/ */
public class MvvProvider implements NetworkProvider public class MvvProvider extends AbstractEfaProvider
{ {
public static final String NETWORK_ID = "efa.mvv-muenchen.de"; public static final String NETWORK_ID = "efa.mvv-muenchen.de";
private static final String API_BASE = "http://efa.mvv-muenchen.de/mobile/";
private static final long PARSER_DAY_ROLLOVER_THRESHOLD_MS = 12 * 60 * 60 * 1000; private static final long PARSER_DAY_ROLLOVER_THRESHOLD_MS = 12 * 60 * 60 * 1000;
private static final String ENCODING = "ISO-8859-1"; private static final String ENCODING = "ISO-8859-1";
@ -58,9 +57,16 @@ public class MvvProvider implements NetworkProvider
private static final Pattern P_AUTOCOMPLETE_COARSE = Pattern.compile("<p>(.*?)</p>"); private static final Pattern P_AUTOCOMPLETE_COARSE = Pattern.compile("<p>(.*?)</p>");
private static final Pattern P_AUTOCOMPLETE_FINE = Pattern.compile(".*?<n>(.*?)</n>.*?<ty>(.*?)</ty>.*?<id>(.*?)</id>.*?<pc>(.*?)</pc>.*?"); private static final Pattern P_AUTOCOMPLETE_FINE = Pattern.compile(".*?<n>(.*?)</n>.*?<ty>(.*?)</ty>.*?<id>(.*?)</id>.*?<pc>(.*?)</pc>.*?");
@Override
protected String autocompleteUri(final CharSequence constraint)
{
return String.format(AUTOCOMPLETE_URI, ParserUtils.urlEncode(constraint.toString(), ENCODING), AUTOCOMPLETE_TYPE);
}
@Override
public List<Autocomplete> autocompleteStations(final CharSequence constraint) throws IOException public List<Autocomplete> autocompleteStations(final CharSequence constraint) throws IOException
{ {
final String uri = String.format(AUTOCOMPLETE_URI, ParserUtils.urlEncode(constraint.toString(), ENCODING), AUTOCOMPLETE_TYPE); final String uri = autocompleteUri(constraint);
final CharSequence page = ParserUtils.scrape(uri); final CharSequence page = ParserUtils.scrape(uri);
final List<Autocomplete> results = new ArrayList<Autocomplete>(); final List<Autocomplete> results = new ArrayList<Autocomplete>();
@ -97,19 +103,34 @@ public class MvvProvider implements NetworkProvider
private static final String NEARBY_LATLON_URI = "http://efa.mvv-muenchen.de/ultralite/XML_DM_REQUEST" private static final String NEARBY_LATLON_URI = "http://efa.mvv-muenchen.de/ultralite/XML_DM_REQUEST"
+ "?mode=direct&coordOutputFormat=WGS84&mergeDep=1&useAllStops=1&name_dm=%2.6f:%2.6f:WGS84&type_dm=coord&itOptionsActive=1&ptOptionsActive=1&useProxFootSearch=1&excludedMeans=checkbox"; + "?mode=direct&coordOutputFormat=WGS84&mergeDep=1&useAllStops=1&name_dm=%2.6f:%2.6f:WGS84&type_dm=coord&itOptionsActive=1&ptOptionsActive=1&useProxFootSearch=1&excludedMeans=checkbox";
@Override
protected String nearbyLatLonUri(final double lat, final double lon)
{
return String.format(NEARBY_LATLON_URI, lon, lat);
}
private static final String NEARBY_STATION_URI = "http://efa.mvv-muenchen.de/ultralite/XML_DM_REQUEST" private static final String NEARBY_STATION_URI = "http://efa.mvv-muenchen.de/ultralite/XML_DM_REQUEST"
+ "?mode=direct&coordOutputFormat=WGS84&mergeDep=1&useAllStops=1&name_dm=%s&type_dm=stop&itOptionsActive=1&ptOptionsActive=1&useProxFootSearch=1&excludedMeans=checkbox"; + "?mode=direct&coordOutputFormat=WGS84&mergeDep=1&useAllStops=1&name_dm=%s&type_dm=stop&itOptionsActive=1&ptOptionsActive=1&useProxFootSearch=1&excludedMeans=checkbox";
@Override
protected String nearbyStationUri(final String stationId)
{
return String.format(NEARBY_STATION_URI, stationId);
}
private static final Pattern P_NEARBY_COARSE = Pattern.compile("<dp>(.*?)</dp>"); private static final Pattern P_NEARBY_COARSE = Pattern.compile("<dp>(.*?)</dp>");
private static final Pattern P_NEARBY_FINE = Pattern.compile(".*?<n>(.*?)</n>.*?<r>.*?<id>(.*?)</id>.*?</r>.*?(?:<c>(\\d+),(\\d+)</c>.*?)?"); private static final Pattern P_NEARBY_FINE = Pattern.compile(".*?<n>(.*?)</n>.*?<r>.*?<id>(.*?)</id>.*?</r>.*?(?:<c>(\\d+),(\\d+)</c>.*?)?");
@Override
public List<Station> nearbyStations(final String stationId, final double lat, final double lon, final int maxDistance, final int maxStations) public List<Station> nearbyStations(final String stationId, final double lat, final double lon, final int maxDistance, final int maxStations)
throws IOException throws IOException
{ {
String uri; String uri;
if (lat != 0 || lon != 0) if (lat != 0 || lon != 0)
uri = String.format(NEARBY_LATLON_URI, lon, lat); uri = nearbyLatLonUri(lat, lon);
else if (stationId != null) else if (stationId != null)
uri = String.format(NEARBY_STATION_URI, stationId); uri = nearbyStationUri(stationId);
else else
throw new IllegalArgumentException("at least one of stationId or lat/lon must be given"); throw new IllegalArgumentException("at least one of stationId or lat/lon must be given");
@ -151,21 +172,6 @@ public class MvvProvider implements NetworkProvider
public StationLocationResult stationLocation(final String stationId) throws IOException public StationLocationResult stationLocation(final String stationId) throws IOException
{ {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
// private Pattern P_GEO =
// Pattern.compile(".*?var latact = \"(\\d+\\.\\d+)\";.*?var lonact = \"(\\d+\\.\\d+)\";.*?", Pattern.DOTALL);
// final String urlGeo =
// "http://www.mvv-muenchen.de/de/home/fahrgastinformation/mvv-netz/sis/sdb/googlemaps/index.html?id="
// + id;
// final CharSequence pageGeo = ParserUtils.scrape(urlGeo);
// final Matcher mGeo = P_GEO.matcher(pageGeo);
// if (mGeo.matches())
// {
// mvvLat = Double.parseDouble(mGeo.group(1));
// mvvLon = Double.parseDouble(mGeo.group(2));
// }
} }
private static final Map<WalkSpeed, String> WALKSPEED_MAP = new HashMap<WalkSpeed, String>(); private static final Map<WalkSpeed, String> WALKSPEED_MAP = new HashMap<WalkSpeed, String>();
@ -186,7 +192,7 @@ public class MvvProvider implements NetworkProvider
final DateFormat HOUR_FORMAT = new SimpleDateFormat("H"); final DateFormat HOUR_FORMAT = new SimpleDateFormat("H");
final DateFormat MINUTE_FORMAT = new SimpleDateFormat("m"); final DateFormat MINUTE_FORMAT = new SimpleDateFormat("m");
final StringBuilder uri = new StringBuilder("http://efa.mvv-muenchen.de/mobile/XSLT_TRIP_REQUEST2"); final StringBuilder uri = new StringBuilder(API_BASE + "XSLT_TRIP_REQUEST2");
uri.append("?language=de"); uri.append("?language=de");
uri.append("&sessionID=0"); uri.append("&sessionID=0");
uri.append("&requestID=0"); uri.append("&requestID=0");
@ -411,10 +417,8 @@ public class MvvProvider implements NetworkProvider
final String to = ParserUtils.resolveEntities(mHead.group(2)); final String to = ParserUtils.resolveEntities(mHead.group(2));
// final String via = ParserUtils.resolveEntities(mHead.group(3)); // final String via = ParserUtils.resolveEntities(mHead.group(3));
final Date currentDate = parseDate(mHead.group(4), mHead.group(5), mHead.group(6)); final Date currentDate = parseDate(mHead.group(4), mHead.group(5), mHead.group(6));
final String linkEarlier = mHead.group(7) != null ? "http://efa.mvv-muenchen.de/mobile/" + ParserUtils.resolveEntities(mHead.group(7)) final String linkEarlier = mHead.group(7) != null ? API_BASE + ParserUtils.resolveEntities(mHead.group(7)) : null;
: null; final String linkLater = mHead.group(8) != null ? API_BASE + ParserUtils.resolveEntities(mHead.group(8)) : null;
final String linkLater = mHead.group(8) != null ? "http://efa.mvv-muenchen.de/mobile/" + ParserUtils.resolveEntities(mHead.group(8))
: null;
final List<Connection> connections = new ArrayList<Connection>(); final List<Connection> connections = new ArrayList<Connection>();
final Matcher mConCoarse = P_CONNECTIONS_COARSE.matcher(page); final Matcher mConCoarse = P_CONNECTIONS_COARSE.matcher(page);
@ -423,7 +427,7 @@ public class MvvProvider implements NetworkProvider
final Matcher mConFine = P_CONNECTIONS_FINE.matcher(mConCoarse.group(1)); final Matcher mConFine = P_CONNECTIONS_FINE.matcher(mConCoarse.group(1));
if (mConFine.matches()) if (mConFine.matches())
{ {
final String link = "http://efa.mvv-muenchen.de/mobile/" + ParserUtils.resolveEntities(mConFine.group(3)); final String link = API_BASE + ParserUtils.resolveEntities(mConFine.group(3));
if (mConFine.group(6) == null) if (mConFine.group(6) == null)
{ {
@ -613,100 +617,16 @@ public class MvvProvider implements NetworkProvider
return time; return time;
} }
private static final String DEPARTURE_URL = "http://efa.mvv-muenchen.de/mobile/XSLT_DM_REQUEST?typeInfo_dm=stopID&mode=direct&nameInfo_dm=";
public String departuresQueryUri(final String stationId, final int maxDepartures) public String departuresQueryUri(final String stationId, final int maxDepartures)
{ {
return DEPARTURE_URL + stationId; final StringBuilder uri = new StringBuilder();
} uri.append(API_BASE).append("XSLT_DM_REQUEST");
uri.append("?outputFormat=XML");
private static final Pattern P_DEPARTURES_HEAD_COARSE = Pattern.compile(".*?<body>(.*?Linie/Richtung.*?)</body>.*?", Pattern.DOTALL); uri.append("&coordOutputFormat=WGS84");
private static final Pattern P_DEPARTURES_HEAD_FINE = Pattern.compile(".*?" // uri.append("&type_dm=stop");
+ "Von:[\\xa0\\s]*</b>(.*?)<br />.*?" // location uri.append("&name_dm=").append(stationId);
+ "Datum:[\\xa0\\s]*</b>\\w{2}\\.,\\s(\\d+)\\.\\s(\\w{3,4})\\.[\\xa0\\s]+(\\d{4})<br />.*?" // date uri.append("&mode=direct");
, Pattern.DOTALL); return uri.toString();
private static final Pattern P_DEPARTURES_COARSE = Pattern.compile("<tr valign=\"top\" bgcolor=\"#\\w{6}\">(.+?)</tr>", Pattern.DOTALL);
private static final Pattern P_DEPARTURES_FINE = Pattern.compile(".*?" //
+ "(?:[\\xa0\\s]*<font color=\"red\">[\\xa0\\s]*(\\d+)\\.(\\d+)\\.[\\xa0\\s]*</font>)?" // date
+ "(\\d{1,2}):(\\d{2})</td>.*?" // time
+ "(?:<img src=\"images/means.*?\" alt=\"(.*?)\" />.*?)?" // product
+ "<td width=\"100\">\\s*([^<]*?)[\\xa0\\s]*(?:<a .*?</a>.*?)?" // line
+ "<br />\\s*(.*?)\\s*<br />.*?" // destination
, Pattern.DOTALL);
private static final Pattern P_DEPARTURES_URI_STATION_ID = Pattern.compile("nameInfo_dm=(\\d+)");
public QueryDeparturesResult queryDepartures(final String uri) throws IOException
{
final CharSequence page = ParserUtils.scrape(uri);
final Matcher mStationId = P_DEPARTURES_URI_STATION_ID.matcher(uri);
if (!mStationId.find())
throw new IllegalStateException(uri);
final int stationId = Integer.parseInt(mStationId.group(1));
final Matcher mHeadCoarse = P_DEPARTURES_HEAD_COARSE.matcher(page);
if (mHeadCoarse.matches())
{
final Matcher mHeadFine = P_DEPARTURES_HEAD_FINE.matcher(mHeadCoarse.group(1));
if (mHeadFine.matches())
{
final String location = ParserUtils.resolveEntities(mHeadFine.group(1));
final Date currentTime = parseDate(mHeadFine.group(2), mHeadFine.group(3), mHeadFine.group(4));
final List<Departure> departures = new ArrayList<Departure>(8);
final Calendar calendar = new GregorianCalendar();
final Matcher mDepCoarse = P_DEPARTURES_COARSE.matcher(mHeadCoarse.group(1));
while (mDepCoarse.find())
{
final Matcher mDepFine = P_DEPARTURES_FINE.matcher(mDepCoarse.group(1));
if (mDepFine.matches())
{
calendar.setTime(currentTime);
final String day = mDepFine.group(1);
if (day != null)
calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(day));
final String month = mDepFine.group(2);
if (month != null)
calendar.set(Calendar.MONTH, Integer.parseInt(month) - 1);
calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(mDepFine.group(3)));
calendar.set(Calendar.MINUTE, Integer.parseInt(mDepFine.group(4)));
final String normalizedLine = normalizeLine(mDepFine.group(5), mDepFine.group(6));
final String destination = normalizeStationName(mDepFine.group(7));
final String position = null; // TODO
final Departure departure = new Departure(calendar.getTime(), normalizedLine, LINES.get(normalizedLine), position, 0,
destination);
departures.add(departure);
}
else
{
throw new IllegalArgumentException("cannot parse '" + mDepCoarse.group(1) + "' on " + uri);
}
}
return new QueryDeparturesResult(uri, stationId, location, departures);
}
else
{
throw new IllegalArgumentException("cannot parse '" + mHeadCoarse.group(1) + "' on " + uri);
}
}
else
{
return new QueryDeparturesResult(uri, Status.NO_INFO);
}
}
private static final Pattern P_STATION_NAME_WHITESPACE = Pattern.compile("\\s+");
private String normalizeStationName(String name)
{
return P_STATION_NAME_WHITESPACE.matcher(name).replaceAll(" ");
} }
private static final Pattern P_NORMALIZE_LINE_TRAM = Pattern.compile("[12]\\d"); private static final Pattern P_NORMALIZE_LINE_TRAM = Pattern.compile("[12]\\d");