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;
import java.util.Collection;
import java.io.IOException;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import com.google.common.base.Charsets;
import de.schildbach.pte.dto.Line;
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.QueryDeparturesResult;
import de.schildbach.pte.dto.QueryTripsContext;
import de.schildbach.pte.dto.QueryTripsResult;
import de.schildbach.pte.dto.Style;
import de.schildbach.pte.dto.SuggestLocationsResult;
/**
* @author Andreas Schildbach
*/
public class VorProvider extends AbstractEfaProvider {
private final static String API_BASE = "https://efa.vor.at/vor/";
public class VorProvider extends AbstractHafasProvider {
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() {
super(NetworkId.VOR, API_BASE);
public VorProvider(final String jsonApiAuthorization) {
super(NetworkId.VOR, API_BASE, "dn", PRODUCTS_MAP);
setHttpReferer(API_BASE + DEFAULT_TRIP_ENDPOINT);
setHttpPost(true);
setIncludeRegionId(false);
setJsonApiVersion("1.11");
setJsonApiClient("{\"id\":\"VAO\",\"l\":\"vs_anachb\",\"type\":\"AND\"}");
setJsonApiAuthorization(jsonApiAuthorization);
setJsonNearbyLocationsEncoding(Charsets.UTF_8);
setStyles(STYLES);
setRequestUrlEncoding(Charsets.UTF_8);
}
@Override
protected boolean hasCapability(final Capability capability) {
if (capability == Capability.TRIPS)
return false;
public Set<Product> defaultProducts() {
return Product.ALL;
}
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
return super.hasCapability(capability);
throw new IllegalArgumentException("cannot handle: " + location);
}
@Override
protected String xsltTripRequestParameters(final Location from, final @Nullable Location via, final Location to,
final Date time, final boolean dep, final @Nullable Collection<Product> products,
public QueryDeparturesResult queryDepartures(final String stationId, final @Nullable Date time,
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 Accessibility accessibility, final @Nullable Set<Option> options) {
final StringBuilder uri = new StringBuilder(super.xsltTripRequestParameters(from, via, to, time, dep, products,
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();
final @Nullable Accessibility accessibility, final @Nullable Set<Option> options) throws IOException {
return jsonTripSearch(from, via, to, date, dep, products, null);
}
@Override
protected Line parseLine(final @Nullable String id, final @Nullable String network, final @Nullable String mot,
final @Nullable String symbol, final @Nullable String name, final @Nullable String longName,
final @Nullable String trainType, final @Nullable String trainNum, final @Nullable String trainName) {
if ("0".equals(mot)) {
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);
public QueryTripsResult queryMoreTrips(final QueryTripsContext context, final boolean later) throws IOException {
final JsonContext jsonContext = (JsonContext) context;
return jsonTripSearch(jsonContext.from, jsonContext.via, jsonContext.to, jsonContext.date, jsonContext.dep,
jsonContext.products, later ? jsonContext.laterContext : jsonContext.earlierContext);
}
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 VorProviderLiveTest() {
super(new VorProvider());
super(new VorProvider(secretProperty("vor.json_api_authorization")));
}
@Test
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);
}
@ -59,7 +59,19 @@ public class VorProviderLiveTest extends AbstractProviderLiveTest {
@Test
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);
}
@ -73,25 +85,25 @@ public class VorProviderLiveTest extends AbstractProviderLiveTest {
public void suggestLocationsWithUmlaut() throws Exception {
final SuggestLocationsResult result = suggestLocations("Längenfeld");
print(result);
assertThat(result.getLocations(), hasItem(new Location(LocationType.STATION, "60200820")));
assertThat(result.getLocations(), hasItem(new Location(LocationType.STATION, "900018107")));
}
@Test
public void suggestLocationsCoverage() throws Exception {
final SuggestLocationsResult huetteldorfResult = suggestLocations("Hütteldorf");
final SuggestLocationsResult huetteldorfResult = suggestLocations("Wien Hütteldorf");
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");
print(wienerNeustadtResult);
assertThat(wienerNeustadtResult.getLocations(), hasItem(new Location(LocationType.STATION, "60205223")));
assertThat(wienerNeustadtResult.getLocations(), hasItem(new Location(LocationType.STATION, "430522300")));
}
@Test
public void shortTrip() throws Exception {
final QueryTripsResult result = queryTrips(
new Location(LocationType.STATION, "60200657", 48200756, 16369001, "Wien", "Karlsplatz"), null,
new Location(LocationType.STATION, "60201094", 48198612, 16367719, "Wien", "Resselgasse"), new Date(),
new Location(LocationType.STATION, "490065700", 48200852, 16368880, "Wien", "Karlsplatz"), null,
new Location(LocationType.STATION, "490109400", 48198362, 16367667, "Wien", "Resselgasse"), new Date(),
true, Product.ALL, WalkSpeed.NORMAL, Accessibility.NEUTRAL);
print(result);
assertEquals(QueryTripsResult.Status.OK, result.status);
@ -118,9 +130,11 @@ public class VorProviderLiveTest extends AbstractProviderLiveTest {
@Test
public void tripToPOI() throws Exception {
final QueryTripsResult result = queryTrips(
new Location(LocationType.ADDRESS, null, 48221088, 16342658, "Wien", "Antonigasse 4"), null,
new Location(LocationType.POI, "poiID:1005:49000000:-1", 48199844, 16365834, "Wien", "Naschmarkt"),
final QueryTripsResult result = queryTrips(new Location(LocationType.STATION, "490134900", 48185184, 16376413),
null,
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);
print(result);
final QueryTripsResult laterResult = queryMoreTrips(result.context, true);