parse SBB connection overview

git-svn-id: https://public-transport-enabler.googlecode.com/svn/trunk@59 0924bc21-9374-b0fa-ee44-9ff1593b38f0
This commit is contained in:
andreas.schildbach 2010-08-10 10:37:37 +00:00
parent 5510ccbf6b
commit 6f1ecafcb2
8 changed files with 169 additions and 25 deletions

View file

@ -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<Connection.Part>(1));
final Connection connection = new Connection(ParserUtils.extractId(link), link, departureTime, arrivalTime, 0, from, 0, to,
new ArrayList<Connection.Part>(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
{

View file

@ -36,10 +36,10 @@ public final class Connection implements Serializable
final public String to;
final public List<Part> 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<Part> 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<Part> 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()
{

View file

@ -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<Connection.Part>(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<Connection.Part>(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
{

View file

@ -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);
}
}

View file

@ -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<Connection.Part>(1));
final Connection connection = new Connection(ParserUtils.extractId(link), link, departureTime, arrivalTime, 0, from, 0, to,
new ArrayList<Connection.Part>(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
{

View file

@ -113,20 +113,121 @@ public class SbbProvider implements NetworkProvider
return uri.toString();
}
private static final Pattern P_PRE_ADDRESS = Pattern.compile(
"<select name=\"(REQ0JourneyStopsS0K|REQ0JourneyStopsZ0K|REQ0JourneyStops1\\.0K)\" accesskey=\"f\".*?>(.*?)</select>", Pattern.DOTALL);
private static final Pattern P_ADDRESSES = Pattern.compile("<option.*?>\\s*(.*?)\\s*</option>", 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<String> fromAddresses = null;
List<String> viaAddresses = null;
List<String> 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<String> addresses = new ArrayList<String>();
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:.*?<td .*?>(.*?)</td>.*?" // from
+ "Datum:.*?<td .*?>.., (\\d{2}\\.\\d{2}\\.\\d{2})</td>.*?" // date
+ "Nach:.*?<td .*?>(.*?)</td>.*?" // to
+ "(?:<a href=\"(http://fahrplan.sbb.ch/bin/query.exe/dn\\?seqnr=\\d+&ident=[\\w\\.]+&REQ0HafasScrollDir=2)\".*?>.*?)?" // linkEarlier
+ "(?:<a href=\"(http://fahrplan.sbb.ch/bin/query.exe/dn\\?seqnr=\\d+&ident=[\\w\\.]+&REQ0HafasScrollDir=1)\".*?>.*?)?" // linkLater
, Pattern.DOTALL);
private static final Pattern P_CONNECTIONS_COARSE = Pattern.compile("<tr class=\"(zebra-row-\\d)\">(.*?)</tr>\n?"//
+ "<tr class=\"\\1\">(.+?)</tr>", 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<Connection> connections = new ArrayList<Connection>();
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<Connection.Part>(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

View file

@ -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<Connection.Part>(1));
final Connection connection = new Connection(ParserUtils.extractId(link), link, departureTime, arrivalTime, 0, from, 0, to,
new ArrayList<Connection.Part>(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);
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}