diff --git a/src/de/schildbach/pte/BahnProvider.java b/src/de/schildbach/pte/BahnProvider.java index 0ec85c8b..0ea74150 100644 --- a/src/de/schildbach/pte/BahnProvider.java +++ b/src/de/schildbach/pte/BahnProvider.java @@ -265,7 +265,8 @@ public final class BahnProvider implements NetworkProvider line = normalizeLine(line); else line = null; - final Connection connection = new Connection(link, departureTime, arrivalTime, 0, from, 0, to, new ArrayList(1)); + final Connection connection = new Connection(ParserUtils.extractId(link), link, departureTime, arrivalTime, 0, from, 0, to, + new ArrayList(1)); connection.parts.add(new Connection.Trip(departureTime, arrivalTime, line, line != null ? LINES.get(line.charAt(0)) : null)); connections.add(connection); } @@ -393,8 +394,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(uri, firstDepartureTime, lastArrivalTime, 0, firstDeparture, 0, - lastArrival, parts)); + return new GetConnectionDetailsResult(new Date(), new Connection(ParserUtils.extractId(uri), uri, firstDepartureTime, lastArrivalTime, 0, + firstDeparture, 0, lastArrival, parts)); } else { diff --git a/src/de/schildbach/pte/Connection.java b/src/de/schildbach/pte/Connection.java index 957aa978..f7780287 100644 --- a/src/de/schildbach/pte/Connection.java +++ b/src/de/schildbach/pte/Connection.java @@ -36,10 +36,10 @@ public final class Connection implements Serializable final public String to; final public List parts; - public Connection(final String link, final Date departureTime, final Date arrivalTime, final int fromId, final String from, final int toId, - final String to, final List parts) + public Connection(final String id, final String link, final Date departureTime, final Date arrivalTime, final int fromId, final String from, + final int toId, final String to, final List parts) { - this.id = extractId(link); + this.id = id; this.link = link; this.departureTime = departureTime; this.fromId = fromId; @@ -50,11 +50,6 @@ public final class Connection implements Serializable this.parts = parts; } - public static String extractId(String link) - { - return link.substring(link.length() - 10); - } - @Override public String toString() { diff --git a/src/de/schildbach/pte/MvvProvider.java b/src/de/schildbach/pte/MvvProvider.java index d08e466d..0b0ff7fb 100644 --- a/src/de/schildbach/pte/MvvProvider.java +++ b/src/de/schildbach/pte/MvvProvider.java @@ -299,7 +299,7 @@ public class MvvProvider implements NetworkProvider Date arrivalTime = ParserUtils.joinDateTime(date, ParserUtils.parseTime(mConFine.group(5))); if (departureTime.after(arrivalTime)) arrivalTime = ParserUtils.addDays(arrivalTime, 1); - final Connection connection = new Connection(link, departureTime, arrivalTime, 0, from, 0, to, + final Connection connection = new Connection(ParserUtils.extractId(link), link, departureTime, arrivalTime, 0, from, 0, to, new ArrayList(1)); connection.parts.add(new Connection.Trip(departureTime, arrivalTime, null, null)); connections.add(connection); @@ -311,7 +311,7 @@ public class MvvProvider implements NetworkProvider final Date departureTime = calendar.getTime(); calendar.add(Calendar.MINUTE, min); final Date arrivalTime = calendar.getTime(); - final Connection connection = new Connection(link, departureTime, arrivalTime, 0, from, 0, to, + final Connection connection = new Connection(ParserUtils.extractId(link), link, departureTime, arrivalTime, 0, from, 0, to, new ArrayList(1)); connection.parts.add(new Connection.Footway(min, from, to)); connections.add(connection); @@ -448,8 +448,8 @@ public class MvvProvider implements NetworkProvider lastArrivalTime = calendar.getTime(); } - return new GetConnectionDetailsResult(new Date(), new Connection(uri, firstDepartureTime, lastArrivalTime, 0, firstDeparture, 0, - lastArrival, parts)); + return new GetConnectionDetailsResult(new Date(), new Connection(ParserUtils.extractId(uri), uri, firstDepartureTime, lastArrivalTime, 0, + firstDeparture, 0, lastArrival, parts)); } else { diff --git a/src/de/schildbach/pte/ParserUtils.java b/src/de/schildbach/pte/ParserUtils.java index 8ae7ebe1..92e0375b 100644 --- a/src/de/schildbach/pte/ParserUtils.java +++ b/src/de/schildbach/pte/ParserUtils.java @@ -201,4 +201,9 @@ public final class ParserUtils throw new RuntimeException(x); } } + + public static String extractId(final String link) + { + return link.substring(link.length() - 10); + } } diff --git a/src/de/schildbach/pte/RmvProvider.java b/src/de/schildbach/pte/RmvProvider.java index 8235d757..d44a4e29 100644 --- a/src/de/schildbach/pte/RmvProvider.java +++ b/src/de/schildbach/pte/RmvProvider.java @@ -264,7 +264,8 @@ public class RmvProvider implements NetworkProvider line = normalizeLine(line); else line = null; - final Connection connection = new Connection(link, departureTime, arrivalTime, 0, from, 0, to, new ArrayList(1)); + final Connection connection = new Connection(ParserUtils.extractId(link), link, departureTime, arrivalTime, 0, from, 0, to, + new ArrayList(1)); connection.parts.add(new Connection.Trip(departureTime, arrivalTime, line, line != null ? LINES.get(line.charAt(0)) : null)); connections.add(connection); } @@ -380,8 +381,8 @@ public class RmvProvider implements NetworkProvider } } - return new GetConnectionDetailsResult(currentDate, new Connection(uri, firstDepartureTime, lastArrivalTime, 0, firstDeparture, 0, - lastArrival, parts)); + return new GetConnectionDetailsResult(currentDate, new Connection(ParserUtils.extractId(uri), uri, firstDepartureTime, lastArrivalTime, + 0, firstDeparture, 0, lastArrival, parts)); } else { diff --git a/src/de/schildbach/pte/SbbProvider.java b/src/de/schildbach/pte/SbbProvider.java index 12d3e0fb..18efe6d3 100644 --- a/src/de/schildbach/pte/SbbProvider.java +++ b/src/de/schildbach/pte/SbbProvider.java @@ -113,20 +113,121 @@ public class SbbProvider implements NetworkProvider return uri.toString(); } + private static final Pattern P_PRE_ADDRESS = Pattern.compile( + "", Pattern.DOTALL); + private static final Pattern P_ADDRESSES = Pattern.compile("\\s*(.*?)\\s*", Pattern.DOTALL); + public QueryConnectionsResult queryConnections(final String from, final String via, final String to, final Date date, final boolean dep) throws IOException { - throw new UnsupportedOperationException(); + final String uri = connectionsQueryUri(from, via, to, date, dep); + final CharSequence page = ParserUtils.scrape(uri); + + // TODO errors + + List fromAddresses = null; + List viaAddresses = null; + List toAddresses = null; + + final Matcher mPreAddress = P_PRE_ADDRESS.matcher(page); + while (mPreAddress.find()) + { + final String type = mPreAddress.group(1); + final String options = mPreAddress.group(2); + + final Matcher mAddresses = P_ADDRESSES.matcher(options); + final List addresses = new ArrayList(); + while (mAddresses.find()) + { + final String address = ParserUtils.resolveEntities(mAddresses.group(1)).trim(); + if (!addresses.contains(address)) + addresses.add(address); + } + + if (type.equals("REQ0JourneyStopsS0K")) + fromAddresses = addresses; + else if (type.equals("REQ0JourneyStopsZ0K")) + toAddresses = addresses; + else if (type.equals("REQ0JourneyStops1.0K")) + viaAddresses = addresses; + else + throw new IOException(type); + } + + if (fromAddresses != null || viaAddresses != null || toAddresses != null) + return new QueryConnectionsResult(QueryConnectionsResult.Status.AMBIGUOUS, fromAddresses, viaAddresses, toAddresses); + else + return queryConnections(uri, page); } - public QueryConnectionsResult queryMoreConnections(String uri) throws IOException + public QueryConnectionsResult queryMoreConnections(final String uri) throws IOException { - throw new UnsupportedOperationException(); + final CharSequence page = ParserUtils.scrape(uri); + + return queryConnections(uri, page); } + private static final Pattern P_CONNECTIONS_HEAD = Pattern.compile(".*?" // + + "Von:.*?(.*?).*?" // from + + "Datum:.*?.., (\\d{2}\\.\\d{2}\\.\\d{2}).*?" // date + + "Nach:.*?(.*?).*?" // to + + "(?:.*?)?" // linkEarlier + + "(?:.*?)?" // linkLater + , Pattern.DOTALL); + private static final Pattern P_CONNECTIONS_COARSE = Pattern.compile("(.*?)\n?"// + + "(.+?)", Pattern.DOTALL); + private static final Pattern P_CONNECTIONS_FINE = Pattern.compile(".*?" // + + ".., (\\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 QueryConnectionsResult queryConnections(final String uri, final CharSequence page) throws IOException { - throw new UnsupportedOperationException(); + final Matcher mHead = P_CONNECTIONS_HEAD.matcher(page); + if (mHead.matches()) + { + final String from = ParserUtils.resolveEntities(mHead.group(1)); + final Date currentDate = ParserUtils.parseDate(mHead.group(2)); + final String to = 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 List connections = new ArrayList(); + + final Matcher mConCoarse = P_CONNECTIONS_COARSE.matcher(page); + int i = 1; + while (mConCoarse.find()) + { + final String set = mConCoarse.group(2) + mConCoarse.group(3); + final Matcher mConFine = P_CONNECTIONS_FINE.matcher(set); + if (mConFine.matches()) + { + final Date departureDate = ParserUtils.parseDate(mConFine.group(1)); + final Date departureTime = ParserUtils.joinDateTime(departureDate, ParserUtils.parseTime(mConFine.group(2))); + final Date arrivalDate = mConFine.group(3) != null ? ParserUtils.parseDate(mConFine.group(3)) : null; + final Date arrivalTime = ParserUtils.joinDateTime(arrivalDate != null ? arrivalDate : departureDate, ParserUtils + .parseTime(mConFine.group(4))); + final String id = departureTime.toString() + arrivalTime.toString(); + + final Connection connection = new Connection(id, uri + "#" + i++, departureTime, arrivalTime, 0, from, 0, to, + new ArrayList(1)); + connection.parts.add(new Connection.Trip(departureTime, arrivalTime, null, null)); + connections.add(connection); + } + else + { + throw new IllegalArgumentException("cannot parse '" + set + "' on " + uri); + } + } + + return new QueryConnectionsResult(uri, from, to, currentDate, linkEarlier, linkLater, connections); + } + else + { + throw new IOException(page.toString()); + } } public GetConnectionDetailsResult getConnectionDetails(final String connectionUri) throws IOException diff --git a/src/de/schildbach/pte/VbbProvider.java b/src/de/schildbach/pte/VbbProvider.java index bcff849b..251777ef 100644 --- a/src/de/schildbach/pte/VbbProvider.java +++ b/src/de/schildbach/pte/VbbProvider.java @@ -271,7 +271,8 @@ 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(link, departureTime, arrivalTime, 0, from, 0, to, new ArrayList(1)); + final Connection connection = new Connection(ParserUtils.extractId(link), link, departureTime, arrivalTime, 0, from, 0, to, + new ArrayList(1)); connection.parts.add(new Connection.Trip(departureTime, arrivalTime, line, line != null ? LINES.get(line) : null)); connections.add(connection); } @@ -410,8 +411,8 @@ public final class VbbProvider implements NetworkProvider } if (firstDepartureTime != null && lastArrivalTime != null) - return new GetConnectionDetailsResult(currentDate, new Connection(uri, firstDepartureTime, lastArrivalTime, firstDepartureId, - firstDeparture, lastArrivalId, lastArrival, parts)); + return new GetConnectionDetailsResult(currentDate, new Connection(ParserUtils.extractId(uri), uri, firstDepartureTime, + lastArrivalTime, firstDepartureId, firstDeparture, lastArrivalId, lastArrival, parts)); else return new GetConnectionDetailsResult(currentDate, null); } diff --git a/test/de/schildbach/pte/live/SbbProviderLiveTest.java b/test/de/schildbach/pte/live/SbbProviderLiveTest.java new file mode 100644 index 00000000..d922f791 --- /dev/null +++ b/test/de/schildbach/pte/live/SbbProviderLiveTest.java @@ -0,0 +1,40 @@ +/* + * 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.live; + +import java.util.Date; + +import org.junit.Test; + +import de.schildbach.pte.QueryConnectionsResult; +import de.schildbach.pte.SbbProvider; + +/** + * @author Andreas Schildbach + */ +public class SbbProviderLiveTest +{ + private SbbProvider provider = new SbbProvider(); + + @Test + public void connection() throws Exception + { + final QueryConnectionsResult result = provider.queryConnections("Zürich!", null, "Bern", new Date(), true); + System.out.println(result); + } +}