Denmark departures

git-svn-id: https://public-transport-enabler.googlecode.com/svn/trunk@588 0924bc21-9374-b0fa-ee44-9ff1593b38f0
This commit is contained in:
andreas.schildbach@gmail.com 2011-05-01 08:16:01 +00:00
parent 2cd4ebb926
commit 8833e42bb6
12 changed files with 719 additions and 513 deletions

View file

@ -21,6 +21,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.HashMap; import java.util.HashMap;
@ -30,11 +31,15 @@ import java.util.TimeZone;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory; import org.xmlpull.v1.XmlPullParserFactory;
import de.schildbach.pte.dto.Connection; import de.schildbach.pte.dto.Connection;
import de.schildbach.pte.dto.Departure;
import de.schildbach.pte.dto.GetConnectionDetailsResult; import de.schildbach.pte.dto.GetConnectionDetailsResult;
import de.schildbach.pte.dto.Line; import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Location; import de.schildbach.pte.dto.Location;
@ -42,6 +47,8 @@ import de.schildbach.pte.dto.LocationType;
import de.schildbach.pte.dto.NearbyStationsResult; import de.schildbach.pte.dto.NearbyStationsResult;
import de.schildbach.pte.dto.QueryConnectionsResult; import de.schildbach.pte.dto.QueryConnectionsResult;
import de.schildbach.pte.dto.QueryConnectionsResult.Status; import de.schildbach.pte.dto.QueryConnectionsResult.Status;
import de.schildbach.pte.dto.QueryDeparturesResult;
import de.schildbach.pte.dto.StationDepartures;
import de.schildbach.pte.util.Color; import de.schildbach.pte.util.Color;
import de.schildbach.pte.util.ParserUtils; import de.schildbach.pte.util.ParserUtils;
import de.schildbach.pte.util.XmlPullUtil; import de.schildbach.pte.util.XmlPullUtil;
@ -193,6 +200,178 @@ public abstract class AbstractHafasProvider implements NetworkProvider
} }
} }
private static final Pattern P_AJAX_GET_STOPS_JSON = Pattern.compile("SLs\\.sls=(.*?);SLs\\.showSuggestion\\(\\);", Pattern.DOTALL);
private static final Pattern P_AJAX_GET_STOPS_ID = Pattern.compile(".*?@L=(\\d+)@.*?");
protected final List<Location> ajaxGetStops(final String uri) throws IOException
{
final CharSequence page = ParserUtils.scrape(uri);
final Matcher mJson = P_AJAX_GET_STOPS_JSON.matcher(page);
if (mJson.matches())
{
final String json = mJson.group(1);
final List<Location> results = new ArrayList<Location>();
try
{
final JSONObject head = new JSONObject(json);
final JSONArray aSuggestions = head.getJSONArray("suggestions");
for (int i = 0; i < aSuggestions.length(); i++)
{
final JSONObject suggestion = aSuggestions.optJSONObject(i);
if (suggestion != null)
{
final int type = suggestion.getInt("type");
final String value = suggestion.getString("value");
final int lat = suggestion.getInt("ycoord");
final int lon = suggestion.getInt("xcoord");
int localId = 0;
final Matcher m = P_AJAX_GET_STOPS_ID.matcher(suggestion.getString("id"));
if (m.matches())
localId = Integer.parseInt(m.group(1));
if (type == 1) // station
{
results.add(new Location(LocationType.STATION, localId, lat, lon, null, value));
}
else if (type == 2) // address
{
results.add(new Location(LocationType.ADDRESS, 0, lat, lon, null, value));
}
else if (type == 4) // poi
{
results.add(new Location(LocationType.POI, localId, lat, lon, null, value));
}
else
{
throw new IllegalStateException("unknown type " + type + " on " + uri);
}
}
}
return results;
}
catch (final JSONException x)
{
x.printStackTrace();
throw new RuntimeException("cannot parse: '" + json + "' on " + uri, x);
}
}
else
{
throw new RuntimeException("cannot parse: '" + page + "' on " + uri);
}
}
private static final Pattern P_XML_QUERY_DEPARTURES_COARSE = Pattern.compile("\\G<Journey (.*?)(?:/>|><HIMMessage (.*?)/></Journey>)(?:\n|\\z)",
Pattern.DOTALL);
private static final Pattern P_XML_QUERY_DEPARTURES_FINE = Pattern.compile("" //
+ "fpTime\\s*=\"(\\d{1,2}:\\d{2})\"\\s*" // time
+ "fpDate\\s*=\"(\\d{2}\\.\\d{2}\\.\\d{2})\"\\s*" // date
+ "delay\\s*=\"(?:-|k\\.A\\.?|cancel|\\+?\\s*(\\d+))\"\\s*" // delay
+ "(?:e_delay\\s*=\"\\d+\"\\s*)?" // (???)
+ "(?:newpl\\s*=\"([^\"]*)\"\\s*)?" //
+ "(?:platform\\s*=\"([^\"]*)\"\\s*)?" // position
+ "targetLoc\\s*=\"([^\"]*)\"\\s*" // destination
+ "(?:hafasname\\s*=\"[^\"]*\"\\s*)?" // (???)
+ "prod\\s*=\"([^\"]*)\"\\s*" // line
+ "(?:class\\s*=\"[^\"]*\"\\s*)?" // (???)
+ "(?:dir\\s*=\"[^\"]*\"\\s*)?" // (destination)
+ "(?:depStation\\s*=\"(.*?)\"\\s*)?" //
+ "(?:delayReason\\s*=\"([^\"]*)\"\\s*)?" // message
+ "(?:is_reachable\\s*=\"([^\"]*)\"\\s*)?" // (???)
);
private static final Pattern P_XML_QUERY_DEPARTURES_MESSAGES = Pattern.compile("<Err code=\"([^\"]*)\" text=\"([^\"]*)\"");
protected QueryDeparturesResult xmlQueryDepartures(final String uri, final int stationId) throws IOException
{
// scrape page
final CharSequence page = ParserUtils.scrape(uri);
final QueryDeparturesResult result = new QueryDeparturesResult();
// parse page
final Matcher mMessage = P_XML_QUERY_DEPARTURES_MESSAGES.matcher(page);
if (mMessage.find())
{
final String code = mMessage.group(1);
final String text = mMessage.group(2);
if (code.equals("H730")) // Your input is not valid
return new QueryDeparturesResult(QueryDeparturesResult.Status.INVALID_STATION);
if (code.equals("H890"))
{
result.stationDepartures.add(new StationDepartures(new Location(LocationType.STATION, stationId),
Collections.<Departure> emptyList(), null));
return result;
}
throw new IllegalArgumentException("unknown error " + code + ", " + text);
}
final List<Departure> departures = new ArrayList<Departure>(8);
final Matcher mCoarse = P_XML_QUERY_DEPARTURES_COARSE.matcher(page);
while (mCoarse.find())
{
// TODO parse HIMMessage
final Matcher mFine = P_XML_QUERY_DEPARTURES_FINE.matcher(mCoarse.group(1));
if (mFine.matches())
{
if (mFine.group(8) == null)
{
final Calendar plannedTime = new GregorianCalendar(timeZone());
plannedTime.clear();
ParserUtils.parseEuropeanTime(plannedTime, mFine.group(1));
ParserUtils.parseGermanDate(plannedTime, mFine.group(2));
final Calendar predictedTime;
if (mFine.group(3) != null)
{
predictedTime = new GregorianCalendar(timeZone());
predictedTime.setTimeInMillis(plannedTime.getTimeInMillis());
predictedTime.add(Calendar.MINUTE, Integer.parseInt(mFine.group(3)));
}
else
{
predictedTime = null;
}
// TODO parse newpl if present
final String position = mFine.group(5) != null ? "Gl. " + ParserUtils.resolveEntities(mFine.group(5)) : null;
final String destination = ParserUtils.resolveEntities(mFine.group(6)).trim();
final String line = normalizeLine(ParserUtils.resolveEntities(mFine.group(7)));
final String message;
if (mFine.group(9) != null)
{
final String m = ParserUtils.resolveEntities(mFine.group(9)).trim();
message = m.length() > 0 ? m : null;
}
else
{
message = null;
}
departures.add(new Departure(plannedTime.getTime(), predictedTime != null ? predictedTime.getTime() : null, line,
line != null ? lineColors(line) : null, null, position, 0, destination, message));
}
}
else
{
throw new IllegalArgumentException("cannot parse '" + mCoarse.group(1) + "' on " + uri);
}
}
result.stationDepartures.add(new StationDepartures(new Location(LocationType.STATION, stationId), departures, null));
return result;
}
public QueryConnectionsResult queryConnections(Location from, Location via, Location to, final Date date, final boolean dep, public QueryConnectionsResult queryConnections(Location from, Location via, Location to, final Date date, final boolean dep,
final String products, final WalkSpeed walkSpeed) throws IOException final String products, final WalkSpeed walkSpeed) throws IOException
{ {
@ -620,6 +799,290 @@ public abstract class AbstractHafasProvider implements NetworkProvider
throw new IllegalArgumentException(location.type.toString()); throw new IllegalArgumentException(location.type.toString());
} }
private final static Pattern P_WHITESPACE = Pattern.compile("\\s+");
private final String normalizeWhitespace(final String str)
{
return P_WHITESPACE.matcher(str).replaceAll("");
}
public GetConnectionDetailsResult getConnectionDetails(String connectionUri) throws IOException
{
throw new UnsupportedOperationException();
}
private static final Pattern P_XML_NEARBY_STATIONS_COARSE = Pattern.compile("\\G<St\\s*(.*?)/?>(?:\n|\\z)", Pattern.DOTALL);
private static final Pattern P_XML_NEARBY_STATIONS_FINE = Pattern.compile("" //
+ "evaId=\"(\\d+)\"\\s*" // id
+ "name=\"([^\"]+)\".*?" // name
+ "x=\"(\\d+)\"\\s*" // x
+ "y=\"(\\d+)\"\\s*" // y
);
private static final Pattern P_XML_NEARBY_STATIONS_MESSAGES = Pattern.compile("<Err code=\"([^\"]*)\" text=\"([^\"]*)\"");
protected final NearbyStationsResult xmlNearbyStations(final String uri) throws IOException
{
// scrape page
final CharSequence page = ParserUtils.scrape(uri);
final List<Location> stations = new ArrayList<Location>();
// parse page
final Matcher mMessage = P_XML_NEARBY_STATIONS_MESSAGES.matcher(page);
if (mMessage.find())
{
final String code = mMessage.group(1);
final String text = mMessage.group(2);
if (code.equals("H730")) // Your input is not valid
return new NearbyStationsResult(NearbyStationsResult.Status.INVALID_STATION);
if (code.equals("H890")) // No trains in result
return new NearbyStationsResult(stations);
throw new IllegalArgumentException("unknown error " + code + ", " + text);
}
final Matcher mCoarse = P_XML_NEARBY_STATIONS_COARSE.matcher(page);
while (mCoarse.find())
{
final Matcher mFine = P_XML_NEARBY_STATIONS_FINE.matcher(mCoarse.group(1));
if (mFine.matches())
{
final int parsedId = Integer.parseInt(mFine.group(1));
final String parsedName = ParserUtils.resolveEntities(mFine.group(2)).trim();
final int parsedLon = Integer.parseInt(mFine.group(3));
final int parsedLat = Integer.parseInt(mFine.group(4));
stations.add(new Location(LocationType.STATION, parsedId, parsedLat, parsedLon, null, parsedName));
}
else
{
throw new IllegalArgumentException("cannot parse '" + mCoarse.group(1) + "' on " + uri);
}
}
return new NearbyStationsResult(stations);
}
private final static Pattern P_NEARBY_COARSE = Pattern.compile("<tr class=\"(zebra[^\"]*)\">(.*?)</tr>", Pattern.DOTALL);
private final static Pattern P_NEARBY_FINE_COORDS = Pattern
.compile("REQMapRoute0\\.Location0\\.X=(-?\\d+)&(?:amp;)?REQMapRoute0\\.Location0\\.Y=(-?\\d+)&");
private final static Pattern P_NEARBY_FINE_LOCATION = Pattern.compile("[\\?&]input=(\\d+)&[^\"]*\">([^<]*)<");
protected abstract String nearbyStationUri(String stationId);
public NearbyStationsResult nearbyStations(final String stationId, final int lat, final int lon, final int maxDistance, final int maxStations)
throws IOException
{
if (stationId == null)
throw new IllegalArgumentException("stationId must be given");
final List<Location> stations = new ArrayList<Location>();
final String uri = nearbyStationUri(stationId);
final CharSequence page = ParserUtils.scrape(uri);
String oldZebra = null;
final Matcher mCoarse = P_NEARBY_COARSE.matcher(page);
while (mCoarse.find())
{
final String zebra = mCoarse.group(1);
if (oldZebra != null && zebra.equals(oldZebra))
throw new IllegalArgumentException("missed row? last:" + zebra);
else
oldZebra = zebra;
final Matcher mFineLocation = P_NEARBY_FINE_LOCATION.matcher(mCoarse.group(2));
if (mFineLocation.find())
{
int parsedLon = 0;
int parsedLat = 0;
final int parsedId = Integer.parseInt(mFineLocation.group(1));
final String parsedName = ParserUtils.resolveEntities(mFineLocation.group(2));
final Matcher mFineCoords = P_NEARBY_FINE_COORDS.matcher(mCoarse.group(2));
if (mFineCoords.find())
{
parsedLon = Integer.parseInt(mFineCoords.group(1));
parsedLat = Integer.parseInt(mFineCoords.group(2));
}
final String[] nameAndPlace = splitNameAndPlace(parsedName);
stations.add(new Location(LocationType.STATION, parsedId, parsedLat, parsedLon, nameAndPlace[0], nameAndPlace[1]));
}
else
{
throw new IllegalArgumentException("cannot parse '" + mCoarse.group(2) + "' on " + uri);
}
}
if (maxStations == 0 || maxStations >= stations.size())
return new NearbyStationsResult(stations);
else
return new NearbyStationsResult(stations.subList(0, maxStations));
}
protected static final Pattern P_NORMALIZE_LINE = Pattern.compile("([A-Za-zÄÖÜäöüßáàâéèêíìîóòôúùûØ/-]+)[\\s-]*(.*)");
protected String normalizeLine(final String type, final String line)
{
final char normalizedType = normalizeType(type);
if (normalizedType != 0)
{
if (line != null)
{
final Matcher m = P_NORMALIZE_LINE.matcher(line);
final String strippedLine = m.matches() ? m.group(1) + m.group(2) : line;
return normalizedType + strippedLine;
}
else
{
return Character.toString(normalizedType);
}
}
throw new IllegalStateException("cannot normalize type '" + type + "' line '" + line + "'");
}
protected abstract char normalizeType(String type);
protected final char normalizeCommonTypes(final String ucType)
{
// Intercity
if (ucType.equals("EC")) // EuroCity
return 'I';
if (ucType.equals("EN")) // EuroNight
return 'I';
if (ucType.equals("EIC")) // Ekspres InterCity, Polen
return 'I';
if (ucType.equals("ICE")) // InterCityExpress
return 'I';
if (ucType.equals("IC")) // InterCity
return 'I';
if (ucType.equals("ICT")) // InterCity
return 'I';
if (ucType.equals("CNL")) // CityNightLine
return 'I';
if (ucType.equals("OEC")) // ÖBB-EuroCity
return 'I';
if (ucType.equals("OIC")) // ÖBB-InterCity
return 'I';
if (ucType.equals("RJ")) // RailJet, Österreichische Bundesbahnen
return 'I';
if (ucType.equals("THA")) // Thalys
return 'I';
if (ucType.equals("TGV")) // Train à Grande Vitesse
return 'I';
if (ucType.equals("DNZ")) // Berlin-Saratov, Berlin-Moskva, Connections only?
return 'I';
if (ucType.equals("AIR")) // Generic Flight
return 'I';
if (ucType.equals("ECB")) // EC, Verona-München
return 'I';
if (ucType.equals("INZ")) // Nacht
return 'I';
if (ucType.equals("RHI")) // ICE
return 'I';
if (ucType.equals("RHT")) // TGV
return 'I';
if (ucType.equals("TGD")) // TGV
return 'I';
if (ucType.equals("IRX")) // IC
return 'I';
// Regional
if (ucType.equals("ZUG")) // Generic Train
return 'R';
if (ucType.equals("R")) // Generic Regional Train
return 'R';
if (ucType.equals("DPN")) // Dritter Personen Nahverkehr
return 'R';
if (ucType.equals("RB")) // RegionalBahn
return 'R';
if (ucType.equals("RE")) // RegionalExpress
return 'R';
if (ucType.equals("IR")) // Interregio
return 'R';
if (ucType.equals("IRE")) // Interregio Express
return 'R';
if (ucType.equals("HEX")) // Harz-Berlin-Express, Veolia
return 'R';
if (ucType.equals("WFB")) // Westfalenbahn
return 'R';
if (ucType.equals("RT")) // RegioTram
return 'R';
if (ucType.equals("REX")) // RegionalExpress, Österreich
return 'R';
if (ucType.equals("OS")) // Osobný vlak, Slovakia oder Osobní vlak, Czech Republic
return 'R';
if (ucType.equals("SP")) // Spěšný vlak, Czech Republic
return 'R';
// Suburban Trains
if (ucType.equals("S")) // Generic S-Bahn
return 'S';
// Subway
if (ucType.equals("U")) // Generic U-Bahn
return 'U';
// Tram
if (ucType.equals("STR")) // Generic Tram
return 'T';
// Bus
if (ucType.equals("BUS")) // Generic Bus
return 'B';
if (ucType.equals("AST")) // Anruf-Sammel-Taxi
return 'B';
if (ucType.equals("RUF")) // Rufbus
return 'B';
if (ucType.equals("SEV")) // Schienen-Ersatz-Verkehr
return 'B';
if (ucType.equals("BUSSEV")) // Schienen-Ersatz-Verkehr
return 'B';
if (ucType.equals("BSV")) // Bus SEV
return 'B';
if (ucType.equals("FB")) // Luxemburg-Saarbrücken
return 'B';
// Ferry
if (ucType.equals("SCH")) // Schiff
return 'F';
if (ucType.equals("AS")) // SyltShuttle, eigentlich Autoreisezug
return 'F';
return 0;
}
protected String normalizeLine(final String line)
{
if (line == null || line.length() == 0)
return null;
final Matcher m = P_NORMALIZE_LINE.matcher(line);
if (m.matches())
{
final String type = m.group(1);
final String number = m.group(2);
final char normalizedType = normalizeType(type);
if (normalizedType != 0)
return normalizedType + type + number;
throw new IllegalStateException("cannot normalize type " + type + " number " + number + " line " + line);
}
throw new IllegalStateException("cannot normalize line " + line);
}
private static final Pattern P_LINE_S = Pattern.compile("S\\d+"); private static final Pattern P_LINE_S = Pattern.compile("S\\d+");
private static final Pattern P_LINE_SN = Pattern.compile("SN\\d*"); private static final Pattern P_LINE_SN = Pattern.compile("SN\\d*");
@ -755,214 +1218,6 @@ public abstract class AbstractHafasProvider implements NetworkProvider
+ longCategory + "'"); + longCategory + "'");
} }
private final static Pattern P_WHITESPACE = Pattern.compile("\\s+");
private final String normalizeWhitespace(final String str)
{
return P_WHITESPACE.matcher(str).replaceAll("");
}
public GetConnectionDetailsResult getConnectionDetails(String connectionUri) throws IOException
{
throw new UnsupportedOperationException();
}
private final static Pattern P_NEARBY_COARSE = Pattern.compile("<tr class=\"(zebra[^\"]*)\">(.*?)</tr>", Pattern.DOTALL);
private final static Pattern P_NEARBY_FINE_COORDS = Pattern
.compile("REQMapRoute0\\.Location0\\.X=(-?\\d+)&(?:amp;)?REQMapRoute0\\.Location0\\.Y=(-?\\d+)&");
private final static Pattern P_NEARBY_FINE_LOCATION = Pattern.compile("[\\?&]input=(\\d+)&[^\"]*\">([^<]*)<");
protected abstract String nearbyStationUri(String stationId);
public NearbyStationsResult nearbyStations(final String stationId, final int lat, final int lon, final int maxDistance, final int maxStations)
throws IOException
{
if (stationId == null)
throw new IllegalArgumentException("stationId must be given");
final List<Location> stations = new ArrayList<Location>();
final String uri = nearbyStationUri(stationId);
final CharSequence page = ParserUtils.scrape(uri);
String oldZebra = null;
final Matcher mCoarse = P_NEARBY_COARSE.matcher(page);
while (mCoarse.find())
{
final String zebra = mCoarse.group(1);
if (oldZebra != null && zebra.equals(oldZebra))
throw new IllegalArgumentException("missed row? last:" + zebra);
else
oldZebra = zebra;
final Matcher mFineLocation = P_NEARBY_FINE_LOCATION.matcher(mCoarse.group(2));
if (mFineLocation.find())
{
int parsedLon = 0;
int parsedLat = 0;
final int parsedId = Integer.parseInt(mFineLocation.group(1));
final String parsedName = ParserUtils.resolveEntities(mFineLocation.group(2));
final Matcher mFineCoords = P_NEARBY_FINE_COORDS.matcher(mCoarse.group(2));
if (mFineCoords.find())
{
parsedLon = Integer.parseInt(mFineCoords.group(1));
parsedLat = Integer.parseInt(mFineCoords.group(2));
}
final String[] nameAndPlace = splitNameAndPlace(parsedName);
stations.add(new Location(LocationType.STATION, parsedId, parsedLat, parsedLon, nameAndPlace[0], nameAndPlace[1]));
}
else
{
throw new IllegalArgumentException("cannot parse '" + mCoarse.group(2) + "' on " + uri);
}
}
if (maxStations == 0 || maxStations >= stations.size())
return new NearbyStationsResult(stations);
else
return new NearbyStationsResult(stations.subList(0, maxStations));
}
protected static final Pattern P_NORMALIZE_LINE = Pattern.compile("([A-Za-zÄÖÜäöüßáàâéèêíìîóòôúùû/-]+)[\\s-]*(.*)");
protected String normalizeLine(final String type, final String line)
{
final char normalizedType = normalizeType(type);
if (normalizedType != 0)
{
if (line != null)
{
final Matcher m = P_NORMALIZE_LINE.matcher(line);
final String strippedLine = m.matches() ? m.group(1) + m.group(2) : line;
return normalizedType + strippedLine;
}
else
{
return Character.toString(normalizedType);
}
}
throw new IllegalStateException("cannot normalize type '" + type + "' line '" + line + "'");
}
protected abstract char normalizeType(String type);
protected final char normalizeCommonTypes(final String ucType)
{
// Intercity
if (ucType.equals("EC")) // EuroCity
return 'I';
if (ucType.equals("EN")) // EuroNight
return 'I';
if (ucType.equals("EIC")) // Ekspres InterCity, Polen
return 'I';
if (ucType.equals("ICE")) // InterCityExpress
return 'I';
if (ucType.equals("IC")) // InterCity
return 'I';
if (ucType.equals("ICT")) // InterCity
return 'I';
if (ucType.equals("CNL")) // CityNightLine
return 'I';
if (ucType.equals("OEC")) // ÖBB-EuroCity
return 'I';
if (ucType.equals("OIC")) // ÖBB-InterCity
return 'I';
if (ucType.equals("RJ")) // RailJet, Österreichische Bundesbahnen
return 'I';
if (ucType.equals("THA")) // Thalys
return 'I';
if (ucType.equals("TGV")) // Train à Grande Vitesse
return 'I';
if (ucType.equals("DNZ")) // Berlin-Saratov, Berlin-Moskva, Connections only?
return 'I';
if (ucType.equals("AIR")) // Generic Flight
return 'I';
if (ucType.equals("ECB")) // EC, Verona-München
return 'I';
if (ucType.equals("INZ")) // Nacht
return 'I';
if (ucType.equals("RHI")) // ICE
return 'I';
if (ucType.equals("RHT")) // TGV
return 'I';
if (ucType.equals("TGD")) // TGV
return 'I';
if (ucType.equals("IRX")) // IC
return 'I';
// Regional
if (ucType.equals("ZUG")) // Generic Train
return 'R';
if (ucType.equals("R")) // Generic Regional Train
return 'R';
if (ucType.equals("DPN")) // Dritter Personen Nahverkehr
return 'R';
if (ucType.equals("RB")) // RegionalBahn
return 'R';
if (ucType.equals("RE")) // RegionalExpress
return 'R';
if (ucType.equals("IR")) // Interregio
return 'R';
if (ucType.equals("IRE")) // Interregio Express
return 'R';
if (ucType.equals("HEX")) // Harz-Berlin-Express, Veolia
return 'R';
if (ucType.equals("WFB")) // Westfalenbahn
return 'R';
if (ucType.equals("RT")) // RegioTram
return 'R';
if (ucType.equals("REX")) // RegionalExpress, Österreich
return 'R';
if (ucType.equals("OS")) // Osobný vlak, Slovakia oder Osobní vlak, Czech Republic
return 'R';
if (ucType.equals("SP")) // Spěšný vlak, Czech Republic
return 'R';
// Suburban Trains
if (ucType.equals("S")) // Generic S-Bahn
return 'S';
// Subway
if (ucType.equals("U")) // Generic U-Bahn
return 'U';
// Tram
if (ucType.equals("STR")) // Generic Tram
return 'T';
// Bus
if (ucType.equals("BUS")) // Generic Bus
return 'B';
if (ucType.equals("AST")) // Anruf-Sammel-Taxi
return 'B';
if (ucType.equals("RUF")) // Rufbus
return 'B';
if (ucType.equals("SEV")) // Schienen-Ersatz-Verkehr
return 'B';
if (ucType.equals("BUSSEV")) // Schienen-Ersatz-Verkehr
return 'B';
if (ucType.equals("BSV")) // Bus SEV
return 'B';
if (ucType.equals("FB")) // Luxemburg-Saarbrücken
return 'B';
// Ferry
if (ucType.equals("SCH")) // Schiff
return 'F';
if (ucType.equals("AS")) // SyltShuttle, eigentlich Autoreisezug
return 'F';
return 0;
}
private static final Pattern P_CONNECTION_ID = Pattern.compile("co=(C\\d+-\\d+)&"); private static final Pattern P_CONNECTION_ID = Pattern.compile("co=(C\\d+-\\d+)&");
protected static String extractConnectionId(final String link) protected static String extractConnectionId(final String link)

View file

@ -20,7 +20,6 @@ package de.schildbach.pte;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.List; import java.util.List;
@ -28,7 +27,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import de.schildbach.pte.dto.Connection; import de.schildbach.pte.dto.Connection;
import de.schildbach.pte.dto.Departure;
import de.schildbach.pte.dto.GetConnectionDetailsResult; import de.schildbach.pte.dto.GetConnectionDetailsResult;
import de.schildbach.pte.dto.Line; import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Location; import de.schildbach.pte.dto.Location;
@ -36,7 +34,6 @@ import de.schildbach.pte.dto.LocationType;
import de.schildbach.pte.dto.NearbyStationsResult; import de.schildbach.pte.dto.NearbyStationsResult;
import de.schildbach.pte.dto.QueryConnectionsResult; import de.schildbach.pte.dto.QueryConnectionsResult;
import de.schildbach.pte.dto.QueryDeparturesResult; import de.schildbach.pte.dto.QueryDeparturesResult;
import de.schildbach.pte.dto.StationDepartures;
import de.schildbach.pte.exception.SessionExpiredException; import de.schildbach.pte.exception.SessionExpiredException;
import de.schildbach.pte.util.ParserUtils; import de.schildbach.pte.util.ParserUtils;
@ -485,107 +482,18 @@ public final class BahnProvider extends AbstractHafasProvider
} }
} }
private String departuresQueryUri(final String stationId, final int maxDepartures) public QueryDeparturesResult queryDepartures(final String stationId, final int maxDepartures, final boolean equivs) throws IOException
{ {
final StringBuilder uri = new StringBuilder(); final StringBuilder uri = new StringBuilder();
uri.append(API_BASE).append("bhftafel.exe/dn"); uri.append(API_BASE).append("bhftafel.exe/dn");
uri.append("?productsFilter=11111111111111"); uri.append("?productsFilter=11111111111111");
uri.append("&boardType=dep"); uri.append("&boardType=dep");
// taken from railnavigator; ignore maxDepartures because result contains other stations uri.append("&maxJourneys=50"); // ignore maxDepartures because result contains other stations
uri.append("&maxJourneys=50");
uri.append("&start=yes"); uri.append("&start=yes");
uri.append("&L=vs_java3"); uri.append("&L=vs_java3");
uri.append("&input=").append(stationId); uri.append("&input=").append(stationId);
return uri.toString();
}
static final Pattern P_DEPARTURES_COARSE = Pattern.compile("\\G<Journey (.*?)/?>(?:\n|\\z)", Pattern.DOTALL); return xmlQueryDepartures(uri.toString(), Integer.parseInt(stationId));
static final Pattern P_DEPARTURES_FINE = Pattern.compile("" //
+ "fpTime=\"(\\d{1,2}:\\d{2})\" fpDate=\"(\\d{2}\\.\\d{2}\\.\\d{2})\" \n" // time, date
+ "delay=\"(?:-|k\\.A\\.?|cancel|\\+?\\s*(\\d+))\" \n" // delay
+ "(?:platform =\"([^\"]*)\" \n)?" // position
+ "(?:newpl =\"([^\"]*)\" \n)?" //
+ "targetLoc=\"(.*?)\" \n" // destination
+ "prod=\"([^\"]*)\" \n" // line
+ "(?:dir=[^\n]*\n)?" // (destination)
+ "(?:depStation=\"(.*?)\"\n)?" //
+ "delayReason=\"([^\"]*)\"\n" // message
);
private static final Pattern P_DEPARTURES_MESSAGES = Pattern.compile("<Err code=\"([^\"]*)\" text=\"([^\"]*)\"");
public QueryDeparturesResult queryDepartures(final String stationId, final int maxDepartures, final boolean equivs) throws IOException
{
final QueryDeparturesResult result = new QueryDeparturesResult();
// scrape page
final String uri = departuresQueryUri(stationId, maxDepartures);
final CharSequence page = ParserUtils.scrape(uri);
// parse page
final Matcher mMessage = P_DEPARTURES_MESSAGES.matcher(page);
if (mMessage.find())
{
final String code = mMessage.group(1);
final String text = mMessage.group(2);
if (code.equals("H730")) // Your input is not valid
return new QueryDeparturesResult(QueryDeparturesResult.Status.INVALID_STATION);
if (code.equals("H890"))
{
result.stationDepartures.add(new StationDepartures(new Location(LocationType.STATION, Integer.parseInt(stationId)), Collections
.<Departure> emptyList(), null));
return result;
}
throw new IllegalArgumentException("unknown error " + code + ", " + text);
}
final List<Departure> departures = new ArrayList<Departure>(8);
final Matcher mDepCoarse = P_DEPARTURES_COARSE.matcher(page);
while (mDepCoarse.find())
{
final Matcher mDepFine = P_DEPARTURES_FINE.matcher(mDepCoarse.group(1));
if (mDepFine.matches())
{
if (mDepFine.group(8) == null)
{
final Calendar plannedTime = new GregorianCalendar(timeZone());
plannedTime.clear();
ParserUtils.parseEuropeanTime(plannedTime, mDepFine.group(1));
ParserUtils.parseGermanDate(plannedTime, mDepFine.group(2));
final Calendar predictedTime;
if (mDepFine.group(3) != null)
{
predictedTime = new GregorianCalendar(timeZone());
predictedTime.setTimeInMillis(plannedTime.getTimeInMillis());
predictedTime.add(Calendar.MINUTE, Integer.parseInt(mDepFine.group(3)));
}
else
{
predictedTime = null;
}
final String position = mDepFine.group(4) != null ? "Gl. " + ParserUtils.resolveEntities(mDepFine.group(4)) : null;
final String destination = ParserUtils.resolveEntities(mDepFine.group(6)).trim();
final String line = normalizeLine(ParserUtils.resolveEntities(mDepFine.group(7)));
final String message = ParserUtils.resolveEntities(mDepFine.group(9)).trim();
departures.add(new Departure(plannedTime.getTime(), predictedTime != null ? predictedTime.getTime() : null, line,
line != null ? lineColors(line) : null, null, position, 0, destination, message.length() > 0 ? message : null));
}
}
else
{
throw new IllegalArgumentException("cannot parse '" + mDepCoarse.group(1) + "' on " + stationId);
}
}
result.stationDepartures.add(new StationDepartures(new Location(LocationType.STATION, Integer.parseInt(stationId)), departures, null));
return result;
} }
@Override @Override
@ -599,7 +507,8 @@ public final class BahnProvider extends AbstractHafasProvider
private static final Pattern P_NORMALIZE_LINE_RUSSIA = Pattern.compile("(?:D\\s*)?(\\d{1,3}(?:[A-Z]{2}|Y))"); private static final Pattern P_NORMALIZE_LINE_RUSSIA = Pattern.compile("(?:D\\s*)?(\\d{1,3}(?:[A-Z]{2}|Y))");
private static final Pattern P_NORMALIZE_LINE_SBAHN = Pattern.compile("S\\w*\\d+"); private static final Pattern P_NORMALIZE_LINE_SBAHN = Pattern.compile("S\\w*\\d+");
private static String normalizeLine(final String line) @Override
protected final String normalizeLine(final String line)
{ {
// TODO ARZ Simplon Tunnel: Brig - Iselle di Trasquera // TODO ARZ Simplon Tunnel: Brig - Iselle di Trasquera
// ARZ29171 // ARZ29171

View file

@ -906,7 +906,8 @@ public final class BvgProvider extends AbstractHafasProvider
private static final Pattern P_NORMALIZE_LINE_SPECIAL_NUMBER = Pattern.compile("\\d{4,}"); private static final Pattern P_NORMALIZE_LINE_SPECIAL_NUMBER = Pattern.compile("\\d{4,}");
private static final Pattern P_NORMALIZE_LINE_SPECIAL_BUS = Pattern.compile("Bus[A-Z]"); private static final Pattern P_NORMALIZE_LINE_SPECIAL_BUS = Pattern.compile("Bus[A-Z]");
private static String normalizeLine(final String line) @Override
protected String normalizeLine(final String line)
{ {
if (line == null || line.length() == 0) if (line == null || line.length() == 0)
return null; return null;

View file

@ -0,0 +1,173 @@
/*
* Copyright 2010, 2011 the original author or authors.
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.schildbach.pte;
import java.io.IOException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import de.schildbach.pte.dto.Location;
import de.schildbach.pte.dto.NearbyStationsResult;
import de.schildbach.pte.dto.QueryDeparturesResult;
import de.schildbach.pte.util.ParserUtils;
/**
* @author Andreas Schildbach
*/
public class DsbProvider extends AbstractHafasProvider
{
public static final NetworkId NETWORK_ID = NetworkId.DSB;
private static final String API_BASE = "http://mobil.rejseplanen.dk/mobil-bin/";
public DsbProvider()
{
super(null, null);
}
public NetworkId id()
{
return NETWORK_ID;
}
public boolean hasCapabilities(final Capability... capabilities)
{
for (final Capability capability : capabilities)
if (capability == Capability.DEPARTURES)
return true;
return false;
}
private static final String AUTOCOMPLETE_URI = API_BASE + "ajax-getstop.exe/dn?getstop=1&REQ0JourneyStopsS0A=255&S=%s?&js=true&";
private static final String ENCODING = "ISO-8859-1";
@Override
public List<Location> autocompleteStations(final CharSequence constraint) throws IOException
{
final String uri = String.format(AUTOCOMPLETE_URI, ParserUtils.urlEncode(constraint.toString(), ENCODING));
return ajaxGetStops(uri);
}
@Override
protected String nearbyStationUri(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
{
final StringBuilder uri = new StringBuilder(API_BASE);
uri.append("stboard.exe/dn");
uri.append("?productsFilter=11111111111");
uri.append("&boardType=dep");
uri.append("&input=").append(ParserUtils.urlEncode(stationId));
uri.append("&sTI=1&start=yes&hcount=0");
uri.append("&L=vs_java3");
// &inputTripelId=A%3d1%40O%3dCopenhagen%20Airport%40X%3d12646941%40Y%3d55629753%40U%3d86%40L%3d900000011%40B%3d1
return xmlNearbyStations(uri.toString());
}
private static final Pattern P_NORMALIZE_LINE_AND_TYPE = Pattern.compile("([^#]*)#(.*)");
@Override
protected String normalizeLine(final String line)
{
final Matcher m = P_NORMALIZE_LINE_AND_TYPE.matcher(line);
if (m.matches())
{
final String number = m.group(1).replaceAll("\\s+", " ");
final String type = m.group(2);
final char normalizedType = normalizeType(type);
if (normalizedType != 0)
return normalizedType + number;
throw new IllegalStateException("cannot normalize type " + type + " number " + number + " line " + line);
}
throw new IllegalStateException("cannot normalize line " + line);
}
@Override
protected char normalizeType(final String type)
{
final String ucType = type.toUpperCase();
if ("ICL".equals(ucType))
return 'I';
if ("ØR".equals(ucType))
return 'R';
if ("RA".equals(ucType))
return 'R';
if ("RX".equals(ucType))
return 'R';
if ("PP".equals(ucType))
return 'R';
if ("S-TOG".equals(ucType))
return 'S';
if ("MET".equals(ucType))
return 'U';
if ("BYBUS".equals(ucType))
return 'B';
if ("X-BUS".equals(ucType))
return 'B';
if ("HV-BUS".equals(ucType)) // Havnebus
return 'B';
if ("T-BUS".equals(ucType)) // Togbus
return 'B';
if ("TELEBUS".equals(ucType))
return 'P';
if ("TELETAXI".equals(ucType))
return 'P';
if ("FÆRGE".equals(ucType))
return 'F';
final char t = normalizeCommonTypes(ucType);
if (t != 0)
return t;
return 0;
}
public QueryDeparturesResult queryDepartures(final String stationId, final int maxDepartures, final boolean equivs) throws IOException
{
final StringBuilder uri = new StringBuilder();
uri.append(API_BASE).append("stboard.exe/dn");
uri.append("?productsFilter=11111111111");
uri.append("&boardType=dep");
uri.append("&maxJourneys=50"); // ignore maxDepartures because result contains other stations
uri.append("&start=yes");
uri.append("&L=vs_java3");
uri.append("&input=").append(stationId);
return xmlQueryDepartures(uri.toString(), Integer.parseInt(stationId));
}
}

View file

@ -37,6 +37,9 @@ public enum NetworkId
// Netherlands // Netherlands
NS, NS,
// Denmark
DSB,
// United Kingdom // United Kingdom
TFL, TLEM, TLEA, TLSE, TLSW, TFL, TLEM, TLEA, TLSE, TLSW,

View file

@ -40,7 +40,7 @@ public class NsProvider extends AbstractHafasProvider
{ {
public static final NetworkId NETWORK_ID = NetworkId.NS; public static final NetworkId NETWORK_ID = NetworkId.NS;
public static final String OLD_NETWORK_ID = "hafas.bene-system.com"; public static final String OLD_NETWORK_ID = "hafas.bene-system.com";
private static final String API_URI = "http://hafas.bene-system.com/bin/extxml.exe"; private static final String API_URI = "http://hafas.bene-system.com/bin/extxml.exe"; // http://plannerint.b-rail.be/bin/extxml.exe
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;
@ -179,27 +179,6 @@ public class NsProvider extends AbstractHafasProvider
} }
} }
private String normalizeLine(final String line)
{
if (line == null || line.length() == 0)
return null;
final Matcher m = P_NORMALIZE_LINE.matcher(line);
if (m.matches())
{
final String type = m.group(1);
final String number = m.group(2);
final char normalizedType = normalizeType(type);
if (normalizedType != 0)
return normalizedType + type + number;
throw new IllegalStateException("cannot normalize type " + type + " number " + number + " line " + line);
}
throw new IllegalStateException("cannot normalize line " + line);
}
@Override @Override
protected char normalizeType(final String type) protected char normalizeType(final String type)
{ {

View file

@ -76,71 +76,13 @@ public class OebbProvider extends AbstractHafasProvider
private static final String AUTOCOMPLETE_URI = API_BASE private static final String AUTOCOMPLETE_URI = API_BASE
+ "ajax-getstop.exe/dny?start=1&tpl=suggest2json&REQ0JourneyStopsS0A=255&REQ0JourneyStopsB=12&S=%s?&js=true&"; + "ajax-getstop.exe/dny?start=1&tpl=suggest2json&REQ0JourneyStopsS0A=255&REQ0JourneyStopsB=12&S=%s?&js=true&";
private static final String ENCODING = "ISO-8859-1"; private static final String ENCODING = "ISO-8859-1";
private static final Pattern P_AUTOCOMPLETE_JSON = Pattern.compile("SLs\\.sls=(.*?);SLs\\.showSuggestion\\(\\);", Pattern.DOTALL);
private static final Pattern P_AUTOCOMPLETE_ID = Pattern.compile(".*?@L=(\\d+)@.*?");
@Override @Override
public List<Location> autocompleteStations(final CharSequence constraint) throws IOException public List<Location> autocompleteStations(final CharSequence constraint) throws IOException
{ {
final String uri = String.format(AUTOCOMPLETE_URI, ParserUtils.urlEncode(constraint.toString(), ENCODING)); final String uri = String.format(AUTOCOMPLETE_URI, ParserUtils.urlEncode(constraint.toString(), ENCODING));
final CharSequence page = ParserUtils.scrape(uri);
final Matcher mJson = P_AUTOCOMPLETE_JSON.matcher(page); return ajaxGetStops(uri);
if (mJson.matches())
{
final String json = mJson.group(1);
final List<Location> results = new ArrayList<Location>();
try
{
final JSONObject head = new JSONObject(json);
final JSONArray aSuggestions = head.getJSONArray("suggestions");
for (int i = 0; i < aSuggestions.length(); i++)
{
final JSONObject suggestion = aSuggestions.optJSONObject(i);
if (suggestion != null)
{
final int type = suggestion.getInt("type");
final String value = suggestion.getString("value");
final int lat = suggestion.getInt("ycoord");
final int lon = suggestion.getInt("xcoord");
int localId = 0;
final Matcher m = P_AUTOCOMPLETE_ID.matcher(suggestion.getString("id"));
if (m.matches())
localId = Integer.parseInt(m.group(1));
if (type == 1) // station
{
results.add(new Location(LocationType.STATION, localId, lat, lon, null, value));
}
else if (type == 2) // address
{
results.add(new Location(LocationType.ADDRESS, 0, lat, lon, null, value));
}
else if (type == 4) // poi
{
results.add(new Location(LocationType.POI, localId, lat, lon, null, value));
}
else
{
throw new IllegalStateException("unknown type " + type + " on " + uri);
}
}
}
return results;
}
catch (final JSONException x)
{
x.printStackTrace();
throw new RuntimeException("cannot parse: '" + json + "' on " + uri, x);
}
}
else
{
throw new RuntimeException("cannot parse: '" + page + "' on " + uri);
}
} }
private final String NEARBY_URI = API_BASE + "stboard.exe/dn?distance=50&near=Suchen&input=%s"; private final String NEARBY_URI = API_BASE + "stboard.exe/dn?distance=50&near=Suchen&input=%s";
@ -604,7 +546,8 @@ public class OebbProvider extends AbstractHafasProvider
private static final Pattern P_NORMALIZE_LINE_RUSSIA = Pattern.compile("\\d{1,3}[A-Z]{2}"); private static final Pattern P_NORMALIZE_LINE_RUSSIA = Pattern.compile("\\d{1,3}[A-Z]{2}");
private static final Pattern P_NORMALIZE_LINE_RUSSIA_INT = Pattern.compile("\\d{3}Y"); private static final Pattern P_NORMALIZE_LINE_RUSSIA_INT = Pattern.compile("\\d{3}Y");
private String normalizeLine(final String line) @Override
protected String normalizeLine(final String line)
{ {
final Matcher m = P_NORMALIZE_LINE.matcher(line); final Matcher m = P_NORMALIZE_LINE.matcher(line);
if (m.matches()) if (m.matches())

View file

@ -603,7 +603,8 @@ public class RmvProvider extends AbstractHafasProvider
} }
} }
private static String normalizeLine(final String line) @Override
protected String normalizeLine(final String line)
{ {
if (line == null || line.length() == 0) if (line == null || line.length() == 0)
return null; return null;

View file

@ -202,27 +202,6 @@ public class SbbProvider extends AbstractHafasProvider
} }
} }
private String normalizeLine(final String line)
{
if (line == null || line.length() == 0)
return null;
final Matcher m = P_NORMALIZE_LINE.matcher(line);
if (m.matches())
{
final String type = m.group(1);
final String number = m.group(2);
final char normalizedType = normalizeType(type);
if (normalizedType != 0)
return normalizedType + type + number;
throw new IllegalStateException("cannot normalize type " + type + " number " + number + " line " + line);
}
throw new IllegalStateException("cannot normalize line " + line);
}
private static final Pattern P_NORMALIZE_TYPE_SBAHN = Pattern.compile("SN?\\d*"); private static final Pattern P_NORMALIZE_TYPE_SBAHN = Pattern.compile("SN?\\d*");
private static final Pattern P_NORMALIZE_TYPE_BUS = Pattern.compile("BUS\\w*"); private static final Pattern P_NORMALIZE_TYPE_BUS = Pattern.compile("BUS\\w*");

View file

@ -179,27 +179,6 @@ public class SncbProvider extends AbstractHafasProvider
} }
} }
private String normalizeLine(final String line)
{
if (line == null || line.length() == 0)
return null;
final Matcher m = P_NORMALIZE_LINE.matcher(line);
if (m.matches())
{
final String type = m.group(1);
final String number = m.group(2);
final char normalizedType = normalizeType(type);
if (normalizedType != 0)
return normalizedType + type + number;
throw new IllegalStateException("cannot normalize type " + type + " number " + number + " line " + line);
}
throw new IllegalStateException("cannot normalize line " + line);
}
@Override @Override
protected char normalizeType(final String type) protected char normalizeType(final String type)
{ {

View file

@ -17,7 +17,6 @@
package de.schildbach.pte; package de.schildbach.pte;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.assertTrue;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -29,49 +28,6 @@ import org.junit.Test;
*/ */
public class BahnProviderTest public class BahnProviderTest
{ {
@Test
public void coarseDeparture()
{
assertCoarseDepartures("" //
+ "<Journey fpTime=\"17:45\" fpDate=\"02.10.10\" \n" //
+ "delay=\"k.A\" \n" //
+ "platform =\"1\" \n" //
+ "targetLoc=\"Berlin Südkreuz (S)\" \n" //
+ "prod=\"S 41\" \n" //
+ "depStation=\"Berlin Sonnenallee\"\n" //
+ "delayReason=\" \"\n" //
+ "/>\n");
}
@Test
public void coarseDepartureWithoutTrailingNewLine()
{
assertCoarseDepartures("" //
+ "<Journey fpTime=\"17:45\" fpDate=\"02.10.10\" \n" //
+ "delay=\"k.A\" \n" //
+ "platform =\"1\" \n" //
+ "targetLoc=\"Berlin Südkreuz (S)\" \n" //
+ "prod=\"S 41\" \n" //
+ "depStation=\"Berlin Sonnenallee\"\n" //
+ "delayReason=\" \"\n" //
+ "/>");
}
@Test
public void coarseDepartureWithInvalidClosingBracket()
{
assertCoarseDepartures("" //
+ "<Journey fpTime=\"17:45\" fpDate=\"02.10.10\" \n" //
+ "delay=\"k.A\" \n" //
+ "platform =\"1\" \n" //
+ "targetLoc=\"Berlin Südkreuz (S)\" \n" //
+ "prod=\"S 41\" \n" //
+ "dir=\"Ringbahn ->\"\n" //
+ "depStation=\"Berlin Sonnenallee\"\n" //
+ "delayReason=\" \"\n" //
+ "/>\n");
}
@Test @Test
public void connectionUebergang() public void connectionUebergang()
{ {
@ -82,21 +38,6 @@ public class BahnProviderTest
+ "<span class=\"bold\">Berlin-Lichtenberg</span><br />\n"); + "<span class=\"bold\">Berlin-Lichtenberg</span><br />\n");
} }
@Test
public void newDepartureWithMessage()
{
final Matcher m = assertFineDepartures("" //
+ "fpTime=\"21:10\" fpDate=\"01.10.10\" \n" //
+ "delay=\"cancel\" \n" //
+ "platform =\"1\" \n" //
+ "targetLoc=\"Magdeburg Hbf\" \n" //
+ "prod=\"RE 38090\" \n" //
+ "delayReason=\" Notarzteinsatz am Gleis\"\n");
assertNotNull(m.group(4)); // position
assertNotNull(m.group(9)); // message
}
private void assertFineConnectionDetails(final String s) private void assertFineConnectionDetails(final String s)
{ {
Matcher m = BahnProvider.P_CONNECTION_DETAILS_FINE.matcher(s); Matcher m = BahnProvider.P_CONNECTION_DETAILS_FINE.matcher(s);
@ -104,28 +45,4 @@ public class BahnProviderTest
// ParserUtils.printGroups(m); // ParserUtils.printGroups(m);
} }
private Matcher assertCoarseDepartures(final String s)
{
Matcher m = BahnProvider.P_DEPARTURES_COARSE.matcher(s);
assertTrue(m.find());
assertFineDepartures(m.group(1));
return m;
}
private Matcher assertFineDepartures(final String s)
{
Matcher m = BahnProvider.P_DEPARTURES_FINE.matcher(s);
assertTrue(m.matches());
// ParserUtils.printGroups(m);
assertNotNull(m.group(1)); // time
assertNotNull(m.group(2)); // date
assertNotNull(m.group(6)); // destination
assertNotNull(m.group(7)); // line
return m;
}
} }

View file

@ -0,0 +1,67 @@
/*
* Copyright 2010, 2011 the original author or authors.
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.schildbach.pte.live;
import java.util.List;
import org.junit.Test;
import de.schildbach.pte.DsbProvider;
import de.schildbach.pte.dto.Location;
import de.schildbach.pte.dto.NearbyStationsResult;
import de.schildbach.pte.dto.QueryDeparturesResult;
/**
* @author Andreas Schildbach
*/
public class DsbProviderLiveTest
{
private final DsbProvider provider = new DsbProvider();
@Test
public void autocomplete() throws Exception
{
final List<Location> autocompletes = provider.autocompleteStations("Airport");
list(autocompletes);
}
private void list(final List<Location> autocompletes)
{
System.out.print(autocompletes.size() + " ");
for (final Location autocomplete : autocompletes)
System.out.print(autocomplete.toDebugString() + " ");
System.out.println();
}
@Test
public void nearbyStation() throws Exception
{
final NearbyStationsResult result = provider.nearbyStations("8600858", 0, 0, 0, 0);
System.out.println(result.stations.size() + " " + result.stations);
}
@Test
public void queryDepartures() throws Exception
{
final QueryDeparturesResult result = provider.queryDepartures("8600858", 0, false);
System.out.println(result.stationDepartures);
}
}