mirror of
https://gitlab.com/oeffi/public-transport-enabler.git
synced 2025-07-07 22:18:49 +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;
|
package de.schildbach.pte;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.SocketTimeoutException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -25,16 +27,108 @@ import java.util.Map;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
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.NearbyStationsResult;
|
||||||
import de.schildbach.pte.dto.Station;
|
import de.schildbach.pte.dto.Station;
|
||||||
import de.schildbach.pte.util.Color;
|
import de.schildbach.pte.util.Color;
|
||||||
import de.schildbach.pte.util.ParserUtils;
|
import de.schildbach.pte.util.ParserUtils;
|
||||||
|
import de.schildbach.pte.util.XmlPullUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Andreas Schildbach
|
* @author Andreas Schildbach
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractHafasProvider implements NetworkProvider
|
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_COARSE = Pattern.compile("<tr class=\"(zebra[^\"]*)\">(.*?)</tr>", Pattern.DOTALL);
|
||||||
private final static Pattern P_NEARBY_FINE_COORDS = Pattern
|
private final static Pattern P_NEARBY_FINE_COORDS = Pattern
|
||||||
.compile("&REQMapRoute0\\.Location0\\.X=(-?\\d+)&REQMapRoute0\\.Location0\\.Y=(-?\\d+)&");
|
.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;
|
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)
|
public boolean hasCapabilities(final Capability... capabilities)
|
||||||
{
|
{
|
||||||
for (final Capability capability : capabilities)
|
for (final Capability capability : capabilities)
|
||||||
|
@ -55,6 +60,7 @@ public class NasaProvider extends AbstractHafasProvider
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public List<Location> autocompleteStations(CharSequence constraint) throws IOException
|
public List<Location> autocompleteStations(CharSequence constraint) throws IOException
|
||||||
{
|
{
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
|
|
@ -48,6 +48,11 @@ public class OebbProvider extends AbstractHafasProvider
|
||||||
public static final String NETWORK_ID = "fahrplan.oebb.at";
|
public static final String NETWORK_ID = "fahrplan.oebb.at";
|
||||||
private static final String API_BASE = "http://fahrplan.oebb.at/bin/";
|
private static final String API_BASE = "http://fahrplan.oebb.at/bin/";
|
||||||
|
|
||||||
|
public OebbProvider()
|
||||||
|
{
|
||||||
|
super(null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasCapabilities(final Capability... capabilities)
|
public boolean hasCapabilities(final Capability... capabilities)
|
||||||
{
|
{
|
||||||
for (final Capability 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_JSON = Pattern.compile("SLs\\.sls=(.*?);SLs\\.showSuggestion\\(\\);", Pattern.DOTALL);
|
||||||
private static final Pattern P_AUTOCOMPLETE_ID = Pattern.compile(".*?@L=(\\d+)@.*?");
|
private static final Pattern P_AUTOCOMPLETE_ID = Pattern.compile(".*?@L=(\\d+)@.*?");
|
||||||
|
|
||||||
|
@Override
|
||||||
public List<Location> autocompleteStations(final CharSequence constraint) throws IOException
|
public List<Location> autocompleteStations(final CharSequence constraint) throws IOException
|
||||||
{
|
{
|
||||||
final String uri = String.format(AUTOCOMPLETE_URI, ParserUtils.urlEncode(constraint.toString(), ENCODING));
|
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;
|
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)
|
public boolean hasCapabilities(final Capability... capabilities)
|
||||||
{
|
{
|
||||||
for (final Capability 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>",
|
private static final Pattern P_MULTI_NAME = Pattern.compile("<a href=\"/auskunft/bin/jp/stboard.exe/dox.*?input=(\\d+)&.*?\">\\s*(.*?)\\s*</a>",
|
||||||
Pattern.DOTALL);
|
Pattern.DOTALL);
|
||||||
|
|
||||||
|
@Override
|
||||||
public List<Location> autocompleteStations(final CharSequence constraint) throws IOException
|
public List<Location> autocompleteStations(final CharSequence constraint) throws IOException
|
||||||
{
|
{
|
||||||
final CharSequence page = ParserUtils.scrape(NAME_URL + ParserUtils.urlEncode(constraint.toString()));
|
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;
|
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)
|
public boolean hasCapabilities(final Capability... capabilities)
|
||||||
{
|
{
|
||||||
for (final Capability capability : capabilities)
|
for (final Capability capability : capabilities)
|
||||||
|
@ -57,35 +62,6 @@ public class SbbProvider extends AbstractHafasProvider
|
||||||
return false;
|
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";
|
private final static String NEARBY_URI = API_BASE + "bhftafel.exe/dn?input=%s&distance=50&near=Anzeigen";
|
||||||
|
|
||||||
@Override
|
@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 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)
|
public boolean hasCapabilities(final Capability... capabilities)
|
||||||
{
|
{
|
||||||
for (final Capability capability : capabilities)
|
for (final Capability capability : capabilities)
|
||||||
|
@ -52,11 +59,6 @@ public class SncbProvider extends AbstractHafasProvider
|
||||||
return false;
|
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";
|
private final String NEARBY_URI = "http://hari.b-rail.be/HAFAS/bin/stboard.exe/en?input=%s&distance=50&near=Anzeigen";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -46,6 +46,11 @@ public class VgsProvider extends AbstractHafasProvider
|
||||||
|
|
||||||
private static final long PARSER_DAY_ROLLOVER_THRESHOLD_MS = 12 * 60 * 60 * 1000;
|
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)
|
public boolean hasCapabilities(final Capability... capabilities)
|
||||||
{
|
{
|
||||||
for (final Capability capability : capabilities)
|
for (final Capability capability : capabilities)
|
||||||
|
@ -55,6 +60,7 @@ public class VgsProvider extends AbstractHafasProvider
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public List<Location> autocompleteStations(CharSequence constraint) throws IOException
|
public List<Location> autocompleteStations(CharSequence constraint) throws IOException
|
||||||
{
|
{
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
|
|
@ -39,6 +39,22 @@ public class SbbProviderLiveTest
|
||||||
private SbbProvider provider = new SbbProvider();
|
private SbbProvider provider = new SbbProvider();
|
||||||
private static final String ALL_PRODUCTS = "IRSUTBFC";
|
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
|
@Test
|
||||||
public void nearbyStation() throws Exception
|
public void nearbyStation() throws Exception
|
||||||
{
|
{
|
||||||
|
@ -90,11 +106,4 @@ public class SbbProviderLiveTest
|
||||||
for (final Connection connection : moreResult.connections)
|
for (final Connection connection : moreResult.connections)
|
||||||
System.out.println(provider.getConnectionDetails(connection.link));
|
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;
|
package de.schildbach.pte.live;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import de.schildbach.pte.SncbProvider;
|
import de.schildbach.pte.SncbProvider;
|
||||||
|
import de.schildbach.pte.dto.Location;
|
||||||
import de.schildbach.pte.dto.NearbyStationsResult;
|
import de.schildbach.pte.dto.NearbyStationsResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,6 +31,22 @@ public class SncbProviderLiveTest
|
||||||
{
|
{
|
||||||
private final SncbProvider provider = new SncbProvider();
|
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
|
@Test
|
||||||
public void nearbyStation() throws Exception
|
public void nearbyStation() throws Exception
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue