mirror of
https://gitlab.com/oeffi/public-transport-enabler.git
synced 2025-07-07 05:18:46 +00:00
autocomplete using XML-interface for Switzerland and Belgium
git-svn-id: https://public-transport-enabler.googlecode.com/svn/trunk@300 0924bc21-9374-b0fa-ee44-9ff1593b38f0
This commit is contained in:
parent
824bab1b5e
commit
06712bf0eb
9 changed files with 165 additions and 41 deletions
|
@ -18,6 +18,8 @@
|
|||
package de.schildbach.pte;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
@ -25,16 +27,108 @@ import java.util.Map;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlPullParserFactory;
|
||||
|
||||
import de.schildbach.pte.dto.Location;
|
||||
import de.schildbach.pte.dto.LocationType;
|
||||
import de.schildbach.pte.dto.NearbyStationsResult;
|
||||
import de.schildbach.pte.dto.Station;
|
||||
import de.schildbach.pte.util.Color;
|
||||
import de.schildbach.pte.util.ParserUtils;
|
||||
import de.schildbach.pte.util.XmlPullUtil;
|
||||
|
||||
/**
|
||||
* @author Andreas Schildbach
|
||||
*/
|
||||
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 accessId;
|
||||
|
||||
public AbstractHafasProvider(final String autocompleteUri, final String prod, final String accessId)
|
||||
{
|
||||
this.autocompleteUri = autocompleteUri;
|
||||
this.prod = prod;
|
||||
this.accessId = accessId;
|
||||
}
|
||||
|
||||
public List<Location> autocompleteStations(final CharSequence constraint) throws IOException
|
||||
{
|
||||
final String request = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>" //
|
||||
+ "<ReqC ver=\"1.1\" prod=\"" + prod + "\" lang=\"DE\"" + (accessId != null ? " accessId=\"" + accessId + "\"" : "") + ">" //
|
||||
+ "<LocValReq id=\"station\" maxNr=\"10\"><ReqLoc match=\"" + constraint + "\" type=\"ST\"/></LocValReq>" //
|
||||
+ "<LocValReq id=\"poi\" maxNr=\"10\"><ReqLoc match=\"" + constraint + "\" type=\"POI\"/></LocValReq>" //
|
||||
+ "</ReqC>";
|
||||
|
||||
InputStream is = null;
|
||||
try
|
||||
{
|
||||
is = ParserUtils.scrapeInputStream(autocompleteUri, request);
|
||||
|
||||
final List<Location> results = new ArrayList<Location>();
|
||||
|
||||
final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
|
||||
final XmlPullParser pp = factory.newPullParser();
|
||||
pp.setInput(is, DEFAULT_ENCODING);
|
||||
|
||||
XmlPullUtil.jump(pp, "ResC");
|
||||
XmlPullUtil.enter(pp);
|
||||
|
||||
XmlPullUtil.require(pp, "LocValRes");
|
||||
XmlPullUtil.requireAttr(pp, "id", "station");
|
||||
XmlPullUtil.enter(pp);
|
||||
|
||||
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));
|
||||
|
||||
XmlPullUtil.skipTree(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);
|
||||
|
||||
return results;
|
||||
}
|
||||
catch (final XmlPullParserException x)
|
||||
{
|
||||
throw new RuntimeException(x);
|
||||
}
|
||||
catch (final SocketTimeoutException x)
|
||||
{
|
||||
throw new RuntimeException(x);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (is != null)
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
|
||||
private final static Pattern P_NEARBY_COARSE = Pattern.compile("<tr class=\"(zebra[^\"]*)\">(.*?)</tr>", Pattern.DOTALL);
|
||||
private final static Pattern P_NEARBY_FINE_COORDS = Pattern
|
||||
.compile("&REQMapRoute0\\.Location0\\.X=(-?\\d+)&REQMapRoute0\\.Location0\\.Y=(-?\\d+)&");
|
||||
|
|
|
@ -46,6 +46,11 @@ public class NasaProvider extends AbstractHafasProvider
|
|||
|
||||
private static final long PARSER_DAY_ROLLOVER_THRESHOLD_MS = 12 * 60 * 60 * 1000;
|
||||
|
||||
public NasaProvider()
|
||||
{
|
||||
super(null, null, null);
|
||||
}
|
||||
|
||||
public boolean hasCapabilities(final Capability... capabilities)
|
||||
{
|
||||
for (final Capability capability : capabilities)
|
||||
|
@ -55,6 +60,7 @@ public class NasaProvider extends AbstractHafasProvider
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Location> autocompleteStations(CharSequence constraint) throws IOException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
|
|
|
@ -48,6 +48,11 @@ public class OebbProvider extends AbstractHafasProvider
|
|||
public static final String NETWORK_ID = "fahrplan.oebb.at";
|
||||
private static final String API_BASE = "http://fahrplan.oebb.at/bin/";
|
||||
|
||||
public OebbProvider()
|
||||
{
|
||||
super(null, null, null);
|
||||
}
|
||||
|
||||
public boolean hasCapabilities(final Capability... capabilities)
|
||||
{
|
||||
for (final Capability capability : capabilities)
|
||||
|
@ -63,6 +68,7 @@ public class OebbProvider extends AbstractHafasProvider
|
|||
private static final Pattern P_AUTOCOMPLETE_JSON = Pattern.compile("SLs\\.sls=(.*?);SLs\\.showSuggestion\\(\\);", Pattern.DOTALL);
|
||||
private static final Pattern P_AUTOCOMPLETE_ID = Pattern.compile(".*?@L=(\\d+)@.*?");
|
||||
|
||||
@Override
|
||||
public List<Location> autocompleteStations(final CharSequence constraint) throws IOException
|
||||
{
|
||||
final String uri = String.format(AUTOCOMPLETE_URI, ParserUtils.urlEncode(constraint.toString(), ENCODING));
|
||||
|
|
|
@ -51,6 +51,11 @@ public class RmvProvider extends AbstractHafasProvider
|
|||
|
||||
private static final long PARSER_DAY_ROLLOVER_THRESHOLD_MS = 12 * 60 * 60 * 1000;
|
||||
|
||||
public RmvProvider()
|
||||
{
|
||||
super(null, null, null);
|
||||
}
|
||||
|
||||
public boolean hasCapabilities(final Capability... capabilities)
|
||||
{
|
||||
for (final Capability capability : capabilities)
|
||||
|
@ -66,6 +71,7 @@ public class RmvProvider extends AbstractHafasProvider
|
|||
private static final Pattern P_MULTI_NAME = Pattern.compile("<a href=\"/auskunft/bin/jp/stboard.exe/dox.*?input=(\\d+)&.*?\">\\s*(.*?)\\s*</a>",
|
||||
Pattern.DOTALL);
|
||||
|
||||
@Override
|
||||
public List<Location> autocompleteStations(final CharSequence constraint) throws IOException
|
||||
{
|
||||
final CharSequence page = ParserUtils.scrape(NAME_URL + ParserUtils.urlEncode(constraint.toString()));
|
||||
|
|
|
@ -48,6 +48,11 @@ public class SbbProvider extends AbstractHafasProvider
|
|||
|
||||
private static final long PARSER_DAY_ROLLOVER_THRESHOLD_MS = 12 * 60 * 60 * 1000;
|
||||
|
||||
public SbbProvider()
|
||||
{
|
||||
super("http://fahrplan.sbb.ch/bin/extxml.exe", "iPhone3.1", "MJXZ841ZfsmqqmSymWhBPy5dMNoqoGsHInHbWJQ5PTUZOJ1rLTkn8vVZOZDFfSe");
|
||||
}
|
||||
|
||||
public boolean hasCapabilities(final Capability... capabilities)
|
||||
{
|
||||
for (final Capability capability : capabilities)
|
||||
|
@ -57,35 +62,6 @@ public class SbbProvider extends AbstractHafasProvider
|
|||
return false;
|
||||
}
|
||||
|
||||
private static final String NAME_URL = API_BASE + "bhftafel.exe/dox?input=";
|
||||
private static final Pattern P_SINGLE_NAME = Pattern.compile(".*?<input type=\"hidden\" name=\"input\" value=\"(.+?)#(\\d+)\" />.*",
|
||||
Pattern.DOTALL);
|
||||
private static final Pattern P_MULTI_NAME = Pattern.compile("<a href=\"http://fahrplan\\.sbb\\.ch/bin/bhftafel\\.exe/dox\\?input=(\\d+).*?\">\n?" //
|
||||
+ "(.*?)\n?" //
|
||||
+ "</a>", Pattern.DOTALL);
|
||||
|
||||
public List<Location> autocompleteStations(final CharSequence constraint) throws IOException
|
||||
{
|
||||
final CharSequence page = ParserUtils.scrape(NAME_URL + ParserUtils.urlEncode(constraint.toString()));
|
||||
|
||||
final List<Location> results = new ArrayList<Location>();
|
||||
|
||||
final Matcher mSingle = P_SINGLE_NAME.matcher(page);
|
||||
if (mSingle.matches())
|
||||
{
|
||||
results.add(new Location(LocationType.STATION, Integer.parseInt(mSingle.group(2)), 0, 0, ParserUtils.resolveEntities(mSingle.group(1))));
|
||||
}
|
||||
else
|
||||
{
|
||||
final Matcher mMulti = P_MULTI_NAME.matcher(page);
|
||||
while (mMulti.find())
|
||||
results
|
||||
.add(new Location(LocationType.STATION, Integer.parseInt(mMulti.group(1)), 0, 0, ParserUtils.resolveEntities(mMulti.group(2))));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private final static String NEARBY_URI = API_BASE + "bhftafel.exe/dn?input=%s&distance=50&near=Anzeigen";
|
||||
|
||||
@Override
|
||||
|
|
|
@ -43,6 +43,13 @@ 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";
|
||||
|
||||
public SncbProvider()
|
||||
{
|
||||
super(AUTOCOMPLETE_URI, "irail", null);
|
||||
}
|
||||
|
||||
public boolean hasCapabilities(final Capability... capabilities)
|
||||
{
|
||||
for (final Capability capability : capabilities)
|
||||
|
@ -52,11 +59,6 @@ public class SncbProvider extends AbstractHafasProvider
|
|||
return false;
|
||||
}
|
||||
|
||||
public List<Location> autocompleteStations(final CharSequence constraint) throws IOException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private final String NEARBY_URI = "http://hari.b-rail.be/HAFAS/bin/stboard.exe/en?input=%s&distance=50&near=Anzeigen";
|
||||
|
||||
@Override
|
||||
|
|
|
@ -46,6 +46,11 @@ public class VgsProvider extends AbstractHafasProvider
|
|||
|
||||
private static final long PARSER_DAY_ROLLOVER_THRESHOLD_MS = 12 * 60 * 60 * 1000;
|
||||
|
||||
public VgsProvider()
|
||||
{
|
||||
super(null, null, null);
|
||||
}
|
||||
|
||||
public boolean hasCapabilities(final Capability... capabilities)
|
||||
{
|
||||
for (final Capability capability : capabilities)
|
||||
|
@ -55,6 +60,7 @@ public class VgsProvider extends AbstractHafasProvider
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Location> autocompleteStations(CharSequence constraint) throws IOException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
|
|
|
@ -39,6 +39,22 @@ public class SbbProviderLiveTest
|
|||
private SbbProvider provider = new SbbProvider();
|
||||
private static final String ALL_PRODUCTS = "IRSUTBFC";
|
||||
|
||||
@Test
|
||||
public void autoComplete() throws Exception
|
||||
{
|
||||
final List<Location> autocompletes = provider.autocompleteStations("haupt");
|
||||
|
||||
list(autocompletes);
|
||||
}
|
||||
|
||||
private void list(final List<Location> autocompletes)
|
||||
{
|
||||
System.out.print(autocompletes.size() + " ");
|
||||
for (final Location autocomplete : autocompletes)
|
||||
System.out.print(autocomplete.toDebugString() + " ");
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nearbyStation() throws Exception
|
||||
{
|
||||
|
@ -90,11 +106,4 @@ public class SbbProviderLiveTest
|
|||
for (final Connection connection : moreResult.connections)
|
||||
System.out.println(provider.getConnectionDetails(connection.link));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoComplete() throws Exception
|
||||
{
|
||||
final List<Location> result = provider.autocompleteStations("haupt");
|
||||
System.out.println(result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,12 @@
|
|||
*/
|
||||
package de.schildbach.pte.live;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import de.schildbach.pte.SncbProvider;
|
||||
import de.schildbach.pte.dto.Location;
|
||||
import de.schildbach.pte.dto.NearbyStationsResult;
|
||||
|
||||
/**
|
||||
|
@ -28,6 +31,22 @@ public class SncbProviderLiveTest
|
|||
{
|
||||
private final SncbProvider provider = new SncbProvider();
|
||||
|
||||
@Test
|
||||
public void autocompleteIncomplete() throws Exception
|
||||
{
|
||||
final List<Location> autocompletes = provider.autocompleteStations("Brussel S");
|
||||
|
||||
list(autocompletes);
|
||||
}
|
||||
|
||||
private void list(final List<Location> autocompletes)
|
||||
{
|
||||
System.out.print(autocompletes.size() + " ");
|
||||
for (final Location autocomplete : autocompletes)
|
||||
System.out.print(autocomplete.toDebugString() + " ");
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nearbyStation() throws Exception
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue