VOR: Switch to JSON API.

This commit is contained in:
Andreas Schildbach 2016-10-18 22:37:47 +02:00
parent 04af7037ff
commit a59d696a42
2 changed files with 105 additions and 52 deletions

View file

@ -17,76 +17,115 @@
package de.schildbach.pte; package de.schildbach.pte;
import java.util.Collection; import java.io.IOException;
import java.util.Date; import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Location; import de.schildbach.pte.dto.Location;
import de.schildbach.pte.dto.LocationType;
import de.schildbach.pte.dto.NearbyLocationsResult;
import de.schildbach.pte.dto.Product; import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.QueryDeparturesResult;
import de.schildbach.pte.dto.QueryTripsContext;
import de.schildbach.pte.dto.QueryTripsResult;
import de.schildbach.pte.dto.Style; import de.schildbach.pte.dto.Style;
import de.schildbach.pte.dto.SuggestLocationsResult;
/** /**
* @author Andreas Schildbach * @author Andreas Schildbach
*/ */
public class VorProvider extends AbstractEfaProvider { public class VorProvider extends AbstractHafasProvider {
private final static String API_BASE = "https://efa.vor.at/vor/"; private static final String API_BASE = "https://anachb.vor.at/bin/";
private static final Product[] PRODUCTS_MAP = { Product.HIGH_SPEED_TRAIN, Product.SUBURBAN_TRAIN, Product.SUBWAY,
null, Product.TRAM, Product.REGIONAL_TRAIN, Product.BUS, Product.BUS, Product.TRAM, Product.FERRY,
Product.ON_DEMAND, Product.BUS, Product.REGIONAL_TRAIN, null, null, null };
public VorProvider() { public VorProvider(final String jsonApiAuthorization) {
super(NetworkId.VOR, API_BASE); super(NetworkId.VOR, API_BASE, "dn", PRODUCTS_MAP);
setHttpReferer(API_BASE + DEFAULT_TRIP_ENDPOINT); setJsonApiVersion("1.11");
setHttpPost(true); setJsonApiClient("{\"id\":\"VAO\",\"l\":\"vs_anachb\",\"type\":\"AND\"}");
setIncludeRegionId(false); setJsonApiAuthorization(jsonApiAuthorization);
setJsonNearbyLocationsEncoding(Charsets.UTF_8);
setStyles(STYLES); setStyles(STYLES);
setRequestUrlEncoding(Charsets.UTF_8);
} }
@Override @Override
protected boolean hasCapability(final Capability capability) { public Set<Product> defaultProducts() {
if (capability == Capability.TRIPS) return Product.ALL;
return false; }
private static final Pattern P_SPLIT_NAME_ONE_COMMA = Pattern.compile("([^,]*), ([^,]{3,64})");
@Override
protected String[] splitStationName(final String name) {
final Matcher m = P_SPLIT_NAME_ONE_COMMA.matcher(name);
if (m.matches())
return new String[] { m.group(2), m.group(1) };
return super.splitStationName(name);
}
@Override
protected String[] splitPOI(final String poi) {
final Matcher m = P_SPLIT_NAME_ONE_COMMA.matcher(poi);
if (m.matches())
return new String[] { m.group(2), m.group(1) };
return super.splitPOI(poi);
}
@Override
protected String[] splitAddress(final String address) {
final Matcher m = P_SPLIT_NAME_FIRST_COMMA.matcher(address);
if (m.matches())
return new String[] { m.group(1), m.group(2) };
return super.splitAddress(address);
}
@Override
public NearbyLocationsResult queryNearbyLocations(final EnumSet<LocationType> types, final Location location,
final int maxDistance, final int maxLocations) throws IOException {
if (location.hasLocation())
return jsonLocGeoPos(types, location.lat, location.lon);
else else
return super.hasCapability(capability); throw new IllegalArgumentException("cannot handle: " + location);
} }
@Override @Override
protected String xsltTripRequestParameters(final Location from, final @Nullable Location via, final Location to, public QueryDeparturesResult queryDepartures(final String stationId, final @Nullable Date time,
final Date time, final boolean dep, final @Nullable Collection<Product> products, final int maxDepartures, final boolean equivs) throws IOException {
return jsonStationBoard(stationId, time, maxDepartures, equivs);
}
@Override
public SuggestLocationsResult suggestLocations(final CharSequence constraint) throws IOException {
return jsonLocMatch(constraint);
}
@Override
public QueryTripsResult queryTrips(final Location from, final @Nullable Location via, final Location to,
final Date date, final boolean dep, final @Nullable Set<Product> products,
final @Nullable Optimize optimize, final @Nullable WalkSpeed walkSpeed, final @Nullable Optimize optimize, final @Nullable WalkSpeed walkSpeed,
final @Nullable Accessibility accessibility, final @Nullable Set<Option> options) { final @Nullable Accessibility accessibility, final @Nullable Set<Option> options) throws IOException {
final StringBuilder uri = new StringBuilder(super.xsltTripRequestParameters(from, via, to, time, dep, products, return jsonTripSearch(from, via, to, date, dep, products, null);
optimize, walkSpeed, accessibility, options));
if (products != null) {
for (final Product p : products) {
if (p == Product.BUS)
uri.append("&inclMOT_11=on"); // night bus
}
}
return uri.toString();
} }
@Override @Override
protected Line parseLine(final @Nullable String id, final @Nullable String network, final @Nullable String mot, public QueryTripsResult queryMoreTrips(final QueryTripsContext context, final boolean later) throws IOException {
final @Nullable String symbol, final @Nullable String name, final @Nullable String longName, final JsonContext jsonContext = (JsonContext) context;
final @Nullable String trainType, final @Nullable String trainNum, final @Nullable String trainName) { return jsonTripSearch(jsonContext.from, jsonContext.via, jsonContext.to, jsonContext.date, jsonContext.dep,
if ("0".equals(mot)) { jsonContext.products, later ? jsonContext.laterContext : jsonContext.earlierContext);
if ("WLB".equals(trainNum) && trainType == null)
return new Line(id, network, Product.TRAM, "WLB");
} else if ("1".equals(mot)) {
if ("LILO".equals(symbol) && "Lokalbahn".equals(trainName))
return new Line(id, network, Product.REGIONAL_TRAIN, "LILO");
}
return super.parseLine(id, network, mot, symbol, name, longName, trainType, trainNum, trainName);
} }
private static final Map<String, Style> STYLES = new HashMap<String, Style>(); private static final Map<String, Style> STYLES = new HashMap<String, Style>();

View file

@ -42,12 +42,12 @@ import de.schildbach.pte.dto.SuggestLocationsResult;
*/ */
public class VorProviderLiveTest extends AbstractProviderLiveTest { public class VorProviderLiveTest extends AbstractProviderLiveTest {
public VorProviderLiveTest() { public VorProviderLiveTest() {
super(new VorProvider()); super(new VorProvider(secretProperty("vor.json_api_authorization")));
} }
@Test @Test
public void nearbyStations() throws Exception { public void nearbyStations() throws Exception {
final NearbyLocationsResult result = queryNearbyStations(new Location(LocationType.STATION, "60203090")); final NearbyLocationsResult result = queryNearbyStations(new Location(LocationType.STATION, "490134900"));
print(result); print(result);
} }
@ -59,7 +59,19 @@ public class VorProviderLiveTest extends AbstractProviderLiveTest {
@Test @Test
public void queryDepartures() throws Exception { public void queryDepartures() throws Exception {
final QueryDeparturesResult result = queryDepartures("60203090", false); final QueryDeparturesResult result = queryDepartures("490134900", false);
print(result);
}
@Test
public void queryDeparturesInvalidStation() throws Exception {
final QueryDeparturesResult result = queryDepartures("999999", 0, false);
assertEquals(QueryDeparturesResult.Status.INVALID_STATION, result.status);
}
@Test
public void suggestLocations() throws Exception {
final SuggestLocationsResult result = suggestLocations("Wien Hauptbahnhof");
print(result); print(result);
} }
@ -73,25 +85,25 @@ public class VorProviderLiveTest extends AbstractProviderLiveTest {
public void suggestLocationsWithUmlaut() throws Exception { public void suggestLocationsWithUmlaut() throws Exception {
final SuggestLocationsResult result = suggestLocations("Längenfeld"); final SuggestLocationsResult result = suggestLocations("Längenfeld");
print(result); print(result);
assertThat(result.getLocations(), hasItem(new Location(LocationType.STATION, "60200820"))); assertThat(result.getLocations(), hasItem(new Location(LocationType.STATION, "900018107")));
} }
@Test @Test
public void suggestLocationsCoverage() throws Exception { public void suggestLocationsCoverage() throws Exception {
final SuggestLocationsResult huetteldorfResult = suggestLocations("Hütteldorf"); final SuggestLocationsResult huetteldorfResult = suggestLocations("Wien Hütteldorf");
print(huetteldorfResult); print(huetteldorfResult);
assertThat(huetteldorfResult.getLocations(), hasItem(new Location(LocationType.STATION, "60200560"))); assertThat(huetteldorfResult.getLocations(), hasItem(new Location(LocationType.STATION, "490056000")));
final SuggestLocationsResult wienerNeustadtResult = suggestLocations("Wiener Neustadt Nord"); final SuggestLocationsResult wienerNeustadtResult = suggestLocations("Wiener Neustadt Nord");
print(wienerNeustadtResult); print(wienerNeustadtResult);
assertThat(wienerNeustadtResult.getLocations(), hasItem(new Location(LocationType.STATION, "60205223"))); assertThat(wienerNeustadtResult.getLocations(), hasItem(new Location(LocationType.STATION, "430522300")));
} }
@Test @Test
public void shortTrip() throws Exception { public void shortTrip() throws Exception {
final QueryTripsResult result = queryTrips( final QueryTripsResult result = queryTrips(
new Location(LocationType.STATION, "60200657", 48200756, 16369001, "Wien", "Karlsplatz"), null, new Location(LocationType.STATION, "490065700", 48200852, 16368880, "Wien", "Karlsplatz"), null,
new Location(LocationType.STATION, "60201094", 48198612, 16367719, "Wien", "Resselgasse"), new Date(), new Location(LocationType.STATION, "490109400", 48198362, 16367667, "Wien", "Resselgasse"), new Date(),
true, Product.ALL, WalkSpeed.NORMAL, Accessibility.NEUTRAL); true, Product.ALL, WalkSpeed.NORMAL, Accessibility.NEUTRAL);
print(result); print(result);
assertEquals(QueryTripsResult.Status.OK, result.status); assertEquals(QueryTripsResult.Status.OK, result.status);
@ -118,9 +130,11 @@ public class VorProviderLiveTest extends AbstractProviderLiveTest {
@Test @Test
public void tripToPOI() throws Exception { public void tripToPOI() throws Exception {
final QueryTripsResult result = queryTrips( final QueryTripsResult result = queryTrips(new Location(LocationType.STATION, "490134900", 48185184, 16376413),
new Location(LocationType.ADDRESS, null, 48221088, 16342658, "Wien", "Antonigasse 4"), null, null,
new Location(LocationType.POI, "poiID:1005:49000000:-1", 48199844, 16365834, "Wien", "Naschmarkt"), new Location(LocationType.POI,
"A=4@O=Naschmarkt, Wien@X=16362903@Y=48198290@U=130@L=960068499@B=1@p=1476842541@", 48198290,
16362903, "Wien", "Naschmarkt"),
new Date(), true, Product.ALL, WalkSpeed.NORMAL, Accessibility.NEUTRAL); new Date(), true, Product.ALL, WalkSpeed.NORMAL, Accessibility.NEUTRAL);
print(result); print(result);
final QueryTripsResult laterResult = queryMoreTrips(result.context, true); final QueryTripsResult laterResult = queryMoreTrips(result.context, true);