From b4bf75d875aa0575f55d9846033293e17351468d Mon Sep 17 00:00:00 2001 From: "andreas.schildbach" Date: Wed, 6 Oct 2010 11:36:18 +0000 Subject: [PATCH] autocomplete for all efa based providers git-svn-id: https://public-transport-enabler.googlecode.com/svn/trunk@245 0924bc21-9374-b0fa-ee44-9ff1593b38f0 --- .../schildbach/pte/AbstractEfaProvider.java | 91 +++++++++++++------ src/de/schildbach/pte/GvhProvider.java | 5 +- src/de/schildbach/pte/LinzProvider.java | 7 +- src/de/schildbach/pte/VrnProvider.java | 8 +- src/de/schildbach/pte/VrrProvider.java | 7 +- src/de/schildbach/pte/dto/Autocomplete.java | 29 +++++- .../pte/live/GvhProviderLiveTest.java | 32 +++++++ .../pte/live/LinzProviderLiveTest.java | 34 +++++++ .../pte/live/VrnProviderLiveTest.java | 43 +++++++++ .../pte/live/VrrProviderLiveTest.java | 35 +++++++ 10 files changed, 250 insertions(+), 41 deletions(-) diff --git a/src/de/schildbach/pte/AbstractEfaProvider.java b/src/de/schildbach/pte/AbstractEfaProvider.java index 9185c3b9..035438af 100644 --- a/src/de/schildbach/pte/AbstractEfaProvider.java +++ b/src/de/schildbach/pte/AbstractEfaProvider.java @@ -26,7 +26,6 @@ import java.util.GregorianCalendar; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.regex.Matcher; import java.util.regex.Pattern; import org.xmlpull.v1.XmlPullParser; @@ -47,40 +46,76 @@ import de.schildbach.pte.util.XmlPullUtil; */ public abstract class AbstractEfaProvider implements NetworkProvider { - private static final Pattern P_AUTOCOMPLETE = Pattern.compile("" // - + "(?:" // - + "]* nameWithPlace=\"([^\"]*)\"" // - + "|" // - + "]* locality=\"([^\"]*)\"" // - + ")"); - protected abstract String autocompleteUri(final CharSequence constraint); public List autocompleteStations(final CharSequence constraint) throws IOException { - final CharSequence page = ParserUtils.scrape(autocompleteUri(constraint)); + final String uri = autocompleteUri(constraint); - final List results = new ArrayList(); - - final Matcher m = P_AUTOCOMPLETE.matcher(page); - while (m.find()) + try { - if (m.group(1) != null) - { - final int sId = Integer.parseInt(m.group(1)); - // final double sLon = latLonToDouble(Integer.parseInt(mAutocomplete.group(2))); - // final double sLat = latLonToDouble(Integer.parseInt(mAutocomplete.group(3))); - final String sName = m.group(4).trim(); - results.add(new Autocomplete(LocationType.STATION, sId, sName)); - } - else if (m.group(5) != null) - { - final String sName = m.group(5).trim(); - results.add(new Autocomplete(LocationType.ANY, 0, sName)); - } - } + final CharSequence page = ParserUtils.scrape(uri); + final List results = new ArrayList(); - return results; + final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null); + final XmlPullParser pp = factory.newPullParser(); + pp.setInput(new StringReader(page.toString())); + + // parse odv name elements + XmlPullUtil.jumpToStartTag(pp, null, "itdOdv"); + final String usage = pp.getAttributeValue(null, "usage"); + if (!"origin".equals(usage)) + throw new IllegalStateException(); + XmlPullUtil.nextStartTagInsideTree(pp, null, "itdOdvName"); + final String nameState = pp.getAttributeValue(null, "state"); + if ("list".equals(nameState)) + { + while (XmlPullUtil.nextStartTagInsideTree(pp, null, "odvNameElem")) + { + final String type = pp.getAttributeValue(null, "anyType"); + int id = Integer.parseInt(pp.getAttributeValue(null, "id")); + if (id < 0) + id = 0; + final String name = normalizeLocationName(pp.nextText()); + results.add(new Autocomplete(type(type), id, name)); + } + } + + // parse assigned stops + if (XmlPullUtil.jumpToStartTag(pp, null, "itdOdvAssignedStops")) + { + while (XmlPullUtil.nextStartTagInsideTree(pp, null, "itdOdvAssignedStop")) + { + final int id = Integer.parseInt(pp.getAttributeValue(null, "stopID")); + final String name = normalizeLocationName(pp.getAttributeValue(null, "nameWithPlace")); + + final Autocomplete autocomplete = new Autocomplete(LocationType.STATION, id, name); + if (!results.contains(autocomplete)) + results.add(autocomplete); + + XmlPullUtil.skipRestOfTree(pp); + } + } + + return results; + } + catch (final XmlPullParserException x) + { + throw new RuntimeException(x); + } + } + + private static LocationType type(final String type) + { + if (type.equals("stop")) + return LocationType.STATION; + if (type.equals("poi")) + return LocationType.POI; + if (type.equals("street")) + return LocationType.ADDRESS; + if (type.equals("loc")) + return LocationType.ANY; + throw new IllegalArgumentException("unknown type: " + type); } private static final Pattern P_NEARBY_MESSAGES = Pattern.compile("(unsere Server zur Zeit ausgelastet)"); diff --git a/src/de/schildbach/pte/GvhProvider.java b/src/de/schildbach/pte/GvhProvider.java index f9e717e6..057005d6 100644 --- a/src/de/schildbach/pte/GvhProvider.java +++ b/src/de/schildbach/pte/GvhProvider.java @@ -42,13 +42,12 @@ public class GvhProvider extends AbstractEfaProvider } private static final String AUTOCOMPLETE_URI = API_BASE - + "XML_STOPFINDER_REQUEST?outputFormat=XML&coordOutputFormat=WGS84&name_sf=%s&type_sf=any"; - private static final String ENCODING = "ISO-8859-1"; + + "XSLT_TRIP_REQUEST2?outputFormat=XML&locationServerActive=1&type_origin=any&name_origin=%s"; @Override protected String autocompleteUri(final CharSequence constraint) { - return String.format(AUTOCOMPLETE_URI, ParserUtils.urlEncode(constraint.toString(), ENCODING)); + return String.format(AUTOCOMPLETE_URI, ParserUtils.urlEncode(constraint.toString(), "ISO-8859-1")); } private static final String NEARBY_STATION_URI = API_BASE diff --git a/src/de/schildbach/pte/LinzProvider.java b/src/de/schildbach/pte/LinzProvider.java index 5311260b..38a25093 100644 --- a/src/de/schildbach/pte/LinzProvider.java +++ b/src/de/schildbach/pte/LinzProvider.java @@ -41,15 +41,12 @@ public class LinzProvider extends AbstractEfaProvider return false; } - private static final String AUTOCOMPLETE_URI = API_BASE + "XML_STOPFINDER_REQUEST" - + "?outputFormat=XML&coordOutputFormat=WGS84&name_sf=%s&type_sf=%s"; - private static final String AUTOCOMPLETE_TYPE = "any"; // any, stop, street, poi - private static final String ENCODING = "ISO-8859-1"; + private static final String AUTOCOMPLETE_URI = API_BASE + "XSLT_TRIP_REQUEST2?outputFormat=XML&name_origin=%s&type_origin=any"; @Override protected String autocompleteUri(final CharSequence constraint) { - return String.format(AUTOCOMPLETE_URI, ParserUtils.urlEncode(constraint.toString(), ENCODING), AUTOCOMPLETE_TYPE); + return String.format(AUTOCOMPLETE_URI, ParserUtils.urlEncode(constraint.toString(), "ISO-8859-1")); } private static final String NEARBY_LATLON_URI = API_BASE diff --git a/src/de/schildbach/pte/VrnProvider.java b/src/de/schildbach/pte/VrnProvider.java index eb1fcee3..e435e76b 100644 --- a/src/de/schildbach/pte/VrnProvider.java +++ b/src/de/schildbach/pte/VrnProvider.java @@ -21,6 +21,7 @@ import java.util.Date; import de.schildbach.pte.dto.GetConnectionDetailsResult; import de.schildbach.pte.dto.QueryConnectionsResult; +import de.schildbach.pte.util.ParserUtils; /** * @author Andreas Schildbach @@ -39,10 +40,13 @@ public class VrnProvider extends AbstractEfaProvider return false; } + private static final String AUTOCOMPLETE_URI = API_BASE + + "XSLT_TRIP_REQUEST2?outputFormat=XML&locationServerActive=1&type_origin=any&name_origin=%s"; + @Override - protected String autocompleteUri(CharSequence constraint) + protected String autocompleteUri(final CharSequence constraint) { - throw new UnsupportedOperationException(); + return String.format(AUTOCOMPLETE_URI, ParserUtils.urlEncode(constraint.toString(), "ISO-8859-1")); } @Override diff --git a/src/de/schildbach/pte/VrrProvider.java b/src/de/schildbach/pte/VrrProvider.java index 36d282e8..3f6e152f 100644 --- a/src/de/schildbach/pte/VrrProvider.java +++ b/src/de/schildbach/pte/VrrProvider.java @@ -21,6 +21,7 @@ import java.util.Date; import de.schildbach.pte.dto.GetConnectionDetailsResult; import de.schildbach.pte.dto.QueryConnectionsResult; +import de.schildbach.pte.util.ParserUtils; /** * @author Andreas Schildbach @@ -39,10 +40,12 @@ public class VrrProvider extends AbstractEfaProvider return false; } + private static final String AUTOCOMPLETE_URI = API_BASE + "XSLT_TRIP_REQUEST2?outputFormat=XML&type_origin=any&name_origin=%s"; + @Override - protected String autocompleteUri(CharSequence constraint) + protected String autocompleteUri(final CharSequence constraint) { - throw new UnsupportedOperationException(); + return String.format(AUTOCOMPLETE_URI, ParserUtils.urlEncode(constraint.toString(), "ISO-8859-1")); } @Override diff --git a/src/de/schildbach/pte/dto/Autocomplete.java b/src/de/schildbach/pte/dto/Autocomplete.java index 41d8c417..3e60619b 100644 --- a/src/de/schildbach/pte/dto/Autocomplete.java +++ b/src/de/schildbach/pte/dto/Autocomplete.java @@ -37,7 +37,34 @@ public final class Autocomplete @Override public String toString() { - // return getClass().getName() + "[" + locationId + " " + location + "]"; return location; // invoked by AutoCompleteTextView in landscape orientation } + + public String toDebugString() + { + return "[" + locationType + " " + locationId + " '" + location + "']"; + } + + @Override + public boolean equals(Object o) + { + if (o == this) + return true; + if (!(o instanceof Autocomplete)) + return false; + final Autocomplete other = (Autocomplete) o; + if (this.locationType != other.locationType) + return false; + if (this.locationId != other.locationId) + return false; + if (this.locationId != 0) + return true; + return this.location.equals(other.location); + } + + @Override + public int hashCode() + { + return locationType.hashCode(); // FIXME not very discriminative + } } diff --git a/test/de/schildbach/pte/live/GvhProviderLiveTest.java b/test/de/schildbach/pte/live/GvhProviderLiveTest.java index ede45cff..2814ddf8 100644 --- a/test/de/schildbach/pte/live/GvhProviderLiveTest.java +++ b/test/de/schildbach/pte/live/GvhProviderLiveTest.java @@ -31,6 +31,38 @@ public class GvhProviderLiveTest { private final GvhProvider provider = new GvhProvider(); + @Test + public void autocompleteIncomplete() throws Exception + { + final List autocompletes = provider.autocompleteStations("Kur"); + + list(autocompletes); + } + + @Test + public void autocompleteIdentified() throws Exception + { + final List autocompletes = provider.autocompleteStations("Hannover, Hannoversche Straße"); + + list(autocompletes); + } + + @Test + public void autocompleteCity() throws Exception + { + final List autocompletes = provider.autocompleteStations("Hannover"); + + list(autocompletes); + } + + private void list(final List autocompletes) + { + System.out.print(autocompletes.size() + " "); + for (final Autocomplete autocomplete : autocompletes) + System.out.print(autocomplete.toDebugString() + " "); + System.out.println(); + } + @Test public void autocomplete() throws Exception { diff --git a/test/de/schildbach/pte/live/LinzProviderLiveTest.java b/test/de/schildbach/pte/live/LinzProviderLiveTest.java index e22c56f8..5e226891 100644 --- a/test/de/schildbach/pte/live/LinzProviderLiveTest.java +++ b/test/de/schildbach/pte/live/LinzProviderLiveTest.java @@ -18,12 +18,14 @@ package de.schildbach.pte.live; import java.util.Date; +import java.util.List; import org.junit.Test; import de.schildbach.pte.LinzProvider; import de.schildbach.pte.NetworkProvider.LocationType; import de.schildbach.pte.NetworkProvider.WalkSpeed; +import de.schildbach.pte.dto.Autocomplete; import de.schildbach.pte.dto.QueryConnectionsResult; import de.schildbach.pte.dto.QueryDeparturesResult; @@ -35,6 +37,38 @@ public class LinzProviderLiveTest private LinzProvider provider = new LinzProvider(); private static final String ALL_PRODUCTS = "IRSUTBFC"; + @Test + public void autocompleteIncomplete() throws Exception + { + final List autocompletes = provider.autocompleteStations("Linz, H"); + + list(autocompletes); + } + + @Test + public void autocompleteIdentified() throws Exception + { + final List autocompletes = provider.autocompleteStations("Leonding, Haag"); + + list(autocompletes); + } + + @Test + public void autocompleteCity() throws Exception + { + final List autocompletes = provider.autocompleteStations("Linz"); + + list(autocompletes); + } + + private void list(final List autocompletes) + { + System.out.print(autocompletes.size() + " "); + for (final Autocomplete autocomplete : autocompletes) + System.out.print(autocomplete.toDebugString() + " "); + System.out.println(); + } + @Test public void queryDepartures() throws Exception { diff --git a/test/de/schildbach/pte/live/VrnProviderLiveTest.java b/test/de/schildbach/pte/live/VrnProviderLiveTest.java index efff3c3f..c3c48406 100644 --- a/test/de/schildbach/pte/live/VrnProviderLiveTest.java +++ b/test/de/schildbach/pte/live/VrnProviderLiveTest.java @@ -16,9 +16,12 @@ */ package de.schildbach.pte.live; +import java.util.List; + import org.junit.Test; import de.schildbach.pte.VrnProvider; +import de.schildbach.pte.dto.Autocomplete; import de.schildbach.pte.dto.NearbyStationsResult; import de.schildbach.pte.dto.QueryDeparturesResult; @@ -29,6 +32,46 @@ public class VrnProviderLiveTest { private final VrnProvider provider = new VrnProvider(); + @Test + public void autocompleteIncomplete() throws Exception + { + final List autocompletes = provider.autocompleteStations("Kur"); + + list(autocompletes); + } + + @Test + public void autocompleteIdentified() throws Exception + { + final List autocompletes = provider.autocompleteStations("Bremen, KUR"); + + list(autocompletes); + } + + @Test + public void autocompleteLocality() throws Exception + { + final List autocompletes = provider.autocompleteStations("Bremen"); + + list(autocompletes); + } + + @Test + public void autocompleteCity() throws Exception + { + final List autocompletes = provider.autocompleteStations("Mannheim"); + + list(autocompletes); + } + + private void list(final List autocompletes) + { + System.out.print(autocompletes.size() + " "); + for (final Autocomplete autocomplete : autocompletes) + System.out.print(autocomplete.toDebugString() + " "); + System.out.println(); + } + @Test public void nearbyStation() throws Exception { diff --git a/test/de/schildbach/pte/live/VrrProviderLiveTest.java b/test/de/schildbach/pte/live/VrrProviderLiveTest.java index d4531cf4..73945af8 100644 --- a/test/de/schildbach/pte/live/VrrProviderLiveTest.java +++ b/test/de/schildbach/pte/live/VrrProviderLiveTest.java @@ -16,9 +16,12 @@ */ package de.schildbach.pte.live; +import java.util.List; + import org.junit.Test; import de.schildbach.pte.VrrProvider; +import de.schildbach.pte.dto.Autocomplete; import de.schildbach.pte.dto.NearbyStationsResult; import de.schildbach.pte.dto.QueryDeparturesResult; @@ -29,6 +32,38 @@ public class VrrProviderLiveTest { private final VrrProvider provider = new VrrProvider(); + @Test + public void autocompleteIncomplete() throws Exception + { + final List autocompletes = provider.autocompleteStations("Kur"); + + list(autocompletes); + } + + @Test + public void autocompleteIdentified() throws Exception + { + final List autocompletes = provider.autocompleteStations("Düsseldorf, Am Frohnhof"); + + list(autocompletes); + } + + @Test + public void autocompleteCity() throws Exception + { + final List autocompletes = provider.autocompleteStations("Düsseldorf"); + + list(autocompletes); + } + + private void list(final List autocompletes) + { + System.out.print(autocompletes.size() + " "); + for (final Autocomplete autocomplete : autocompletes) + System.out.print(autocomplete.toDebugString() + " "); + System.out.println(); + } + @Test public void nearbyStation() throws Exception {