From 0a773096f0ce2bb58a3ea17d20c09f103d5a1519 Mon Sep 17 00:00:00 2001 From: "andreas.schildbach" Date: Fri, 15 Oct 2010 22:23:01 +0000 Subject: [PATCH] fixed parsing connections for Switzerland, ambiguous still missing git-svn-id: https://public-transport-enabler.googlecode.com/svn/trunk@293 0924bc21-9374-b0fa-ee44-9ff1593b38f0 --- .../schildbach/pte/AbstractHafasProvider.java | 11 + src/de/schildbach/pte/BahnProvider.java | 23 +- src/de/schildbach/pte/RmvProvider.java | 4 +- src/de/schildbach/pte/SbbProvider.java | 284 +++++++++--------- src/de/schildbach/pte/VbbProvider.java | 4 +- src/de/schildbach/pte/util/ParserUtils.java | 11 +- test/de/schildbach/pte/SbbProviderTest.java | 249 --------------- .../pte/live/SbbProviderLiveTest.java | 7 + 8 files changed, 179 insertions(+), 414 deletions(-) delete mode 100644 test/de/schildbach/pte/SbbProviderTest.java diff --git a/src/de/schildbach/pte/AbstractHafasProvider.java b/src/de/schildbach/pte/AbstractHafasProvider.java index 7a40ed3e..acc5a85a 100644 --- a/src/de/schildbach/pte/AbstractHafasProvider.java +++ b/src/de/schildbach/pte/AbstractHafasProvider.java @@ -214,6 +214,17 @@ public abstract class AbstractHafasProvider implements NetworkProvider return 0; } + private static final Pattern P_CONNECTION_ID = Pattern.compile("co=(C\\d+-\\d+)&"); + + protected static String extractConnectionId(final String link) + { + final Matcher m = P_CONNECTION_ID.matcher(link); + if (m.find()) + return m.group(1); + else + throw new IllegalArgumentException("cannot extract id from " + link); + } + private static final Map LINES = new HashMap(); static diff --git a/src/de/schildbach/pte/BahnProvider.java b/src/de/schildbach/pte/BahnProvider.java index 307393ef..173eb603 100644 --- a/src/de/schildbach/pte/BahnProvider.java +++ b/src/de/schildbach/pte/BahnProvider.java @@ -234,7 +234,7 @@ public final class BahnProvider implements NetworkProvider return queryConnections(uri, page); } - private static final Pattern P_CONNECTIONS_HEAD = Pattern.compile(".*" // + private static final Pattern P_CONNECTIONS_HEAD = Pattern.compile(".*?" // + "von: ([^<]*).*?" // from + "nach: ([^<]*).*?" // to + "Datum: .., (\\d{2}\\.\\d{2}\\.\\d{2}).*?" // currentDate @@ -244,7 +244,7 @@ public final class BahnProvider implements NetworkProvider private static final Pattern P_CONNECTIONS_COARSE = Pattern.compile("(.+?)", Pattern.DOTALL); private static final Pattern P_CONNECTIONS_FINE = Pattern.compile(".*?" // + "" // link - + "(\\d+:\\d+)
(\\d+:\\d+)
.+?" // departureTime, arrivalTime + + "(\\d{1,2}:\\d{2})
(\\d{1,2}:\\d{2}).+?" // departureTime, arrivalTime + "(.*?)
.*?" // line , Pattern.DOTALL); @@ -284,8 +284,8 @@ public final class BahnProvider implements NetworkProvider line = normalizeLine(line); else line = null; - final Connection connection = new Connection(ParserUtils.extractId(link), link, departureTime, arrivalTime, line, - line != null ? LINES.get(line.charAt(0)) : null, 0, from.name, 0, to.name, null); + final Connection connection = new Connection(AbstractHafasProvider.extractConnectionId(link), link, departureTime, arrivalTime, + line, line != null ? LINES.get(line.charAt(0)) : null, 0, from.name, 0, to.name, null); connections.add(connection); } else @@ -302,18 +302,19 @@ public final class BahnProvider implements NetworkProvider } } - private static final Pattern P_CONNECTION_DETAILS_HEAD = Pattern.compile(".*Verbindungsdetails.*", Pattern.DOTALL); + private static final Pattern P_CONNECTION_DETAILS_HEAD = Pattern.compile(".*?" // + + "Verbindungsdetails.*", Pattern.DOTALL); private static final Pattern P_CONNECTION_DETAILS_COARSE = Pattern.compile("
\n(.+?>\n)
", Pattern.DOTALL); static final Pattern P_CONNECTION_DETAILS_FINE = Pattern.compile("\\s*(.+?)\\s*.*?" // departure + "(?:" // + "\\s*(.+?)\\s*.*?" // line - + "ab\\s+(?:]*>.*?)?\\s*(\\d+:\\d+)\\s*(?:]*>.*?)?" // departureTime + + "ab\\s+(?:]*>.*?)?\\s*(\\d{1,2}:\\d{2})\\s*(?:]*>.*?)?" // departureTime + "\\s*(Gl\\. .+?)?\\s*\n" // departurePosition - + "am\\s+(\\d+\\.\\d+\\.\\d+).*?" // departureDate + + "am\\s+(\\d{2}\\.\\d{2}\\.\\d{2}).*?" // departureDate + "\\s*(.+?)\\s*
.*?" // arrival - + "an\\s+(?:]*>.*?)?\\s*(\\d+:\\d+)\\s*(?:]*>.*?)?" // arrivalTime + + "an\\s+(?:]*>.*?)?\\s*(\\d{1,2}:\\d{2})\\s*(?:]*>.*?)?" // arrivalTime + "\\s*(Gl\\. .+?)?\\s*\n" // arrivalPosition - + "am\\s+(\\d+\\.\\d+\\.\\d+).*?" // arrivalDate + + "am\\s+(\\d{2}\\.\\d{2}\\.\\d{2}).*?" // arrivalDate + "|" // + "(\\d+) Min\\..*?" // footway + "\\s*(.+?)\\s*
\n" // arrival @@ -422,8 +423,8 @@ public final class BahnProvider implements NetworkProvider if (firstDepartureTime == null || lastArrivalTime == null) throw new IllegalStateException("could not parse all parts of:\n" + page + "\n" + parts); - return new GetConnectionDetailsResult(new Date(), new Connection(ParserUtils.extractId(uri), uri, firstDepartureTime, lastArrivalTime, - null, null, 0, firstDeparture, 0, lastArrival, parts)); + return new GetConnectionDetailsResult(new Date(), new Connection(AbstractHafasProvider.extractConnectionId(uri), uri, firstDepartureTime, + lastArrivalTime, null, null, 0, firstDeparture, 0, lastArrival, parts)); } else { diff --git a/src/de/schildbach/pte/RmvProvider.java b/src/de/schildbach/pte/RmvProvider.java index c1a7c745..58e04641 100644 --- a/src/de/schildbach/pte/RmvProvider.java +++ b/src/de/schildbach/pte/RmvProvider.java @@ -286,7 +286,7 @@ public class RmvProvider extends AbstractHafasProvider line = normalizeLine(line); else line = null; - final Connection connection = new Connection(ParserUtils.extractId(link), link, departureTime, arrivalTime, line, + final Connection connection = new Connection(extractConnectionId(link), link, departureTime, arrivalTime, line, line != null ? lineColors(line) : null, 0, from.name, 0, to.name, null); connections.add(connection); } @@ -399,7 +399,7 @@ public class RmvProvider extends AbstractHafasProvider } } - return new GetConnectionDetailsResult(currentDate, new Connection(ParserUtils.extractId(uri), uri, firstDepartureTime, lastArrivalTime, + return new GetConnectionDetailsResult(currentDate, new Connection(extractConnectionId(uri), uri, firstDepartureTime, lastArrivalTime, null, null, 0, firstDeparture, 0, lastArrival, parts)); } else diff --git a/src/de/schildbach/pte/SbbProvider.java b/src/de/schildbach/pte/SbbProvider.java index 2010c4cf..447e865c 100644 --- a/src/de/schildbach/pte/SbbProvider.java +++ b/src/de/schildbach/pte/SbbProvider.java @@ -44,19 +44,20 @@ import de.schildbach.pte.util.ParserUtils; 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 long PARSER_DAY_ROLLOVER_THRESHOLD_MS = 12 * 60 * 60 * 1000; public boolean hasCapabilities(final Capability... capabilities) { for (final Capability capability : capabilities) - if (capability == Capability.NEARBY_STATIONS) - return false; + if (capability == Capability.DEPARTURES) + return true; - return true; + return false; } - private static final String NAME_URL = "http://fahrplan.sbb.ch/bin/bhftafel.exe/dox?input="; + private static final String NAME_URL = API_BASE + "bhftafel.exe/dox?input="; private static final Pattern P_SINGLE_NAME = Pattern.compile(".*?.*", Pattern.DOTALL); private static final Pattern P_MULTI_NAME = Pattern.compile("\n?" // @@ -85,7 +86,7 @@ public class SbbProvider extends AbstractHafasProvider return results; } - private final static String NEARBY_URI = "http://fahrplan.sbb.ch/bin/bhftafel.exe/dn?input=%s&distance=50&near=Anzeigen"; + private final static String NEARBY_URI = API_BASE + "bhftafel.exe/dn?input=%s&distance=50&near=Anzeigen"; @Override protected String nearbyStationUri(final String stationId) @@ -99,7 +100,7 @@ public class SbbProvider extends AbstractHafasProvider final DateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm"); final StringBuilder uri = new StringBuilder(); - uri.append("http://fahrplan.sbb.ch/bin/query.exe/dn"); + uri.append(API_BASE).append("query.exe/dox"); uri.append("?OK"); uri.append("&REQ0HafasMaxChangeTime=120"); uri.append("&REQ0HafasOptimize1=").append(ParserUtils.urlEncode("1:1")); @@ -175,6 +176,8 @@ public class SbbProvider extends AbstractHafasProvider List viaAddresses = null; List toAddresses = null; + // FIXME cannot parse ambiguous + final Matcher mPreAddress = P_PRE_ADDRESS.matcher(page); while (mPreAddress.find()) { @@ -214,43 +217,20 @@ public class SbbProvider extends AbstractHafasProvider } private static final Pattern P_CONNECTIONS_HEAD = Pattern.compile(".*?" // - + "Von:.*?]*>(?:)?(.*?).*?" // from - + "Datum:.*?]*>.., (\\d{2}\\.\\d{2}\\.\\d{2}).*?" // date - + "Nach:.*?]*>(?:)?(.*?).*?" // to - + "(?:([^<]*)<.*?" // from + + "Nach: ([^<]*)<.*?" // to + + "Datum: .., (\\d{2}\\.\\d{2}\\.\\d{2}).*?" // currentDate + + "(

.*?" // body + + "(?:(.*?)\n"// - + "(.*?)\n"// - + "(?:.*?\n)?", Pattern.DOTALL); - private static final Pattern P_CONNECTIONS_FINE = Pattern.compile(".*?" // - + "name=\"guiVCtrl_connection_detailsOut_select_([\\w-]+)\".*?" // id - + ".., (\\d{2}\\.\\d{2}\\.\\d{2}).*?" // departureDate - + "ab.*?(\\d{2}:\\d{2}).*?" // departureTime - + "duration.*?\\d{1,2}:\\d{2}.*?" // - + "(?:.., (\\d{2}\\.\\d{2}\\.\\d{2}).*?)?" // arrivalDate - + "an.*?(\\d{2}:\\d{2}).*?" // arrivalTime - , Pattern.DOTALL); - private static final Pattern P_CONNECTIONS_DETAILS_COARSE = Pattern.compile(".*?" // id - + "\n?.*?(.*?)
", Pattern.DOTALL); - private static final Pattern P_CONNECTION_DETAILS_COARSE = Pattern.compile("(.*?class=\"stop-station-icon\".*?)\n?" // - + "(.*?class=\"stop-station-icon last\".*?)", Pattern.DOTALL); - static final Pattern P_CONNECTION_DETAILS_FINE = Pattern.compile(".*?" // - + "\n" // - + "(?:
]*>)?" // departureId - + "([^\n<]*?)<.*?" // departure - + "]*>\n(?:.., (\\d{2}\\.\\d{2}\\.\\d{2})\n)?.*?" // departureDate - + "]*>(?:(\\d{2}:\\d{2})| ).*?" // departureTime - + "]*>\n(?:]*>\n)?(.+?)?\\s*(?:]*>\n\n)?.*?" // departurePosition - + "]*>\\s*(.*?)\\s*|" // line - + "\n(\\d+) Min\\.).*?" // min - + "\n" // - + "(?:]*>)?" // arrivalId - + "([^\n<]*?)<.*?" // arrival - + "]*>\n(?:.., (\\d{2}\\.\\d{2}\\.\\d{2})\n)?.*?" // arrivalDate - + "]*>(?:(\\d{2}:\\d{2})| ).*?" // arrivalTime - + "]*>\n(?:]*>\n)?(.+?)?\\s*(?:]*>\n\n)?.*?" // arrivalPosition + private static final Pattern P_CONNECTIONS_COARSE = Pattern.compile("\\G" // + + "

\n" // + + "(.*?)

\n", Pattern.DOTALL); + private static final Pattern P_CONNECTIONS_FINE = Pattern.compile("" // + + "(?:]*>)?" // + + "" // link + + "(\\d{1,2}:\\d{2})-(\\d{1,2}:\\d{2}).*?" // departureTime, arrivalTime , Pattern.DOTALL); private QueryConnectionsResult queryConnections(final String uri, final CharSequence page) throws IOException @@ -259,36 +239,43 @@ public class SbbProvider extends AbstractHafasProvider if (mHead.matches()) { final Location from = new Location(LocationType.ANY, 0, 0, 0, ParserUtils.resolveEntities(mHead.group(1))); - final Location to = new Location(LocationType.ANY, 0, 0, 0, ParserUtils.resolveEntities(mHead.group(3))); - final String linkEarlier = mHead.group(4) != null ? ParserUtils.resolveEntities(mHead.group(4)) : null; - final String linkLater = mHead.group(5) != null ? ParserUtils.resolveEntities(mHead.group(5)) : null; + final Location to = new Location(LocationType.ANY, 0, 0, 0, ParserUtils.resolveEntities(mHead.group(2))); + final Date currentDate = ParserUtils.parseDate(mHead.group(3)); + final String body = mHead.group(4); + final String linkEarlier = mHead.group(5) != null ? ParserUtils.resolveEntities(mHead.group(5)) : null; + final String linkLater = mHead.group(6) != null ? ParserUtils.resolveEntities(mHead.group(6)) : null; final List connections = new ArrayList(); String oldZebra = null; - final Matcher mConCoarse = P_CONNECTIONS_COARSE.matcher(page); - while (mConCoarse.find()) + final Matcher mCoarse = P_CONNECTIONS_COARSE.matcher(body); + while (mCoarse.find()) { - final String zebra = mConCoarse.group(1); + final String zebra = mCoarse.group(1); if (oldZebra != null && zebra.equals(oldZebra)) throw new IllegalArgumentException("missed row? last:" + zebra); else oldZebra = zebra; - final String set = mConCoarse.group(2) + mConCoarse.group(3); - final Matcher mConFine = P_CONNECTIONS_FINE.matcher(set); - if (mConFine.matches()) + final String set = mCoarse.group(2); + final Matcher mFine = P_CONNECTIONS_FINE.matcher(set); + if (mFine.matches()) { - final String id = mConFine.group(1); - final Date departureDate = ParserUtils.parseDate(mConFine.group(2)); - final Date departureTime = ParserUtils.joinDateTime(departureDate, ParserUtils.parseTime(mConFine.group(3))); - final Date arrivalDate = mConFine.group(4) != null ? ParserUtils.parseDate(mConFine.group(4)) : null; - final Date arrivalTime = ParserUtils.joinDateTime(arrivalDate != null ? arrivalDate : departureDate, ParserUtils - .parseTime(mConFine.group(5))); - final String link = uri + "#" + id; // TODO use print link? + final String link = ParserUtils.resolveEntities(mFine.group(1)); + Date departureTime = ParserUtils.joinDateTime(currentDate, ParserUtils.parseTime(mFine.group(2))); + if (!connections.isEmpty()) + { + final long diff = ParserUtils.timeDiff(departureTime, connections.get(connections.size() - 1).departureTime); + if (diff > PARSER_DAY_ROLLOVER_THRESHOLD_MS) + departureTime = ParserUtils.addDays(departureTime, -1); + else if (diff < -PARSER_DAY_ROLLOVER_THRESHOLD_MS) + departureTime = ParserUtils.addDays(departureTime, 1); + } + Date arrivalTime = ParserUtils.joinDateTime(currentDate, ParserUtils.parseTime(mFine.group(3))); + if (departureTime.after(arrivalTime)) + arrivalTime = ParserUtils.addDays(arrivalTime, 1); - final Connection connection = new Connection(id, link, departureTime, arrivalTime, null, null, 0, from.name, 0, to.name, - new ArrayList(1)); - connections.add(connection); + connections.add(new Connection(extractConnectionId(link), link, departureTime, arrivalTime, null, null, 0, from.name, 0, to.name, + null)); } else { @@ -296,77 +283,6 @@ public class SbbProvider extends AbstractHafasProvider } } - final Matcher mConDetCoarse = P_CONNECTIONS_DETAILS_COARSE.matcher(page); - while (mConDetCoarse.find()) - { - final String id = mConDetCoarse.group(1); - final Connection connection = findConnection(connections, id); - - Date lastDate = null; - - final Matcher mDetCoarse = P_CONNECTION_DETAILS_COARSE.matcher(mConDetCoarse.group(2)); - while (mDetCoarse.find()) - { - final String set = mDetCoarse.group(1) + mDetCoarse.group(2); - - final Matcher mDetFine = P_CONNECTION_DETAILS_FINE.matcher(set); - if (mDetFine.matches()) - { - final int departureId = mDetFine.group(1) != null ? Integer.parseInt(mDetFine.group(1)) : 0; - - final String departure = ParserUtils.resolveEntities(mDetFine.group(2)); - - Date departureDate = mDetFine.group(3) != null ? ParserUtils.parseDate(mDetFine.group(3)) : lastDate; - if (departureDate != null) - lastDate = departureDate; - - final String lineType = mDetFine.group(6); - - final int arrivalId = mDetFine.group(9) != null ? Integer.parseInt(mDetFine.group(9)) : 0; - - final String arrival = ParserUtils.resolveEntities(mDetFine.group(10)); - - Date arrivalDate = mDetFine.group(11) != null ? ParserUtils.parseDate(mDetFine.group(11)) : lastDate; - if (arrivalDate != null) - lastDate = arrivalDate; - - if (!lineType.equals("fuss") && !lineType.equals("transfer")) - { - if (departureId == 0) - throw new IllegalStateException("departureId"); - - final Date departureTime = ParserUtils.joinDateTime(departureDate, ParserUtils.parseTime(mDetFine.group(4))); - - final String departurePosition = mDetFine.group(5) != null ? ParserUtils.resolveEntities(mDetFine.group(5)) : null; - - final String line = normalizeLine(lineType, ParserUtils.resolveEntities(mDetFine.group(7))); - - if (arrivalId == 0) - throw new IllegalStateException("arrivalId"); - - final Date arrivalTime = ParserUtils.joinDateTime(arrivalDate, ParserUtils.parseTime(mDetFine.group(12))); - - final String arrivalPosition = mDetFine.group(13) != null ? ParserUtils.resolveEntities(mDetFine.group(13)) : null; - - final Connection.Trip trip = new Connection.Trip(line, lineColors(line), 0, null, departureTime, departurePosition, - departureId, departure, arrivalTime, arrivalPosition, arrivalId, arrival); - connection.parts.add(trip); - } - else - { - final int min = Integer.parseInt(mDetFine.group(8)); - - final Connection.Footway footway = new Connection.Footway(min, departureId, departure, arrivalId, arrival); - connection.parts.add(footway); - } - } - else - { - throw new IllegalArgumentException("cannot parse '" + set + "' on " + uri); - } - } - } - return new QueryConnectionsResult(uri, from, null, to, linkEarlier, linkLater, connections); } else @@ -375,24 +291,106 @@ public class SbbProvider extends AbstractHafasProvider } } - private Connection findConnection(final List connections, final String id) - { - for (final Connection connection : connections) - if (connection.id.equals(id)) - return connection; + private static final Pattern P_CONNECTION_DETAILS_HEAD = Pattern.compile(".*?" // + + "

\n- ([^<]*) -\n

\n" // + + "(.*?)" // + + "

\n" // + + "Abfahrt: (\\d+\\.\\d+\\.\\d+).*?", Pattern.DOTALL); + private static final Pattern P_CONNECTION_DETAILS_COARSE = Pattern.compile("\\G" // + + "

\n(.*?)

\n" // + + "

\n(.*?)

\n" // + , Pattern.DOTALL); + private static final Pattern P_CONNECTION_DETAILS_JOURNEY = Pattern.compile("" // + + "(?:" // + + "(.+?)\n.*?" // line + + "ab (\\d{1,2}:\\d{2})\n" // departureTime + + "(?: (Gl\\. .+?)\\s*\n)?" // departurePosition + + ".*?" // + + "an (\\d{1,2}:\\d{2})\n" // arrivalTime + + "(?: (Gl\\. .+?)\\s*\n)?" // arrivalPosition + + "|" // + + "(?:Fussweg|Übergang)\n" // + + "(\\d+) Min\\.\n" // minutes + + ")" // + , Pattern.DOTALL); + private static final Pattern P_CONNECTION_DETAILS_DESTINATION = Pattern.compile("" // + + "- ([^<]*) -\n" // destination + , Pattern.DOTALL); - return null; - } - - public GetConnectionDetailsResult getConnectionDetails(final String connectionUri) throws IOException + public GetConnectionDetailsResult getConnectionDetails(final String uri) throws IOException { - throw new UnsupportedOperationException(); + final CharSequence page = ParserUtils.scrape(uri); + + final Matcher mHead = P_CONNECTION_DETAILS_HEAD.matcher(page); + if (mHead.matches()) + { + Date firstDepartureTime = null; + final String firstDeparture = ParserUtils.resolveEntities(mHead.group(1)); + Date lastArrivalTime = null; + String departure = firstDeparture; + final String body = mHead.group(2); + final Date date = ParserUtils.parseDate(mHead.group(3)); + + final List parts = new ArrayList(4); + + final Matcher mCoarse = P_CONNECTION_DETAILS_COARSE.matcher(body); + while (mCoarse.find()) + { + final Matcher mJourney = P_CONNECTION_DETAILS_JOURNEY.matcher(mCoarse.group(1)); + final Matcher mDestination = P_CONNECTION_DETAILS_DESTINATION.matcher(mCoarse.group(2)); + if (mJourney.matches() && mDestination.matches()) + { + final String arrival = mDestination.group(1); + + if (mJourney.group(6) == null) + { + final String line = normalizeLine(ParserUtils.resolveEntities(mJourney.group(1))); + Date departureTime = ParserUtils.joinDateTime(date, ParserUtils.parseTime(mJourney.group(2))); + if (lastArrivalTime != null && departureTime.before(lastArrivalTime)) + departureTime = ParserUtils.addDays(departureTime, 1); + final String departurePosition = mJourney.group(3) != null ? ParserUtils.resolveEntities(mJourney.group(3)) : null; + Date arrivalTime = ParserUtils.joinDateTime(date, ParserUtils.parseTime(mJourney.group(4))); + if (departureTime.after(arrivalTime)) + arrivalTime = ParserUtils.addDays(arrivalTime, 1); + final String arrivalPosition = mJourney.group(5) != null ? ParserUtils.resolveEntities(mJourney.group(5)) : null; + + parts.add(new Connection.Trip(line, lineColors(line), 0, null, departureTime, departurePosition, 0, departure, arrivalTime, + arrivalPosition, 0, arrival)); + + if (firstDepartureTime == null) + firstDepartureTime = departureTime; + lastArrivalTime = arrivalTime; + departure = arrival; + } + else + { + final int min = Integer.parseInt(mJourney.group(6)); + + parts.add(new Connection.Footway(min, 0, departure, 0, arrival, 0, 0)); + + departure = arrival; + } + } + else + { + throw new IllegalArgumentException("cannot parse '" + mCoarse.group(1) + "', '" + mCoarse.group(2) + "' on " + uri); + } + } + + return new GetConnectionDetailsResult(new Date(), new Connection(AbstractHafasProvider.extractConnectionId(uri), uri, firstDepartureTime, + lastArrivalTime, null, null, 0, firstDeparture, 0, departure, parts)); + } + else + { + throw new IllegalArgumentException("cannot parse '" + page + "' on " + uri); + } + } public String departuresQueryUri(final String stationId, final int maxDepartures) { final StringBuilder uri = new StringBuilder(); - uri.append("http://fahrplan.sbb.ch/bin/bhftafel.exe/dox"); + uri.append(API_BASE).append("bhftafel.exe/dox"); uri.append("?start="); if (maxDepartures != 0) uri.append("&maxJourneys=").append(maxDepartures); diff --git a/src/de/schildbach/pte/VbbProvider.java b/src/de/schildbach/pte/VbbProvider.java index 1eedfe63..2d29e1d5 100644 --- a/src/de/schildbach/pte/VbbProvider.java +++ b/src/de/schildbach/pte/VbbProvider.java @@ -277,7 +277,7 @@ public final class VbbProvider implements NetworkProvider if (departureTime.after(arrivalTime)) arrivalTime = ParserUtils.addDays(arrivalTime, 1); final String line = normalizeLine(ParserUtils.resolveEntities(mConFine.group(4))); - final Connection connection = new Connection(ParserUtils.extractId(link), link, departureTime, arrivalTime, line, + 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); connections.add(connection); } @@ -424,7 +424,7 @@ public final class VbbProvider implements NetworkProvider } if (firstDepartureTime != null && lastArrivalTime != null) - return new GetConnectionDetailsResult(currentDate, new Connection(ParserUtils.extractId(uri), uri, firstDepartureTime, + return new GetConnectionDetailsResult(currentDate, new Connection(AbstractHafasProvider.extractConnectionId(uri), uri, firstDepartureTime, lastArrivalTime, null, null, firstDepartureId, firstDeparture, lastArrivalId, lastArrival, parts)); else return new GetConnectionDetailsResult(currentDate, null); diff --git a/src/de/schildbach/pte/util/ParserUtils.java b/src/de/schildbach/pte/util/ParserUtils.java index afd7bd53..35b324d6 100644 --- a/src/de/schildbach/pte/util/ParserUtils.java +++ b/src/de/schildbach/pte/util/ParserUtils.java @@ -267,9 +267,11 @@ public final class ParserUtils return cTime.getTime(); } - public static long timeDiff(Date d1, Date d2) + public static long timeDiff(final Date d1, final Date d2) { - return d1.getTime() - d2.getTime(); + final long t1 = d1.getTime(); + final long t2 = d2.getTime(); + return t1 - t2; } public static Date addDays(final Date time, final int days) @@ -329,10 +331,5 @@ public final class ParserUtils return selected; } - public static String extractId(final String link) - { - return link.substring(link.length() - 10); - } - public static final String P_PLATFORM = "[\\wÄÖÜäöüßáàâéèêíìîóòôúùû\\. -/&#;]+?"; } diff --git a/test/de/schildbach/pte/SbbProviderTest.java b/test/de/schildbach/pte/SbbProviderTest.java deleted file mode 100644 index f80e09a1..00000000 --- a/test/de/schildbach/pte/SbbProviderTest.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright 2010 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 . - */ - -package de.schildbach.pte; - -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertTrue; - -import java.util.regex.Matcher; - -import org.junit.Test; - -/** - * @author Andreas Schildbach - */ -public class SbbProviderTest -{ - @Test - public void tripThatTriggeredLongRunningMatch() - { - assertFineConnectionDetails("\n" // - + "\"Umgebungskarte:\n" // - + "\n" // - + "\n" // - + "Budapest-Keleti pu.\n" // - + "\n" // - + "Di, 10.08.10\n" // - + "\n" // - + "ab21:05\n" // - + "\n" // - + "\n" // - + "\"EN
\n" // - + "\n" // - + "EN 462\n" // - + "\n" // - + "\n" // - + "\n" // - + "
\n" // - + "
\n" // - + "
\n" // - + "
\n" // - + "
\n" // - + "
\n" // - + "\n" // - + "\n" // - + "EuroNight, \"Nur \"Reservierung \"Schlafwagen\" \"Liegewagen\" \"Minibar\" GP \n" // - + "\n" // - + "\"Umgebungskarte:\n" // - + "\n" // - + "München Hbf\n" // - + "\n" // - + "Mi, 11.08.10\n" // - + "\n" // - + "an06:15\n" // - + "12 \n" // - + "\n"); - } - - @Test - public void tripWithoutDate() - { - assertFineConnectionDetails("\n" // - + "\"Umgebungskarte:\n" // - + "\n" // - + "\n" // - + "Aarau\n" // - + "\n" // - + "\n" // - + "ab15:47\n" // - + "5 \n" // - + "\n" // - + "\n" // - + "\"IR
\n" // - + "\n" // - + "IR 1928\n" // - + "\n" // - + "\n" // - + "\n" // - + "
\n" // - + "
\n" // - + "1. \"Tiefe\n" // - + "
\n" // - + "
\n" // - + "2. \"Tiefe\n" // - + "
\n" // - + "
\n" // - + "\n" // - + "\n" // - + "InterRegio \n" // - + "\n" // - + "\n" // - + "\"Umgebungskarte:\n" // - + "\n" // - + "Bern\n" // - + "\n" // - + "\n" // - + "an16:25\n" // - + "10 \n" // - + ""); - } - - @Test - public void tripWithPrognosisInPosition() - { - assertFineConnectionDetails("\n" // - + "\n" // - + "\"Umgebungskarte:\n" // - + "\n" // - + "\n" // - + "Spiez\n" // - + "\n" // - + "\n" // - + "ab15:54\n" // - + "4 \n" // - + "\n" // - + "\n" // - + "\"IC
\n" // - + "\n" // - + "IC 1080\n" // - + "\n" // - + "\n" // - + "\n" // - + "
\n" // - + "
\n" // - + "1. \"Hohe\n" // - + "
\n" // - + "
\n" // - + "2. \"Hohe\n" // - + "
\n" // - + "
\n" // - + "\n" // - + "\n" // - + "InterCity, \"Restaurant\" \"Minibar\" \"Reservierung FZ BZ RZ \n" // - + "\n" // - + "\"Umgebungskarte:\n" // - + "\n" // - + "Basel SBB\n" // - + "\n" // - + "\n" // - + "an17:32\n" // - + "\n" // - + "12 \"Gleiswechsel!\"\n" // - + "\n" // - + ""); - } - - @Test - public void footwayFromStationToStation() - { - assertFineConnectionDetails("\n" // - + "\n" // - + "\"Umgebungskarte:\n" // - + "\n" // - + "\n" // - + "Amriswil, Bahnhof\n" // - + "\n" // - + "\n" // - + "  \n" // - + "\n" // - + "\n" // - + "\"Fussweg\"
\n" // - + "Fussweg\n" // - + "\n" // - + "\n" // - + "
\n" // - + "
\n" // - + "
\n" // - + "
\n" // - + "
\n" // - + "
\n" // - + "\n" // - + "\n" // - + "1 Min., Y \n" // - + "\n" // - + "\n" // - + "\"Umgebungskarte:\n" // - + "\n" // - + "Amriswil\n" // - + "\n" // - + "\n" // - + "  \n" // - + "\n"); - } - - @Test - public void footwayFromStationToAddress() - { - assertFineConnectionDetails("\n" // - + "\n" // - + "\"Umgebungskarte:\n" // - + "\n" // - + "\n" // - + "Einsiedeln, Birchli/Garage\n" // - + "\n" // - + "\n" // - + "  \n" // - + "\n" // - + "\n" // - + "\"Fussweg\"
\n" // - + "Fussweg\n" // - + "\n" // - + "\n" // - + "
\n" // - + "
\n" // - + "
\n" // - + "
\n" // - + "
\n" // - + "
\n" // - + "\n" // - + "\n" // - + "9 Min. \n" // - + "\n" // - + "\n" // - + "\"Umgebungskarte:\n" // - + "\n" // - + "8840 Einsiedeln, Erlenmoosweg 24\n" // - + "\n" // - + "\n" // - + "  \n" // - + "\n"); - } - - private void assertFineConnectionDetails(String s) - { - Matcher m = SbbProvider.P_CONNECTION_DETAILS_FINE.matcher(s); - assertTrue(m.matches()); - - // ParserUtils.printGroups(m); - - assertNotNull(m.group(2)); // departure - assertTrue(m.group(5) == null || m.group(5).length() < 10); // departurePosition - assertNotNull(m.group(10)); // arrival - assertTrue(m.group(13) == null || m.group(13).length() < 10); // arrivalPosition - } -} diff --git a/test/de/schildbach/pte/live/SbbProviderLiveTest.java b/test/de/schildbach/pte/live/SbbProviderLiveTest.java index 7f330159..d54936b1 100644 --- a/test/de/schildbach/pte/live/SbbProviderLiveTest.java +++ b/test/de/schildbach/pte/live/SbbProviderLiveTest.java @@ -24,6 +24,7 @@ import org.junit.Test; import de.schildbach.pte.SbbProvider; import de.schildbach.pte.NetworkProvider.WalkSpeed; +import de.schildbach.pte.dto.Connection; import de.schildbach.pte.dto.Location; import de.schildbach.pte.dto.LocationType; import de.schildbach.pte.dto.NearbyStationsResult; @@ -62,6 +63,8 @@ public class SbbProviderLiveTest System.out.println(result); final QueryConnectionsResult moreResult = provider.queryMoreConnections(result.linkLater); System.out.println(moreResult); + for (final Connection connection : moreResult.connections) + System.out.println(provider.getConnectionDetails(connection.link)); } @Test @@ -72,6 +75,8 @@ public class SbbProviderLiveTest System.out.println(result); final QueryConnectionsResult moreResult = provider.queryMoreConnections(result.linkLater); System.out.println(moreResult); + for (final Connection connection : moreResult.connections) + System.out.println(provider.getConnectionDetails(connection.link)); } @Test @@ -82,6 +87,8 @@ public class SbbProviderLiveTest System.out.println(result); final QueryConnectionsResult moreResult = provider.queryMoreConnections(result.linkLater); System.out.println(moreResult); + for (final Connection connection : moreResult.connections) + System.out.println(provider.getConnectionDetails(connection.link)); } @Test