use ID parameters for connection queries, rather than A and G

git-svn-id: https://public-transport-enabler.googlecode.com/svn/trunk@321 0924bc21-9374-b0fa-ee44-9ff1593b38f0
This commit is contained in:
andreas.schildbach 2010-10-24 17:44:05 +00:00
parent f3c0a54272
commit 5711f7ea3a
4 changed files with 65 additions and 117 deletions

View file

@ -547,7 +547,7 @@ public abstract class AbstractHafasProvider implements NetworkProvider
throw new IllegalArgumentException("cannot parse duration: " + str); 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) if (location.type == LocationType.STATION && location.id != 0)
return "<Station externalId=\"" + location.id + "\" />"; return "<Station externalId=\"" + location.id + "\" />";
@ -559,6 +559,34 @@ public abstract class AbstractHafasProvider implements NetworkProvider
throw new IllegalArgumentException("cannot handle: " + location.toDebugString()); 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 static final Pattern P_LINE_S = Pattern.compile("SN?\\d+");
private final String _normalizeLine(final String type, final String name, final String longCategory) private final String _normalizeLine(final String type, final String name, final String longCategory)

View file

@ -24,9 +24,7 @@ import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; 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.QueryConnectionsResult;
import de.schildbach.pte.dto.QueryDeparturesResult; import de.schildbach.pte.dto.QueryDeparturesResult;
import de.schildbach.pte.dto.Station; import de.schildbach.pte.dto.Station;
import de.schildbach.pte.util.Color;
import de.schildbach.pte.util.ParserUtils; import de.schildbach.pte.util.ParserUtils;
/** /**
* @author Andreas Schildbach * @author Andreas Schildbach
*/ */
public final class BahnProvider implements NetworkProvider public final class BahnProvider extends AbstractHafasProvider
{ {
public static final String NETWORK_ID = "mobile.bahn.de"; public static final String NETWORK_ID = "mobile.bahn.de";
private static final String API_BASE = "http://mobile.bahn.de/bin/mobil/"; 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; private static final long PARSER_DAY_ROLLOVER_THRESHOLD_MS = 12 * 60 * 60 * 1000;
public BahnProvider()
{
super(null, null);
}
public boolean hasCapabilities(final Capability... capabilities) public boolean hasCapabilities(final Capability... capabilities)
{ {
return true; return true;
@ -62,6 +64,7 @@ public final class BahnProvider implements NetworkProvider
Pattern.DOTALL); Pattern.DOTALL);
private static final Pattern P_MULTI_NAME = Pattern.compile("<option value=\".+?#(\\d+)\">(.+?)</option>", Pattern.DOTALL); private static final Pattern P_MULTI_NAME = Pattern.compile("<option value=\".+?#(\\d+)\">(.+?)</option>", Pattern.DOTALL);
@Override
public List<Location> autocompleteStations(final CharSequence constraint) throws IOException public List<Location> autocompleteStations(final CharSequence constraint) throws IOException
{ {
final CharSequence page = ParserUtils.scrape(NAME_URL + ParserUtils.urlEncode(constraint.toString())); 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 private final static Pattern P_NEARBY_STATIONS = Pattern
.compile("<a class=\"uLine\" href=\".+?!X=(\\d+)!Y=(\\d+)!id=(\\d+)!dist=(\\d+).*?\">(.+?)</a>"); .compile("<a class=\"uLine\" href=\".+?!X=(\\d+)!Y=(\\d+)!id=(\\d+)!dist=(\\d+).*?\">(.+?)</a>");
@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) public NearbyStationsResult nearbyStations(final String stationId, final int lat, final int lon, final int maxDistance, final int maxStations)
throws IOException throws IOException
{ {
@ -127,15 +137,10 @@ public final class BahnProvider implements NetworkProvider
uri.append(API_BASE).append("query.exe/dox"); uri.append(API_BASE).append("query.exe/dox");
uri.append("?REQ0HafasOptimize1=0:1"); uri.append("?REQ0HafasOptimize1=0:1");
uri.append("&REQ0JourneyStopsS0G=").append(ParserUtils.urlEncode(locationValue(from))); uri.append("&REQ0JourneyStopsS0ID=").append(ParserUtils.urlEncode(locationId(from)));
uri.append("&REQ0JourneyStopsS0A=").append(locationTypeValue(from));
if (via != null) if (via != null)
{ uri.append("&REQ0JourneyStops1.0ID=").append(ParserUtils.urlEncode(locationId(via)));
uri.append("&REQ0JourneyStops1.0G=").append(ParserUtils.urlEncode(locationValue(via))); uri.append("&REQ0JourneyStopsZ0ID=").append(ParserUtils.urlEncode(locationId(to)));
uri.append("&REQ0JourneyStops1.0A=").append(locationTypeValue(via));
}
uri.append("&REQ0JourneyStopsZ0G=").append(ParserUtils.urlEncode(locationValue(to)));
uri.append("&REQ0JourneyStopsZ0A=").append(locationTypeValue(to));
uri.append("&REQ0HafasSearchForw=").append(dep ? "1" : "0"); uri.append("&REQ0HafasSearchForw=").append(dep ? "1" : "0");
uri.append("&REQ0JourneyDate=").append(ParserUtils.urlEncode(DATE_FORMAT.format(date))); uri.append("&REQ0JourneyDate=").append(ParserUtils.urlEncode(DATE_FORMAT.format(date)));
uri.append("&REQ0JourneyTime=").append(ParserUtils.urlEncode(TIME_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(); 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( private static final Pattern P_PRE_ADDRESS = Pattern.compile(
"<select name=\"(REQ0JourneyStopsS0K|REQ0JourneyStopsZ0K|REQ0JourneyStops1\\.0K)\"[^>]*>(.*?)</select>", Pattern.DOTALL); "<select name=\"(REQ0JourneyStopsS0K|REQ0JourneyStopsZ0K|REQ0JourneyStops1\\.0K)\"[^>]*>(.*?)</select>", Pattern.DOTALL);
private static final Pattern P_ADDRESSES = Pattern.compile("<option[^>]*>\\s*(.*?)\\s*</option>", Pattern.DOTALL); private static final Pattern P_ADDRESSES = Pattern.compile("<option[^>]*>\\s*(.*?)\\s*</option>", Pattern.DOTALL);
private static final Pattern P_CHECK_CONNECTIONS_ERROR = Pattern 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&#252;nfte vom)"); .compile("(zu dicht beieinander|mehrfach vorhanden oder identisch)|(leider konnte zu Ihrer Anfrage keine Verbindung gefunden werden)|(derzeit nur Ausk&#252;nfte vom)");
@Override
public QueryConnectionsResult queryConnections(final Location from, final Location via, final Location to, final Date date, final boolean dep, 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 final String products, final WalkSpeed walkSpeed) throws IOException
{ {
@ -227,6 +213,7 @@ public final class BahnProvider implements NetworkProvider
return queryConnections(uri, page); return queryConnections(uri, page);
} }
@Override
public QueryConnectionsResult queryMoreConnections(final String uri) throws IOException public QueryConnectionsResult queryMoreConnections(final String uri) throws IOException
{ {
final CharSequence page = ParserUtils.scrape(uri); final CharSequence page = ParserUtils.scrape(uri);
@ -285,7 +272,7 @@ public final class BahnProvider implements NetworkProvider
else else
line = null; line = null;
final Connection connection = new Connection(AbstractHafasProvider.extractConnectionId(link), link, departureTime, arrivalTime, 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); connections.add(connection);
} }
else else
@ -325,6 +312,7 @@ public final class BahnProvider implements NetworkProvider
private static final Pattern P_CONNECTION_DETAILS_MESSAGES = Pattern 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&#228;ngerer Aufenthalt)|(&#228;quivalentem Bahnhof)|(Bahnhof wird mehrfach durchfahren)"); .compile("Dauer: \\d+:\\d+|(Anschlusszug nicht mehr rechtzeitig)|(Anschlusszug jedoch erreicht werden)|(nur teilweise dargestellt)|(L&#228;ngerer Aufenthalt)|(&#228;quivalentem Bahnhof)|(Bahnhof wird mehrfach durchfahren)");
@Override
public GetConnectionDetailsResult getConnectionDetails(final String uri) throws IOException public GetConnectionDetailsResult getConnectionDetails(final String uri) throws IOException
{ {
final CharSequence page = ParserUtils.scrape(uri); 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 departureDateTime = ParserUtils.joinDateTime(departureDate, departureTime);
final Date arrivalDateTime = ParserUtils.joinDateTime(arrivalDate, arrivalTime); 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); departurePosition, 0, departure, arrivalDateTime, arrivalPosition, 0, arrival);
parts.add(lastTrip); parts.add(lastTrip);
@ -506,8 +494,8 @@ public final class BahnProvider implements NetworkProvider
final String message = ParserUtils.resolveEntities(mDepFine.group(9)); 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, departures.add(new Departure(plannedTime, predictedTime, line, line != null ? lineColors(line) : null, null, position, 0,
0, destination, message)); destination, message));
} }
} }
else 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); 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_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 = Pattern.compile("([A-Za-zÄÖÜäöüßáàâéèêíìîóòôúùû]+)[\\s-]*(.*)");
private static final Pattern P_NORMALIZE_LINE_RUSSIA = Pattern.compile("(?:D\\s*)?(\\d{1,3}[A-Z]{2})"); 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); throw new IllegalStateException("cannot normalize line " + line);
} }
private static final Map<Character, int[]> LINES = new HashMap<Character, int[]>();
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));
}
} }

View file

@ -159,18 +159,10 @@ public class OebbProvider extends AbstractHafasProvider
uri.append("&start.x=0"); uri.append("&start.x=0");
uri.append("&start.y=0"); uri.append("&start.y=0");
uri.append("&start=Suchen"); uri.append("&start=Suchen");
uri.append("&REQ0JourneyStopsS0A=").append(locationTypeValue(from)); uri.append("&REQ0JourneyStopsS0ID=").append(ParserUtils.urlEncode(locationId(from)));
uri.append("&REQ0JourneyStopsS0G=").append(ParserUtils.urlEncode(locationValue(from)));
uri.append("&REQ0JourneyStopsS0ID="); // "tupel"?
if (via != null) if (via != null)
{ uri.append("&REQ0JourneyStops1.0ID=").append(ParserUtils.urlEncode(locationId(via)));
uri.append("&REQ0JourneyStops1.0A=").append(locationTypeValue(via)); uri.append("&REQ0JourneyStopsZ0ID=").append(ParserUtils.urlEncode(locationId(to)));
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("&REQ0JourneyDate=").append(ParserUtils.urlEncode(DATE_FORMAT.format(date))); 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("&wDayExt0=").append(ParserUtils.urlEncode("Mo|Di|Mi|Do|Fr|Sa|So"));
uri.append("&REQ0JourneyTime=").append(ParserUtils.urlEncode(TIME_FORMAT.format(date))); uri.append("&REQ0JourneyTime=").append(ParserUtils.urlEncode(TIME_FORMAT.format(date)));
@ -202,28 +194,6 @@ public class OebbProvider extends AbstractHafasProvider
return uri.toString(); 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 String QUERY_CONNECTIONS_FORM_URL = API_BASE + "query.exe/dn?";
private static final Pattern P_QUERY_CONNECTIONS_FORM_ACTION = Pattern private static final Pattern P_QUERY_CONNECTIONS_FORM_ACTION = Pattern
.compile("<form id=\"HFSQuery\" action=\"(http://fahrplan\\.oebb\\.at/bin/query\\.exe[^#]*)#"); .compile("<form id=\"HFSQuery\" action=\"(http://fahrplan\\.oebb\\.at/bin/query\\.exe[^#]*)#");

View file

@ -122,15 +122,10 @@ public class RmvProvider extends AbstractHafasProvider
uri.append("&REQ0HafasSearchForw=").append(dep ? "1" : "0"); uri.append("&REQ0HafasSearchForw=").append(dep ? "1" : "0");
uri.append("&REQ0JourneyDate=").append(ParserUtils.urlEncode(DATE_FORMAT.format(date))); uri.append("&REQ0JourneyDate=").append(ParserUtils.urlEncode(DATE_FORMAT.format(date)));
uri.append("&REQ0JourneyTime=").append(ParserUtils.urlEncode(TIME_FORMAT.format(date))); uri.append("&REQ0JourneyTime=").append(ParserUtils.urlEncode(TIME_FORMAT.format(date)));
uri.append("&REQ0JourneyStopsS0G=").append(ParserUtils.urlEncode(locationValue(from))); uri.append("&REQ0JourneyStopsS0ID=").append(ParserUtils.urlEncode(locationId(from)));
uri.append("&REQ0JourneyStopsS0A=").append(locationTypeValue(from));
uri.append("&REQ0JourneyStopsZ0G=").append(ParserUtils.urlEncode(locationValue(to)));
uri.append("&REQ0JourneyStopsZ0A=").append(locationTypeValue(to));
if (via != null) if (via != null)
{ uri.append("&REQ0JourneyStops1.0ID=").append(ParserUtils.urlEncode(locationId(via)));
uri.append("&REQ0JourneyStops1.0G=").append(ParserUtils.urlEncode(locationValue(via))); uri.append("&REQ0JourneyStopsZ0ID=").append(ParserUtils.urlEncode(locationId(to)));
uri.append("&REQ0JourneyStops1.0A=").append(locationTypeValue(via));
}
uri.append("&REQ0JourneyDep_Foot_speed=").append(WALKSPEED_MAP.get(walkSpeed)); uri.append("&REQ0JourneyDep_Foot_speed=").append(WALKSPEED_MAP.get(walkSpeed));
for (final char p : products.toCharArray()) for (final char p : products.toCharArray())
@ -157,26 +152,6 @@ public class RmvProvider extends AbstractHafasProvider
return uri.toString(); 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.ANY)
return 255;
throw new IllegalArgumentException(type.toString());
}
private static 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("(?:Geben Sie einen (Startort|Zielort) an.*?)?Bitte w&#228;hlen Sie aus der Liste", private static final Pattern P_PRE_ADDRESS = Pattern.compile("(?:Geben Sie einen (Startort|Zielort) an.*?)?Bitte w&#228;hlen Sie aus der Liste",
Pattern.DOTALL); Pattern.DOTALL);
private static final Pattern P_ADDRESSES = Pattern.compile( private static final Pattern P_ADDRESSES = Pattern.compile(