query first page of connection results only once

git-svn-id: https://public-transport-enabler.googlecode.com/svn/trunk@52 0924bc21-9374-b0fa-ee44-9ff1593b38f0
This commit is contained in:
andreas.schildbach 2010-08-08 12:14:04 +00:00
parent 3a9ea3f93f
commit 515dbf7b13
9 changed files with 132 additions and 118 deletions

View file

@ -158,19 +158,19 @@ public final class BahnProvider implements NetworkProvider
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))"); .compile("(?:(zu dicht beieinander|mehrfach vorhanden oder identisch)|(leider konnte zu Ihrer Anfrage keine Verbindung gefunden werden))");
public CheckConnectionsQueryResult checkConnectionsQuery(final String from, final String via, final String to, final Date date, final boolean dep) public QueryConnectionsResult queryConnections(final String from, final String via, final String to, final Date date, final boolean dep)
throws IOException throws IOException
{ {
final String queryUri = connectionsQueryUri(from, via, to, date, dep); final String uri = connectionsQueryUri(from, via, to, date, dep);
final CharSequence page = ParserUtils.scrape(queryUri); final CharSequence page = ParserUtils.scrape(uri);
final Matcher mError = P_CHECK_CONNECTIONS_ERROR.matcher(page); final Matcher mError = P_CHECK_CONNECTIONS_ERROR.matcher(page);
if (mError.find()) if (mError.find())
{ {
if (mError.group(1) != null) if (mError.group(1) != null)
return CheckConnectionsQueryResult.TOO_CLOSE; return QueryConnectionsResult.TOO_CLOSE;
if (mError.group(2) != null) if (mError.group(2) != null)
return CheckConnectionsQueryResult.NO_CONNECTIONS; return QueryConnectionsResult.NO_CONNECTIONS;
} }
List<String> fromAddresses = null; List<String> fromAddresses = null;
@ -203,9 +203,16 @@ public final class BahnProvider implements NetworkProvider
} }
if (fromAddresses != null || viaAddresses != null || toAddresses != null) if (fromAddresses != null || viaAddresses != null || toAddresses != null)
return new CheckConnectionsQueryResult(CheckConnectionsQueryResult.Status.AMBIGUOUS, queryUri, fromAddresses, viaAddresses, toAddresses); return new QueryConnectionsResult(QueryConnectionsResult.Status.AMBIGUOUS, fromAddresses, viaAddresses, toAddresses);
else else
return new CheckConnectionsQueryResult(CheckConnectionsQueryResult.Status.OK, queryUri, null, null, null); return queryConnections(uri, page);
}
public QueryConnectionsResult queryMoreConnections(final String uri) throws IOException
{
final CharSequence page = ParserUtils.scrape(uri);
return queryConnections(uri, page);
} }
private static final Pattern P_CONNECTIONS_HEAD = Pattern.compile(".*" // private static final Pattern P_CONNECTIONS_HEAD = Pattern.compile(".*" //
@ -221,10 +228,8 @@ public final class BahnProvider implements NetworkProvider
+ "<td class=\"overview iphonepfeil\">(.*?)<br />.*?" // line + "<td class=\"overview iphonepfeil\">(.*?)<br />.*?" // line
, Pattern.DOTALL); , Pattern.DOTALL);
public QueryConnectionsResult queryConnections(final String uri) throws IOException private QueryConnectionsResult queryConnections(final String uri, final CharSequence page) throws IOException
{ {
final CharSequence page = ParserUtils.scrape(uri);
final Matcher mHead = P_CONNECTIONS_HEAD.matcher(page); final Matcher mHead = P_CONNECTIONS_HEAD.matcher(page);
if (mHead.matches()) if (mHead.matches())
{ {
@ -270,7 +275,7 @@ public final class BahnProvider implements NetworkProvider
} }
} }
return new QueryConnectionsResult(from, to, currentDate, linkEarlier, linkLater, connections); return new QueryConnectionsResult(uri, from, to, currentDate, linkEarlier, linkLater, connections);
} }
else else
{ {

View file

@ -1,50 +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 <http://www.gnu.org/licenses/>.
*/
package de.schildbach.pte;
import java.util.List;
/**
* @author Andreas Schildbach
*/
public final class CheckConnectionsQueryResult
{
public enum Status
{
OK, AMBIGUOUS, TOO_CLOSE, NO_CONNECTIONS;
}
public static final CheckConnectionsQueryResult TOO_CLOSE = new CheckConnectionsQueryResult(Status.TOO_CLOSE, null, null, null, null);
public static final CheckConnectionsQueryResult NO_CONNECTIONS = new CheckConnectionsQueryResult(Status.NO_CONNECTIONS, null, null, null, null);
public final Status status;
public final String queryUri;
public final List<String> ambiguousFromAddresses;
public final List<String> ambiguousViaAddresses;
public final List<String> ambiguousToAddresses;
public CheckConnectionsQueryResult(final Status status, final String queryUri, final List<String> ambiguousFromAddresses,
final List<String> ambiguousViaAddresses, final List<String> ambiguousToAddresses)
{
this.status = status;
this.queryUri = queryUri;
this.ambiguousFromAddresses = ambiguousFromAddresses;
this.ambiguousViaAddresses = ambiguousViaAddresses;
this.ambiguousToAddresses = ambiguousToAddresses;
}
}

View file

@ -17,13 +17,14 @@
package de.schildbach.pte; package de.schildbach.pte;
import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
/** /**
* @author Andreas Schildbach * @author Andreas Schildbach
*/ */
public final class Connection public final class Connection implements Serializable
{ {
final public String id; final public String id;
final public String link; final public String link;
@ -83,7 +84,7 @@ public final class Connection
return id.hashCode(); return id.hashCode();
} }
public static interface Part public static interface Part extends Serializable
{ {
} }

View file

@ -174,24 +174,24 @@ public class MvvProvider implements NetworkProvider
private static final Pattern P_CHECK_CONNECTIONS_ERROR = Pattern.compile("(?:(xxxzudichtxxx)|(konnte keine Verbindung gefunden werden))", private static final Pattern P_CHECK_CONNECTIONS_ERROR = Pattern.compile("(?:(xxxzudichtxxx)|(konnte keine Verbindung gefunden werden))",
Pattern.CASE_INSENSITIVE); Pattern.CASE_INSENSITIVE);
public CheckConnectionsQueryResult checkConnectionsQuery(final String from, final String via, final String to, final Date date, final boolean dep) public QueryConnectionsResult queryConnections(final String from, final String via, final String to, final Date date, final boolean dep)
throws IOException throws IOException
{ {
final String queryUri = connectionsQueryUri(from, via, to, date, dep); final String uri = connectionsQueryUri(from, via, to, date, dep);
CharSequence page = ParserUtils.scrape(queryUri); CharSequence page = ParserUtils.scrape(uri);
while (page.length() == 0) while (page.length() == 0)
{ {
System.out.println("Got empty page, retrying..."); System.out.println("Got empty page, retrying...");
page = ParserUtils.scrape(queryUri); page = ParserUtils.scrape(uri);
} }
final Matcher mError = P_CHECK_CONNECTIONS_ERROR.matcher(page); final Matcher mError = P_CHECK_CONNECTIONS_ERROR.matcher(page);
if (mError.find()) if (mError.find())
{ {
if (mError.group(1) != null) if (mError.group(1) != null)
return CheckConnectionsQueryResult.TOO_CLOSE; return QueryConnectionsResult.TOO_CLOSE;
if (mError.group(2) != null) if (mError.group(2) != null)
return CheckConnectionsQueryResult.NO_CONNECTIONS; return QueryConnectionsResult.NO_CONNECTIONS;
} }
List<String> fromAddresses = null; List<String> fromAddresses = null;
@ -224,9 +224,21 @@ public class MvvProvider implements NetworkProvider
} }
if (fromAddresses != null || viaAddresses != null || toAddresses != null) if (fromAddresses != null || viaAddresses != null || toAddresses != null)
return new CheckConnectionsQueryResult(CheckConnectionsQueryResult.Status.AMBIGUOUS, queryUri, fromAddresses, viaAddresses, toAddresses); return new QueryConnectionsResult(QueryConnectionsResult.Status.AMBIGUOUS, fromAddresses, viaAddresses, toAddresses);
else else
return new CheckConnectionsQueryResult(CheckConnectionsQueryResult.Status.OK, queryUri, null, null, null); return queryConnections(uri, page);
}
public QueryConnectionsResult queryMoreConnections(final String uri) throws IOException
{
CharSequence page = ParserUtils.scrape(uri);
while (page.length() == 0)
{
System.out.println("Got empty page, retrying...");
page = ParserUtils.scrape(uri);
}
return queryConnections(uri, page);
} }
private static final Pattern P_CONNECTIONS_HEAD = Pattern.compile(".*<b>Von:[\\xa0\\s]+</b>(.+?)<br />[\\xa0\\s]+" private static final Pattern P_CONNECTIONS_HEAD = Pattern.compile(".*<b>Von:[\\xa0\\s]+</b>(.+?)<br />[\\xa0\\s]+"
@ -244,15 +256,8 @@ public class MvvProvider implements NetworkProvider
+ "|" + "Fußweg.*?Dauer:[\\xa0\\s]+(\\d+):(\\d+)" // + "|" + "Fußweg.*?Dauer:[\\xa0\\s]+(\\d+):(\\d+)" //
+ ").*?", Pattern.DOTALL); + ").*?", Pattern.DOTALL);
public QueryConnectionsResult queryConnections(final String uri) throws IOException private QueryConnectionsResult queryConnections(final String uri, final CharSequence page) throws IOException
{ {
CharSequence page = ParserUtils.scrape(uri);
while (page.length() == 0)
{
System.out.println("Got empty page, retrying...");
page = ParserUtils.scrape(uri);
}
final Matcher mHead = P_CONNECTIONS_HEAD.matcher(page); final Matcher mHead = P_CONNECTIONS_HEAD.matcher(page);
if (mHead.matches()) if (mHead.matches())
{ {
@ -318,7 +323,7 @@ public class MvvProvider implements NetworkProvider
} }
} }
return new QueryConnectionsResult(from, to, currentDate, linkEarlier, linkLater, connections); return new QueryConnectionsResult(uri, from, to, currentDate, linkEarlier, linkLater, connections);
} }
else else
{ {

View file

@ -72,7 +72,7 @@ public interface NetworkProvider
StationLocationResult stationLocation(String stationId) throws IOException; StationLocationResult stationLocation(String stationId) throws IOException;
/** /**
* Check if query is well defined, asking for any ambiguousnesses * Query connections, asking for any ambiguousnesses
* *
* @param from * @param from
* location to route from, mandatory * location to route from, mandatory
@ -84,21 +84,20 @@ public interface NetworkProvider
* desired date for departing, mandatory * desired date for departing, mandatory
* @param dep * @param dep
* date is departure date? {@code true} for departure, {@code false} for arrival * date is departure date? {@code true} for departure, {@code false} for arrival
* @return result object that can contain alternatives to clear up ambiguousnesses * @return result object that can contain alternatives to clear up ambiguousnesses, or contains possible connections
* @throws IOException * @throws IOException
*/ */
CheckConnectionsQueryResult checkConnectionsQuery(String from, String via, String to, Date date, boolean dep) throws IOException; QueryConnectionsResult queryConnections(String from, String via, String to, Date date, boolean dep) throws IOException;
/** /**
* Execute well-defined connections query * Query more connections (e.g. earlier or later)
* *
* @param queryUri * @param uri
* uri constructed by {@link NetworkProvider#connectionsQueryUri} and optionally checked with * uri to query more connections from
* {@link NetworkProvider#checkConnectionsQuery} * @return result object that contains possible connections
* @return result object containing possible connections
* @throws IOException * @throws IOException
*/ */
QueryConnectionsResult queryConnections(String queryUri) throws IOException; QueryConnectionsResult queryMoreConnections(String uri) throws IOException;
/** /**
* Get details about a connection * Get details about a connection

View file

@ -17,14 +17,30 @@
package de.schildbach.pte; package de.schildbach.pte;
import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
/** /**
* @author Andreas Schildbach * @author Andreas Schildbach
*/ */
public final class QueryConnectionsResult public final class QueryConnectionsResult implements Serializable
{ {
public enum Status
{
OK, AMBIGUOUS, TOO_CLOSE, NO_CONNECTIONS;
}
public static final QueryConnectionsResult TOO_CLOSE = new QueryConnectionsResult(Status.TOO_CLOSE, null, null, null);
public static final QueryConnectionsResult NO_CONNECTIONS = new QueryConnectionsResult(Status.NO_CONNECTIONS, null, null, null);
public final Status status;
public final List<String> ambiguousFromAddresses;
public final List<String> ambiguousViaAddresses;
public final List<String> ambiguousToAddresses;
public final String queryUri;
public final String from; public final String from;
public final String to; public final String to;
public final Date currentDate; public final Date currentDate;
@ -32,14 +48,37 @@ public final class QueryConnectionsResult
public final String linkLater; public final String linkLater;
public final List<Connection> connections; public final List<Connection> connections;
public QueryConnectionsResult(final String from, final String to, final Date currentDate, final String linkEarlier, final String linkLater, public QueryConnectionsResult(final Status status, final List<String> ambiguousFromAddresses, final List<String> ambiguousViaAddresses,
final List<Connection> connections) final List<String> ambiguousToAddresses)
{ {
this.status = status;
this.ambiguousFromAddresses = ambiguousFromAddresses;
this.ambiguousViaAddresses = ambiguousViaAddresses;
this.ambiguousToAddresses = ambiguousToAddresses;
this.queryUri = null;
this.from = null;
this.to = null;
this.currentDate = null;
this.linkEarlier = null;
this.linkLater = null;
this.connections = null;
}
public QueryConnectionsResult(final String queryUri, final String from, final String to, final Date currentDate, final String linkEarlier,
final String linkLater, final List<Connection> connections)
{
this.status = Status.OK;
this.queryUri = queryUri;
this.from = from; this.from = from;
this.to = to; this.to = to;
this.currentDate = currentDate; this.currentDate = currentDate;
this.linkEarlier = linkEarlier; this.linkEarlier = linkEarlier;
this.linkLater = linkLater; this.linkLater = linkLater;
this.connections = connections; this.connections = connections;
this.ambiguousFromAddresses = null;
this.ambiguousViaAddresses = null;
this.ambiguousToAddresses = null;
} }
} }

View file

@ -153,6 +153,13 @@ public class RmvProvider implements NetworkProvider
return uri.toString(); return uri.toString();
} }
public QueryConnectionsResult queryMoreConnections(final String uri) throws IOException
{
final CharSequence page = ParserUtils.scrape(uri);
return queryConnections(uri, page);
}
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(
@ -160,19 +167,19 @@ public class RmvProvider implements NetworkProvider
private static final Pattern P_CHECK_CONNECTIONS_ERROR = Pattern.compile( private static final Pattern P_CHECK_CONNECTIONS_ERROR = Pattern.compile(
"(?:(mehrfach vorhanden oder identisch)|(keine Verbindung gefunden werden))", Pattern.CASE_INSENSITIVE); "(?:(mehrfach vorhanden oder identisch)|(keine Verbindung gefunden werden))", Pattern.CASE_INSENSITIVE);
public CheckConnectionsQueryResult checkConnectionsQuery(final String from, final String via, final String to, final Date date, final boolean dep) public QueryConnectionsResult queryConnections(final String from, final String via, final String to, final Date date, final boolean dep)
throws IOException throws IOException
{ {
final String queryUri = connectionsQueryUri(from, via, to, date, dep); final String uri = connectionsQueryUri(from, via, to, date, dep);
final CharSequence page = ParserUtils.scrape(queryUri); final CharSequence page = ParserUtils.scrape(uri);
final Matcher mError = P_CHECK_CONNECTIONS_ERROR.matcher(page); final Matcher mError = P_CHECK_CONNECTIONS_ERROR.matcher(page);
if (mError.find()) if (mError.find())
{ {
if (mError.group(1) != null) if (mError.group(1) != null)
return CheckConnectionsQueryResult.TOO_CLOSE; return QueryConnectionsResult.TOO_CLOSE;
if (mError.group(2) != null) if (mError.group(2) != null)
return CheckConnectionsQueryResult.NO_CONNECTIONS; return QueryConnectionsResult.NO_CONNECTIONS;
} }
List<String> fromAddresses = null; List<String> fromAddresses = null;
@ -206,9 +213,9 @@ public class RmvProvider implements NetworkProvider
} }
if (fromAddresses != null || viaAddresses != null || toAddresses != null) if (fromAddresses != null || viaAddresses != null || toAddresses != null)
return new CheckConnectionsQueryResult(CheckConnectionsQueryResult.Status.AMBIGUOUS, queryUri, fromAddresses, viaAddresses, toAddresses); return new QueryConnectionsResult(QueryConnectionsResult.Status.AMBIGUOUS, fromAddresses, viaAddresses, toAddresses);
else else
return new CheckConnectionsQueryResult(CheckConnectionsQueryResult.Status.OK, queryUri, null, null, null); return queryConnections(uri, page);
} }
private static final Pattern P_CONNECTIONS_HEAD = Pattern.compile(".*" // private static final Pattern P_CONNECTIONS_HEAD = Pattern.compile(".*" //
@ -222,10 +229,8 @@ public class RmvProvider implements NetworkProvider
+ "(\\d+:\\d+)-(\\d+:\\d+)</a>" // + "(\\d+:\\d+)-(\\d+:\\d+)</a>" //
+ "(?:&nbsp;(.+?))?", Pattern.DOTALL); + "(?:&nbsp;(.+?))?", Pattern.DOTALL);
public QueryConnectionsResult queryConnections(final String uri) throws IOException private QueryConnectionsResult queryConnections(final String uri, final CharSequence page) throws IOException
{ {
final CharSequence page = ParserUtils.scrape(uri);
final Matcher mHead = P_CONNECTIONS_HEAD.matcher(page); final Matcher mHead = P_CONNECTIONS_HEAD.matcher(page);
if (mHead.matches()) if (mHead.matches())
{ {
@ -271,7 +276,7 @@ public class RmvProvider implements NetworkProvider
} }
} }
return new QueryConnectionsResult(from, to, currentDate, linkEarlier, linkLater, connections); return new QueryConnectionsResult(uri, from, to, currentDate, linkEarlier, linkLater, connections);
} }
else else
{ {

View file

@ -113,13 +113,18 @@ public class SbbProvider implements NetworkProvider
return uri.toString(); return uri.toString();
} }
public CheckConnectionsQueryResult checkConnectionsQuery(final String from, final String via, final String to, final Date date, final boolean dep) public QueryConnectionsResult queryConnections(final String from, final String via, final String to, final Date date, final boolean dep)
throws IOException throws IOException
{ {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public QueryConnectionsResult queryConnections(final String queryUri) throws IOException public QueryConnectionsResult queryMoreConnections(String uri) throws IOException
{
throw new UnsupportedOperationException();
}
private QueryConnectionsResult queryConnections(final String uri, final CharSequence page) throws IOException
{ {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View file

@ -181,19 +181,19 @@ public final class VbbProvider implements NetworkProvider
private static final Pattern P_CHECK_TO = Pattern.compile("Nach:"); private static final Pattern P_CHECK_TO = Pattern.compile("Nach:");
private static final Pattern P_CHECK_CONNECTIONS_ERROR = Pattern.compile("(zu dicht beieinander)|(keine Verbindung gefunden)"); private static final Pattern P_CHECK_CONNECTIONS_ERROR = Pattern.compile("(zu dicht beieinander)|(keine Verbindung gefunden)");
public CheckConnectionsQueryResult checkConnectionsQuery(final String from, final String via, final String to, final Date date, final boolean dep) public QueryConnectionsResult queryConnections(final String from, final String via, final String to, final Date date, final boolean dep)
throws IOException throws IOException
{ {
final String queryUri = connectionsQueryUri(from, via, to, date, dep); final String uri = connectionsQueryUri(from, via, to, date, dep);
final CharSequence page = ParserUtils.scrape(queryUri); final CharSequence page = ParserUtils.scrape(uri);
final Matcher mError = P_CHECK_CONNECTIONS_ERROR.matcher(page); final Matcher mError = P_CHECK_CONNECTIONS_ERROR.matcher(page);
if (mError.find()) if (mError.find())
{ {
if (mError.group(1) != null) if (mError.group(1) != null)
return CheckConnectionsQueryResult.TOO_CLOSE; return QueryConnectionsResult.TOO_CLOSE;
if (mError.group(2) != null) if (mError.group(2) != null)
return CheckConnectionsQueryResult.NO_CONNECTIONS; return QueryConnectionsResult.NO_CONNECTIONS;
} }
final Matcher mAddress = P_CHECK_ADDRESS.matcher(page); final Matcher mAddress = P_CHECK_ADDRESS.matcher(page);
@ -208,21 +208,28 @@ public final class VbbProvider implements NetworkProvider
if (addresses.isEmpty()) if (addresses.isEmpty())
{ {
return new CheckConnectionsQueryResult(CheckConnectionsQueryResult.Status.OK, queryUri, null, null, null); return queryConnections(uri, page);
} }
else if (P_CHECK_FROM.matcher(page).find()) else if (P_CHECK_FROM.matcher(page).find())
{ {
if (P_CHECK_TO.matcher(page).find()) if (P_CHECK_TO.matcher(page).find())
return new CheckConnectionsQueryResult(CheckConnectionsQueryResult.Status.AMBIGUOUS, queryUri, null, addresses, null); return new QueryConnectionsResult(QueryConnectionsResult.Status.AMBIGUOUS, null, addresses, null);
else else
return new CheckConnectionsQueryResult(CheckConnectionsQueryResult.Status.AMBIGUOUS, queryUri, null, null, addresses); return new QueryConnectionsResult(QueryConnectionsResult.Status.AMBIGUOUS, null, null, addresses);
} }
else else
{ {
return new CheckConnectionsQueryResult(CheckConnectionsQueryResult.Status.AMBIGUOUS, queryUri, addresses, null, null); return new QueryConnectionsResult(QueryConnectionsResult.Status.AMBIGUOUS, addresses, null, null);
} }
} }
public QueryConnectionsResult queryMoreConnections(final String uri) throws IOException
{
final CharSequence page = ParserUtils.scrape(uri);
return queryConnections(uri, page);
}
private static final Pattern P_CONNECTIONS_HEAD = Pattern.compile( private static final Pattern P_CONNECTIONS_HEAD = Pattern.compile(
".*Von: <strong>(.*?)</strong>.*?Nach: <strong>(.*?)</strong>.*?Datum: .., (.*?)<br />.*?" ".*Von: <strong>(.*?)</strong>.*?Nach: <strong>(.*?)</strong>.*?Datum: .., (.*?)<br />.*?"
+ "(?:<a href=\"(/Fahrinfo/bin/query\\.bin/dox.{1,80}ScrollDir=2)\">.*?)?" + "(?:<a href=\"(/Fahrinfo/bin/query\\.bin/dox.{1,80}ScrollDir=2)\">.*?)?"
@ -231,10 +238,8 @@ public final class VbbProvider implements NetworkProvider
private static final Pattern P_CONNECTIONS_FINE = Pattern.compile(".*?<a href=\"(/Fahrinfo/bin/query\\.bin/dox.*?)\">" private static final Pattern P_CONNECTIONS_FINE = Pattern.compile(".*?<a href=\"(/Fahrinfo/bin/query\\.bin/dox.*?)\">"
+ "(\\d\\d:\\d\\d)-(\\d\\d:\\d\\d)</a>&nbsp;&nbsp;(?:\\d+ Umst\\.|([\\w\\d ]+)).*?", Pattern.DOTALL); + "(\\d\\d:\\d\\d)-(\\d\\d:\\d\\d)</a>&nbsp;&nbsp;(?:\\d+ Umst\\.|([\\w\\d ]+)).*?", Pattern.DOTALL);
public QueryConnectionsResult queryConnections(final String uri) throws IOException private QueryConnectionsResult queryConnections(final String uri, final CharSequence page) throws IOException
{ {
final CharSequence page = ParserUtils.scrape(uri);
final Matcher mHead = P_CONNECTIONS_HEAD.matcher(page); final Matcher mHead = P_CONNECTIONS_HEAD.matcher(page);
if (mHead.matches()) if (mHead.matches())
{ {
@ -276,7 +281,7 @@ public final class VbbProvider implements NetworkProvider
} }
} }
return new QueryConnectionsResult(from, to, currentDate, linkEarlier, linkLater, connections); return new QueryConnectionsResult(uri, from, to, currentDate, linkEarlier, linkLater, connections);
} }
else else
{ {