diff --git a/src/de/schildbach/pte/AbstractHafasProvider.java b/src/de/schildbach/pte/AbstractHafasProvider.java index acc5a85a..8472e51c 100644 --- a/src/de/schildbach/pte/AbstractHafasProvider.java +++ b/src/de/schildbach/pte/AbstractHafasProvider.java @@ -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 autocompleteStations(final CharSequence constraint) throws IOException + { + final String request = "" // + + "" // + + "" // + + "" // + + ""; + + InputStream is = null; + try + { + is = ParserUtils.scrapeInputStream(autocompleteUri, request); + + final List results = new ArrayList(); + + 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("(.*?)", Pattern.DOTALL); private final static Pattern P_NEARBY_FINE_COORDS = Pattern .compile("&REQMapRoute0\\.Location0\\.X=(-?\\d+)&REQMapRoute0\\.Location0\\.Y=(-?\\d+)&"); diff --git a/src/de/schildbach/pte/NasaProvider.java b/src/de/schildbach/pte/NasaProvider.java index 70628ae7..cd3ff13f 100644 --- a/src/de/schildbach/pte/NasaProvider.java +++ b/src/de/schildbach/pte/NasaProvider.java @@ -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 autocompleteStations(CharSequence constraint) throws IOException { throw new UnsupportedOperationException(); diff --git a/src/de/schildbach/pte/OebbProvider.java b/src/de/schildbach/pte/OebbProvider.java index fa6061ad..79f49b18 100644 --- a/src/de/schildbach/pte/OebbProvider.java +++ b/src/de/schildbach/pte/OebbProvider.java @@ -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 autocompleteStations(final CharSequence constraint) throws IOException { final String uri = String.format(AUTOCOMPLETE_URI, ParserUtils.urlEncode(constraint.toString(), ENCODING)); diff --git a/src/de/schildbach/pte/RmvProvider.java b/src/de/schildbach/pte/RmvProvider.java index 58e04641..70584256 100644 --- a/src/de/schildbach/pte/RmvProvider.java +++ b/src/de/schildbach/pte/RmvProvider.java @@ -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("\\s*(.*?)\\s*", Pattern.DOTALL); + @Override public List autocompleteStations(final CharSequence constraint) throws IOException { final CharSequence page = ParserUtils.scrape(NAME_URL + ParserUtils.urlEncode(constraint.toString())); diff --git a/src/de/schildbach/pte/SbbProvider.java b/src/de/schildbach/pte/SbbProvider.java index 447e865c..c84d5102 100644 --- a/src/de/schildbach/pte/SbbProvider.java +++ b/src/de/schildbach/pte/SbbProvider.java @@ -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(".*?.*", - Pattern.DOTALL); - private static final Pattern P_MULTI_NAME = Pattern.compile("\n?" // - + "(.*?)\n?" // - + "", Pattern.DOTALL); - - public List autocompleteStations(final CharSequence constraint) throws IOException - { - final CharSequence page = ParserUtils.scrape(NAME_URL + ParserUtils.urlEncode(constraint.toString())); - - final List results = new ArrayList(); - - 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 diff --git a/src/de/schildbach/pte/SncbProvider.java b/src/de/schildbach/pte/SncbProvider.java index 83593896..3d7b1123 100644 --- a/src/de/schildbach/pte/SncbProvider.java +++ b/src/de/schildbach/pte/SncbProvider.java @@ -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 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 diff --git a/src/de/schildbach/pte/VgsProvider.java b/src/de/schildbach/pte/VgsProvider.java index e3846df4..d6a7053a 100644 --- a/src/de/schildbach/pte/VgsProvider.java +++ b/src/de/schildbach/pte/VgsProvider.java @@ -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 autocompleteStations(CharSequence constraint) throws IOException { throw new UnsupportedOperationException(); diff --git a/test/de/schildbach/pte/live/SbbProviderLiveTest.java b/test/de/schildbach/pte/live/SbbProviderLiveTest.java index d54936b1..0cec0a35 100644 --- a/test/de/schildbach/pte/live/SbbProviderLiveTest.java +++ b/test/de/schildbach/pte/live/SbbProviderLiveTest.java @@ -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 autocompletes = provider.autocompleteStations("haupt"); + + list(autocompletes); + } + + private void list(final List 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 result = provider.autocompleteStations("haupt"); - System.out.println(result); - } } diff --git a/test/de/schildbach/pte/live/SncbProviderLiveTest.java b/test/de/schildbach/pte/live/SncbProviderLiveTest.java index 78cae5c6..73a907ac 100644 --- a/test/de/schildbach/pte/live/SncbProviderLiveTest.java +++ b/test/de/schildbach/pte/live/SncbProviderLiveTest.java @@ -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 autocompletes = provider.autocompleteStations("Brussel S"); + + list(autocompletes); + } + + private void list(final List 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 {