diff --git a/src/de/schildbach/pte/AbstractHafasProvider.java b/src/de/schildbach/pte/AbstractHafasProvider.java
index 8472e51c..95c2d356 100644
--- a/src/de/schildbach/pte/AbstractHafasProvider.java
+++ b/src/de/schildbach/pte/AbstractHafasProvider.java
@@ -20,7 +20,11 @@ package de.schildbach.pte;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketTimeoutException;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -31,9 +35,12 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
+import de.schildbach.pte.dto.Connection;
+import de.schildbach.pte.dto.GetConnectionDetailsResult;
import de.schildbach.pte.dto.Location;
import de.schildbach.pte.dto.LocationType;
import de.schildbach.pte.dto.NearbyStationsResult;
+import de.schildbach.pte.dto.QueryConnectionsResult;
import de.schildbach.pte.dto.Station;
import de.schildbach.pte.util.Color;
import de.schildbach.pte.util.ParserUtils;
@@ -46,29 +53,62 @@ public abstract class AbstractHafasProvider implements NetworkProvider
{
private static final String DEFAULT_ENCODING = "ISO-8859-1";
- private final String autocompleteUri;
- private final String prod;
+ private final String apiUri;
+ private static final String prod = "hafas";
private final String accessId;
- public AbstractHafasProvider(final String autocompleteUri, final String prod, final String accessId)
+ public AbstractHafasProvider(final String apiUri, final String accessId)
{
- this.autocompleteUri = autocompleteUri;
- this.prod = prod;
+ this.apiUri = apiUri;
this.accessId = accessId;
}
+ private final String wrap(final String request)
+ {
+ return "" //
+ + "" //
+ + request //
+ + "";
+ }
+
+ private static final Location parseLocation(final XmlPullParser pp)
+ {
+ final String type = pp.getName();
+ if ("Station".equals(type))
+ {
+ final String name = pp.getAttributeValue(null, "name").trim();
+ final int id = Integer.parseInt(pp.getAttributeValue(null, "externalStationNr"));
+ final int x = Integer.parseInt(pp.getAttributeValue(null, "x"));
+ final int y = Integer.parseInt(pp.getAttributeValue(null, "y"));
+ return new Location(LocationType.STATION, id, y, x, name);
+ }
+ throw new IllegalStateException("cannot handle: " + type);
+ }
+
+ private static final Location parsePoi(final XmlPullParser pp)
+ {
+ final String type = pp.getName();
+ if ("Poi".equals(type))
+ {
+ String name = pp.getAttributeValue(null, "name").trim();
+ if (name.equals("unknown"))
+ name = null;
+ final int x = Integer.parseInt(pp.getAttributeValue(null, "x"));
+ final int y = Integer.parseInt(pp.getAttributeValue(null, "y"));
+ return new Location(LocationType.POI, 0, y, x, name);
+ }
+ throw new IllegalStateException("cannot handle: " + type);
+ }
+
public List autocompleteStations(final CharSequence constraint) throws IOException
{
- final String request = "" //
- + "" //
- + "" //
- + "" //
- + "";
+ final String request = "" //
+ + "";
InputStream is = null;
try
{
- is = ParserUtils.scrapeInputStream(autocompleteUri, request);
+ is = ParserUtils.scrapeInputStream(apiUri, wrap(request));
final List results = new ArrayList();
@@ -85,32 +125,25 @@ public abstract class AbstractHafasProvider implements NetworkProvider
while (XmlPullUtil.test(pp, "Station"))
{
- final String name = pp.getAttributeValue(null, "name");
- final int id = Integer.parseInt(pp.getAttributeValue(null, "externalStationNr"));
- final int x = Integer.parseInt(pp.getAttributeValue(null, "x"));
- final int y = Integer.parseInt(pp.getAttributeValue(null, "y"));
- results.add(new Location(LocationType.STATION, id, y, x, name));
+ results.add(parseLocation(pp));
- XmlPullUtil.skipTree(pp);
+ XmlPullUtil.next(pp);
}
XmlPullUtil.exit(pp);
- XmlPullUtil.require(pp, "LocValRes");
- XmlPullUtil.requireAttr(pp, "id", "poi");
- XmlPullUtil.enter(pp);
-
- while (XmlPullUtil.test(pp, "Poi"))
- {
- final String name = pp.getAttributeValue(null, "name");
- final int x = Integer.parseInt(pp.getAttributeValue(null, "x"));
- final int y = Integer.parseInt(pp.getAttributeValue(null, "y"));
- results.add(new Location(LocationType.POI, 0, y, x, name));
-
- XmlPullUtil.skipTree(pp);
- }
-
- XmlPullUtil.exit(pp);
+ // XmlPullUtil.require(pp, "LocValRes");
+ // XmlPullUtil.requireAttr(pp, "id", "poi");
+ // XmlPullUtil.enter(pp);
+ //
+ // while (XmlPullUtil.test(pp, "Poi"))
+ // {
+ // results.add(parsePoi(pp));
+ //
+ // XmlPullUtil.next(pp);
+ // }
+ //
+ // XmlPullUtil.exit(pp);
return results;
}
@@ -129,6 +162,371 @@ public abstract class AbstractHafasProvider implements NetworkProvider
}
}
+ public QueryConnectionsResult queryConnections(Location from, Location via, Location to, final Date date, final boolean dep,
+ final String products, final WalkSpeed walkSpeed) throws IOException
+ {
+ if (from.type == LocationType.ANY)
+ {
+ final List autocompletes = autocompleteStations(from.name);
+ if (autocompletes.isEmpty())
+ return new QueryConnectionsResult(QueryConnectionsResult.Status.NO_CONNECTIONS); // TODO
+ if (autocompletes.size() > 1)
+ return new QueryConnectionsResult(autocompletes, null, null);
+ from = autocompletes.get(0);
+ }
+
+ if (via != null && via.type == LocationType.ANY)
+ {
+ final List autocompletes = autocompleteStations(via.name);
+ if (autocompletes.isEmpty())
+ return new QueryConnectionsResult(QueryConnectionsResult.Status.NO_CONNECTIONS); // TODO
+ if (autocompletes.size() > 1)
+ return new QueryConnectionsResult(null, autocompletes, null);
+ via = autocompletes.get(0);
+ }
+
+ if (to.type == LocationType.ANY)
+ {
+ final List autocompletes = autocompleteStations(to.name);
+ if (autocompletes.isEmpty())
+ return new QueryConnectionsResult(QueryConnectionsResult.Status.NO_CONNECTIONS); // TODO
+ if (autocompletes.size() > 1)
+ return new QueryConnectionsResult(null, null, autocompletes);
+ to = autocompletes.get(0);
+ }
+
+ final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd");
+ final DateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm");
+
+ final String request = "" //
+ + "" + location(from) + "" //
+ + (via != null ? "" + location(via) + "" : "") //
+ + "" + location(to) + "" //
+ + "" //
+ + "" //
+ + "";
+
+ // System.out.println(request);
+ // System.out.println(ParserUtils.scrape(apiUri, true, wrap(request), null, false));
+
+ InputStream is = null;
+ try
+ {
+ is = ParserUtils.scrapeInputStream(apiUri, wrap(request));
+
+ final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
+ final XmlPullParser pp = factory.newPullParser();
+ pp.setInput(is, DEFAULT_ENCODING);
+
+ XmlPullUtil.jump(pp, "ConRes");
+ XmlPullUtil.enter(pp);
+ if (pp.getName().equals("Err"))
+ {
+ final String code = XmlPullUtil.attr(pp, "code");
+ if (code.equals("K9380"))
+ return QueryConnectionsResult.TOO_CLOSE;
+ if (code.equals("K9220")) // Nearby to the given address stations could not be found
+ return QueryConnectionsResult.NO_CONNECTIONS;
+ throw new IllegalStateException("error " + code + " " + XmlPullUtil.attr(pp, "text"));
+ }
+
+ XmlPullUtil.require(pp, "ConResCtxt");
+ final String sessionId = XmlPullUtil.text(pp);
+ XmlPullUtil.require(pp, "ConnectionList");
+ XmlPullUtil.enter(pp);
+
+ final List connections = new ArrayList();
+
+ while (XmlPullUtil.test(pp, "Connection"))
+ {
+ final String id = XmlPullUtil.attr(pp, "id");
+
+ XmlPullUtil.enter(pp);
+ while (pp.getName().equals("RtStateList"))
+ XmlPullUtil.next(pp);
+ XmlPullUtil.require(pp, "Overview");
+ XmlPullUtil.enter(pp);
+ XmlPullUtil.require(pp, "Date");
+ final Date currentDate = DATE_FORMAT.parse(XmlPullUtil.text(pp));
+ XmlPullUtil.exit(pp);
+ XmlPullUtil.require(pp, "ConSectionList");
+ XmlPullUtil.enter(pp);
+
+ final List parts = new ArrayList(4);
+ Date firstDepartureTime = null;
+ Date lastArrivalTime = null;
+
+ while (XmlPullUtil.test(pp, "ConSection"))
+ {
+ XmlPullUtil.enter(pp);
+
+ // departure
+ XmlPullUtil.require(pp, "Departure");
+ XmlPullUtil.enter(pp);
+ XmlPullUtil.require(pp, "BasicStop");
+ XmlPullUtil.enter(pp);
+ while (pp.getName().equals("StAttrList"))
+ XmlPullUtil.next(pp);
+ Location departure;
+ if (pp.getName().equals("Station"))
+ departure = parseLocation(pp);
+ else if (pp.getName().equals("Poi"))
+ departure = parsePoi(pp);
+ else
+ throw new IllegalStateException("cannot parse: " + pp.getName());
+ XmlPullUtil.next(pp);
+ XmlPullUtil.require(pp, "Dep");
+ XmlPullUtil.enter(pp);
+ XmlPullUtil.require(pp, "Time");
+ final Date departureTime = ParserUtils.joinDateTime(currentDate, TIME_FORMAT.parse(XmlPullUtil.text(pp).substring(3, 8)));
+ XmlPullUtil.require(pp, "Platform");
+ XmlPullUtil.enter(pp);
+ XmlPullUtil.require(pp, "Text");
+ String departurePos = XmlPullUtil.text(pp).trim();
+ if (departurePos.length() == 0)
+ departurePos = null;
+ XmlPullUtil.exit(pp);
+
+ XmlPullUtil.exit(pp);
+
+ XmlPullUtil.exit(pp);
+ XmlPullUtil.exit(pp);
+
+ // journey
+ String line = null;
+ String direction = null;
+ int min = 0;
+
+ final String tag = pp.getName();
+ if (tag.equals("Journey"))
+ {
+ XmlPullUtil.enter(pp);
+ while (pp.getName().equals("JHandle"))
+ XmlPullUtil.next(pp);
+ XmlPullUtil.require(pp, "JourneyAttributeList");
+ XmlPullUtil.enter(pp);
+ String name = null;
+ String category = null;
+ while (XmlPullUtil.test(pp, "JourneyAttribute"))
+ {
+ XmlPullUtil.enter(pp);
+ XmlPullUtil.require(pp, "Attribute");
+ final String attrName = XmlPullUtil.attr(pp, "type");
+ XmlPullUtil.enter(pp);
+ final String attrValue = parseAttributeVariant(pp, "NORMAL");
+ XmlPullUtil.exit(pp);
+ XmlPullUtil.exit(pp);
+
+ if ("NAME".equals(attrName))
+ name = attrValue;
+ else if ("CATEGORY".equals(attrName))
+ category = attrValue;
+ else if ("DIRECTION".equals(attrName))
+ direction = attrValue;
+ }
+ XmlPullUtil.exit(pp);
+ XmlPullUtil.exit(pp);
+
+ line = _normalizeLine(category, name);
+ }
+ else if (tag.equals("Walk") || tag.equals("Transfer"))
+ {
+ XmlPullUtil.enter(pp);
+ XmlPullUtil.require(pp, "Duration");
+ XmlPullUtil.enter(pp);
+ XmlPullUtil.require(pp, "Time");
+ min = parseDuration(XmlPullUtil.text(pp).substring(3, 8));
+ XmlPullUtil.exit(pp);
+ XmlPullUtil.exit(pp);
+ }
+ else
+ {
+ throw new IllegalStateException("cannot handle: " + pp.getName());
+ }
+
+ // arrival
+ XmlPullUtil.require(pp, "Arrival");
+ XmlPullUtil.enter(pp);
+ XmlPullUtil.require(pp, "BasicStop");
+ XmlPullUtil.enter(pp);
+ while (pp.getName().equals("StAttrList"))
+ XmlPullUtil.next(pp);
+ Location arrival;
+ if (pp.getName().equals("Station"))
+ arrival = parseLocation(pp);
+ else if (pp.getName().equals("Poi"))
+ arrival = parsePoi(pp);
+ else
+ throw new IllegalStateException("cannot parse: " + pp.getName());
+ XmlPullUtil.next(pp);
+ XmlPullUtil.require(pp, "Arr");
+ XmlPullUtil.enter(pp);
+ XmlPullUtil.require(pp, "Time");
+ final Date arrivalTime = ParserUtils.joinDateTime(currentDate, TIME_FORMAT.parse(XmlPullUtil.text(pp).substring(3, 8)));
+ XmlPullUtil.require(pp, "Platform");
+ XmlPullUtil.enter(pp);
+ XmlPullUtil.require(pp, "Text");
+ String arrivalPos = XmlPullUtil.text(pp).trim();
+ if (arrivalPos.length() == 0)
+ arrivalPos = null;
+ XmlPullUtil.exit(pp);
+
+ XmlPullUtil.exit(pp);
+
+ XmlPullUtil.exit(pp);
+ XmlPullUtil.exit(pp);
+
+ XmlPullUtil.exit(pp);
+
+ if (min == 0 || line != null)
+ {
+ parts.add(new Connection.Trip(line, lineColors(line), 0, direction, departureTime, departurePos, departure.id,
+ departure.name, arrivalTime, arrivalPos, arrival.id, arrival.name));
+ }
+ else
+ {
+ if (parts.size() > 0 && parts.get(parts.size() - 1) instanceof Connection.Footway)
+ {
+ final Connection.Footway lastFootway = (Connection.Footway) parts.remove(parts.size() - 1);
+ parts.add(new Connection.Footway(lastFootway.min + min, lastFootway.departureId, lastFootway.departure, arrival.id,
+ arrival.name));
+ }
+ else
+ {
+ parts.add(new Connection.Footway(min, departure.id, departure.name, arrival.id, arrival.name));
+ }
+ }
+
+ if (firstDepartureTime == null)
+ firstDepartureTime = departureTime;
+ lastArrivalTime = arrivalTime;
+ }
+
+ XmlPullUtil.exit(pp);
+
+ XmlPullUtil.exit(pp);
+
+ connections.add(new Connection(id, null, firstDepartureTime, lastArrivalTime, null, null, 0, null, 0, null, parts));
+ }
+
+ XmlPullUtil.exit(pp);
+
+ return new QueryConnectionsResult(null, from, via, to, null, null, connections);
+ }
+ catch (final XmlPullParserException x)
+ {
+ throw new RuntimeException(x);
+ }
+ catch (final SocketTimeoutException x)
+ {
+ throw new RuntimeException(x);
+ }
+ catch (final ParseException x)
+ {
+ throw new RuntimeException(x);
+ }
+ finally
+ {
+ if (is != null)
+ is.close();
+ }
+ }
+
+ private final String parseAttributeVariant(final XmlPullParser pp, final String type) throws XmlPullParserException, IOException
+ {
+ String value = null;
+
+ while (XmlPullUtil.test(pp, "AttributeVariant"))
+ {
+ if (type.equals(XmlPullUtil.attr(pp, "type")))
+ {
+ XmlPullUtil.enter(pp);
+ XmlPullUtil.require(pp, "Text");
+ value = XmlPullUtil.text(pp).trim();
+ XmlPullUtil.exit(pp);
+ }
+ else
+ {
+ XmlPullUtil.next(pp);
+ }
+ }
+
+ return value;
+ }
+
+ private static final Pattern P_DURATION = Pattern.compile("(\\d+):(\\d{2})");
+
+ private final int parseDuration(final String str)
+ {
+ final Matcher m = P_DURATION.matcher(str);
+ if (m.matches())
+ return Integer.parseInt(m.group(1)) * 60 + Integer.parseInt(m.group(2));
+ else
+ throw new IllegalArgumentException("cannot parse duration: " + str);
+ }
+
+ private final String location(final Location location)
+ {
+ if (location.type == LocationType.STATION && location.id != 0)
+ return "";
+ if (location.type == LocationType.POI && (location.lat != 0 || location.lon != 0))
+ return "";
+
+ throw new IllegalArgumentException("cannot handle: " + location.toDebugString());
+ }
+
+ private final String _normalizeLine(final String type, final String name)
+ {
+ final String normalizedType = type.split(" ", 2)[0];
+ final String normalizedName = normalizeWhitespace(name);
+
+ if ("THALYS".equals(normalizedType))
+ return "I" + normalizedName;
+ if ("IC".equals(normalizedType))
+ return "I" + normalizedName;
+ if ("EN".equals(normalizedType))
+ return "I" + normalizedName;
+ if ("OEC".equals(normalizedType))
+ return "I" + normalizedName;
+
+ if ("R".equals(normalizedType))
+ return "R" + normalizedName;
+ if ("RE".equals(normalizedType))
+ return "R" + normalizedName;
+ if ("IR".equals(normalizedType))
+ return "R" + normalizedName;
+
+ if ("Tramway".equals(normalizedType))
+ return "T" + normalizedName;
+
+ if ("BUS".equals(normalizedType))
+ return "B" + normalizedName;
+
+ if ("L".equals(normalizedType))
+ return "?" + normalizedName;
+ if ("NZ".equals(normalizedType))
+ return "?" + normalizedName;
+
+ throw new IllegalStateException("cannot normalize type '" + normalizedType + "' (" + type + ") name '" + normalizedName + "'");
+ }
+
+ private final static Pattern P_WHITESPACE = Pattern.compile("\\s+");
+
+ private final String normalizeWhitespace(final String str)
+ {
+ return P_WHITESPACE.matcher(str).replaceAll("");
+ }
+
+ public QueryConnectionsResult queryMoreConnections(String uri) throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public GetConnectionDetailsResult getConnectionDetails(String connectionUri) throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
private final static Pattern P_NEARBY_COARSE = Pattern.compile("(.*?)
", Pattern.DOTALL);
private final static Pattern P_NEARBY_FINE_COORDS = Pattern
.compile("&REQMapRoute0\\.Location0\\.X=(-?\\d+)&REQMapRoute0\\.Location0\\.Y=(-?\\d+)&");
@@ -200,7 +598,7 @@ public abstract class AbstractHafasProvider implements NetworkProvider
if (normalizedType != 0)
return normalizedType + strippedLine;
- throw new IllegalStateException("cannot normalize type " + type + " line " + line);
+ throw new IllegalStateException("cannot normalize type '" + type + "' line '" + line + "'");
}
protected abstract char normalizeType(String type);
diff --git a/src/de/schildbach/pte/NasaProvider.java b/src/de/schildbach/pte/NasaProvider.java
index cd3ff13f..a9d392ac 100644
--- a/src/de/schildbach/pte/NasaProvider.java
+++ b/src/de/schildbach/pte/NasaProvider.java
@@ -48,7 +48,7 @@ public class NasaProvider extends AbstractHafasProvider
public NasaProvider()
{
- super(null, null, null);
+ super(null, null);
}
public boolean hasCapabilities(final Capability... capabilities)
@@ -250,17 +250,20 @@ public class NasaProvider extends AbstractHafasProvider
return 0;
}
+ @Override
public QueryConnectionsResult queryConnections(final Location from, final Location via, final Location to, final Date date, final boolean dep,
final String products, final WalkSpeed walkSpeed) throws IOException
{
throw new UnsupportedOperationException();
}
+ @Override
public QueryConnectionsResult queryMoreConnections(String uri) throws IOException
{
throw new UnsupportedOperationException();
}
+ @Override
public GetConnectionDetailsResult getConnectionDetails(String connectionUri) throws IOException
{
throw new UnsupportedOperationException();
diff --git a/src/de/schildbach/pte/OebbProvider.java b/src/de/schildbach/pte/OebbProvider.java
index 79f49b18..0c65d036 100644
--- a/src/de/schildbach/pte/OebbProvider.java
+++ b/src/de/schildbach/pte/OebbProvider.java
@@ -50,7 +50,7 @@ public class OebbProvider extends AbstractHafasProvider
public OebbProvider()
{
- super(null, null, null);
+ super(null, null);
}
public boolean hasCapabilities(final Capability... capabilities)
@@ -233,6 +233,7 @@ public class OebbProvider extends AbstractHafasProvider
"]*>\n(.*?)", Pattern.DOTALL);
private static final Pattern P_ADDRESSES = Pattern.compile("", Pattern.DOTALL);
+ @Override
public QueryConnectionsResult queryConnections(final Location from, final Location via, final Location to, final Date date, final boolean dep,
final String products, final WalkSpeed walkSpeed) throws IOException
{
@@ -293,6 +294,7 @@ public class OebbProvider extends AbstractHafasProvider
return queryConnections(baseUri, page);
}
+ @Override
public QueryConnectionsResult queryMoreConnections(final String uri) throws IOException
{
final CharSequence page = ParserUtils.scrape(uri, false, null, null, true);
@@ -483,6 +485,7 @@ public class OebbProvider extends AbstractHafasProvider
}
}
+ @Override
public GetConnectionDetailsResult getConnectionDetails(final String connectionUri) throws IOException
{
throw new UnsupportedOperationException();
diff --git a/src/de/schildbach/pte/RmvProvider.java b/src/de/schildbach/pte/RmvProvider.java
index 70584256..3c12c59e 100644
--- a/src/de/schildbach/pte/RmvProvider.java
+++ b/src/de/schildbach/pte/RmvProvider.java
@@ -53,7 +53,7 @@ public class RmvProvider extends AbstractHafasProvider
public RmvProvider()
{
- super(null, null, null);
+ super(null, null);
}
public boolean hasCapabilities(final Capability... capabilities)
@@ -184,6 +184,7 @@ public class RmvProvider extends AbstractHafasProvider
private static final Pattern P_CHECK_CONNECTIONS_ERROR = Pattern.compile(
"(mehrfach vorhanden oder identisch)|(keine Verbindung gefunden werden)|(derzeit nur Auskünfte vom)", Pattern.CASE_INSENSITIVE);
+ @Override
public QueryConnectionsResult queryConnections(final Location from, final Location via, final Location to, final Date date, final boolean dep,
final String products, final WalkSpeed walkSpeed) throws IOException
{
@@ -249,6 +250,7 @@ public class RmvProvider extends AbstractHafasProvider
+ "(?: (.+?))?" //
, Pattern.DOTALL);
+ @Override
public QueryConnectionsResult queryMoreConnections(final String uri) throws IOException
{
final CharSequence page = ParserUtils.scrape(uri);
@@ -333,6 +335,7 @@ public class RmvProvider extends AbstractHafasProvider
+ "- (.*?)" // arrival
, Pattern.DOTALL);
+ @Override
public GetConnectionDetailsResult getConnectionDetails(final String uri) throws IOException
{
final CharSequence page = ParserUtils.scrape(uri);
diff --git a/src/de/schildbach/pte/SbbProvider.java b/src/de/schildbach/pte/SbbProvider.java
index c84d5102..850abe5f 100644
--- a/src/de/schildbach/pte/SbbProvider.java
+++ b/src/de/schildbach/pte/SbbProvider.java
@@ -45,12 +45,13 @@ public class SbbProvider extends AbstractHafasProvider
{
public static final String NETWORK_ID = "fahrplan.sbb.ch";
private static final String API_BASE = "http://fahrplan.sbb.ch/bin/";
+ private static final String API_URI = "http://fahrplan.sbb.ch/bin/extxml.exe";
private static final long PARSER_DAY_ROLLOVER_THRESHOLD_MS = 12 * 60 * 60 * 1000;
- public SbbProvider()
+ public SbbProvider(final String accessId)
{
- super("http://fahrplan.sbb.ch/bin/extxml.exe", "iPhone3.1", "MJXZ841ZfsmqqmSymWhBPy5dMNoqoGsHInHbWJQ5PTUZOJ1rLTkn8vVZOZDFfSe");
+ super(API_URI, accessId);
}
public boolean hasCapabilities(final Capability... capabilities)
@@ -131,6 +132,7 @@ public class SbbProvider extends AbstractHafasProvider
private static final Pattern P_CHECK_CONNECTIONS_ERROR = Pattern
.compile("(mehrfach vorhanden oder identisch)|(keine Verbindung gefunden werden)|(liegt nach dem Ende der Fahrplanperiode|liegt vor Beginn der Fahrplanperiode)");
+ @Override
public QueryConnectionsResult queryConnections(final Location from, final Location via, final Location to, final Date date, final boolean dep,
final String products, final WalkSpeed walkSpeed) throws IOException
{
@@ -185,6 +187,7 @@ public class SbbProvider extends AbstractHafasProvider
return queryConnections(uri, page);
}
+ @Override
public QueryConnectionsResult queryMoreConnections(final String uri) throws IOException
{
final CharSequence page = ParserUtils.scrape(uri);
@@ -293,6 +296,7 @@ public class SbbProvider extends AbstractHafasProvider
+ "- ([^<]*) -\n" // destination
, Pattern.DOTALL);
+ @Override
public GetConnectionDetailsResult getConnectionDetails(final String uri) throws IOException
{
final CharSequence page = ParserUtils.scrape(uri);
diff --git a/src/de/schildbach/pte/SncbProvider.java b/src/de/schildbach/pte/SncbProvider.java
index 3d7b1123..74d51398 100644
--- a/src/de/schildbach/pte/SncbProvider.java
+++ b/src/de/schildbach/pte/SncbProvider.java
@@ -27,9 +27,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import de.schildbach.pte.dto.Departure;
-import de.schildbach.pte.dto.GetConnectionDetailsResult;
-import de.schildbach.pte.dto.Location;
-import de.schildbach.pte.dto.QueryConnectionsResult;
import de.schildbach.pte.dto.QueryDeparturesResult;
import de.schildbach.pte.dto.QueryDeparturesResult.Status;
import de.schildbach.pte.util.ParserUtils;
@@ -43,17 +40,17 @@ public class SncbProvider extends AbstractHafasProvider
private static final long PARSER_DAY_ROLLOVER_THRESHOLD_MS = 12 * 60 * 60 * 1000;
- private static final String AUTOCOMPLETE_URI = "http://hari.b-rail.be/Hafas/bin/extxml.exe";
+ private static final String API_URI = "http://hari.b-rail.be/Hafas/bin/extxml.exe";
public SncbProvider()
{
- super(AUTOCOMPLETE_URI, "irail", null);
+ super(API_URI, null);
}
public boolean hasCapabilities(final Capability... capabilities)
{
for (final Capability capability : capabilities)
- if (capability == Capability.DEPARTURES)
+ if (capability == Capability.DEPARTURES || capability == Capability.CONNECTIONS)
return true;
return false;
@@ -67,22 +64,6 @@ public class SncbProvider extends AbstractHafasProvider
return String.format(NEARBY_URI, stationId);
}
- 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
- {
- throw new UnsupportedOperationException();
- }
-
- public QueryConnectionsResult queryMoreConnections(final String uri) throws IOException
- {
- throw new UnsupportedOperationException();
- }
-
- public GetConnectionDetailsResult getConnectionDetails(final String connectionUri) throws IOException
- {
- throw new UnsupportedOperationException();
- }
-
public String departuresQueryUri(final String stationId, final int maxDepartures)
{
final StringBuilder uri = new StringBuilder();
diff --git a/src/de/schildbach/pte/VgsProvider.java b/src/de/schildbach/pte/VgsProvider.java
index d6a7053a..6cd6a3ee 100644
--- a/src/de/schildbach/pte/VgsProvider.java
+++ b/src/de/schildbach/pte/VgsProvider.java
@@ -48,7 +48,7 @@ public class VgsProvider extends AbstractHafasProvider
public VgsProvider()
{
- super(null, null, null);
+ super(null, null);
}
public boolean hasCapabilities(final Capability... capabilities)
@@ -247,17 +247,20 @@ public class VgsProvider extends AbstractHafasProvider
return 0;
}
+ @Override
public QueryConnectionsResult queryConnections(final Location from, final Location via, final Location to, final Date date, final boolean dep,
final String products, final WalkSpeed walkSpeed) throws IOException
{
throw new UnsupportedOperationException();
}
+ @Override
public QueryConnectionsResult queryMoreConnections(String uri) throws IOException
{
throw new UnsupportedOperationException();
}
+ @Override
public GetConnectionDetailsResult getConnectionDetails(String connectionUri) throws IOException
{
throw new UnsupportedOperationException();
diff --git a/src/de/schildbach/pte/util/XmlPullUtil.java b/src/de/schildbach/pte/util/XmlPullUtil.java
index 9a879047..784c0175 100644
--- a/src/de/schildbach/pte/util/XmlPullUtil.java
+++ b/src/de/schildbach/pte/util/XmlPullUtil.java
@@ -32,7 +32,8 @@ public final class XmlPullUtil
/**
* enters current tag
- * @throws IOException
+ *
+ * @throws IOException
*/
public static void enter(final XmlPullParser pp) throws XmlPullParserException, IOException
{
@@ -40,22 +41,34 @@ public final class XmlPullUtil
throw new IllegalStateException("expecting start tag to enter");
if (pp.isEmptyElementTag())
throw new IllegalStateException("cannot enter empty tag");
+
pp.next();
}
-
+
public static void exit(final XmlPullParser pp) throws XmlPullParserException, IOException
{
+ while (pp.getEventType() != XmlPullParser.END_TAG)
+ {
+ if (pp.getEventType() == XmlPullParser.START_TAG)
+ next(pp);
+ else if (pp.getEventType() == XmlPullParser.TEXT)
+ pp.next();
+ else
+ throw new IllegalStateException();
+ }
+
if (pp.getEventType() != XmlPullParser.END_TAG)
throw new IllegalStateException("expecting end tag to exit");
+
pp.next();
}
-
+
public static boolean test(final XmlPullParser pp, final String tagName) throws XmlPullParserException
{
return pp.getEventType() == XmlPullParser.START_TAG && pp.getName().equals(tagName);
}
-
- public static void skipTree(final XmlPullParser pp) throws XmlPullParserException, IOException
+
+ public static void next(final XmlPullParser pp) throws XmlPullParserException, IOException
{
skipSubTree(pp);
pp.next();
@@ -82,6 +95,22 @@ public final class XmlPullUtil
throw new IllegalStateException("cannot find " + attrName + "=\"" + requiredValue + "\" />");
}
+ public static String text(final XmlPullParser pp) throws XmlPullParserException, IOException
+ {
+ if (pp.getEventType() != XmlPullParser.START_TAG || pp.isEmptyElementTag())
+ throw new IllegalStateException("expecting start tag to get text from");
+
+ enter(pp);
+
+ String text = "";
+ if (pp.getEventType() == XmlPullParser.TEXT)
+ text = pp.getText();
+
+ exit(pp);
+
+ return text;
+ }
+
/**
* Return value of attribute with given name and no namespace.
*/
diff --git a/test/de/schildbach/pte/live/SbbProviderLiveTest.java b/test/de/schildbach/pte/live/SbbProviderLiveTest.java
index 0cec0a35..5aec87e7 100644
--- a/test/de/schildbach/pte/live/SbbProviderLiveTest.java
+++ b/test/de/schildbach/pte/live/SbbProviderLiveTest.java
@@ -36,7 +36,7 @@ import de.schildbach.pte.dto.QueryDeparturesResult;
*/
public class SbbProviderLiveTest
{
- private SbbProvider provider = new SbbProvider();
+ private SbbProvider provider = new SbbProvider(Secrets.SBB_ACCESS_ID);
private static final String ALL_PRODUCTS = "IRSUTBFC";
@Test
@@ -74,8 +74,8 @@ public class SbbProviderLiveTest
@Test
public void shortConnection() throws Exception
{
- final QueryConnectionsResult result = provider.queryConnections(new Location(LocationType.ANY, 0, 0, 0, "Zürich!"), null, new Location(
- LocationType.ANY, 0, 0, 0, "Bern"), new Date(), true, ALL_PRODUCTS, WalkSpeed.NORMAL);
+ final QueryConnectionsResult result = provider.queryConnections(new Location(LocationType.STATION, 8503000, 0, 0, "Zürich HB"), null,
+ new Location(LocationType.STATION, 8507785, 0, 0, "Bern, Hauptbahnhof"), new Date(), true, ALL_PRODUCTS, WalkSpeed.NORMAL);
System.out.println(result);
final QueryConnectionsResult moreResult = provider.queryMoreConnections(result.linkLater);
System.out.println(moreResult);
diff --git a/test/de/schildbach/pte/live/SncbProviderLiveTest.java b/test/de/schildbach/pte/live/SncbProviderLiveTest.java
index 73a907ac..b18cdf53 100644
--- a/test/de/schildbach/pte/live/SncbProviderLiveTest.java
+++ b/test/de/schildbach/pte/live/SncbProviderLiveTest.java
@@ -16,13 +16,17 @@
*/
package de.schildbach.pte.live;
+import java.util.Date;
import java.util.List;
import org.junit.Test;
import de.schildbach.pte.SncbProvider;
+import de.schildbach.pte.NetworkProvider.WalkSpeed;
import de.schildbach.pte.dto.Location;
+import de.schildbach.pte.dto.LocationType;
import de.schildbach.pte.dto.NearbyStationsResult;
+import de.schildbach.pte.dto.QueryConnectionsResult;
/**
* @author Andreas Schildbach
@@ -47,6 +51,24 @@ public class SncbProviderLiveTest
System.out.println();
}
+ @Test
+ public void shortConnection() throws Exception
+ {
+ final QueryConnectionsResult result = provider.queryConnections(new Location(LocationType.STATION, 100024, 0, 0, null), null, new Location(
+ LocationType.STATION, 100066, 0, 0, null), new Date(), true, null, WalkSpeed.FAST);
+
+ System.out.println(result.status + " " + result.connections);
+ }
+
+ @Test
+ public void longConnection() throws Exception
+ {
+ final QueryConnectionsResult result = provider.queryConnections(new Location(LocationType.STATION, 100024, 0, 0, null), null, new Location(
+ LocationType.STATION, 103624, 0, 0, null), new Date(), true, null, WalkSpeed.FAST);
+
+ System.out.println(result.status + " " + result.connections);
+ }
+
@Test
public void nearbyStation() throws Exception
{