Use HttpUrl and HttpUrl.Builder where possible.

This commit is contained in:
Andreas Schildbach 2017-01-02 19:15:29 +01:00
parent e50098f092
commit 4f7bd832e6
79 changed files with 977 additions and 916 deletions

View file

@ -22,7 +22,6 @@ import static com.google.common.base.Preconditions.checkState;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
@ -52,7 +51,6 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import com.google.common.base.Charsets;
import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
@ -97,17 +95,15 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
protected static final String SERVER_PRODUCT = "efa";
private final String departureMonitorEndpoint;
private final String tripEndpoint;
private final String stopFinderEndpoint;
private final String coordEndpoint;
private final HttpUrl departureMonitorEndpoint;
private final HttpUrl tripEndpoint;
private final HttpUrl stopFinderEndpoint;
private final HttpUrl coordEndpoint;
private String language = "de";
private @Nullable String additionalQueryParameter = null;
private boolean needsSpEncId = false;
private boolean includeRegionId = true;
private boolean useProxFootSearch = true;
private Charset requestUrlEncoding = Charsets.ISO_8859_1;
private @Nullable String httpReferer = null;
private @Nullable String httpRefererTrip = null;
private boolean httpPost = false;
@ -144,22 +140,28 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
}
}
public AbstractEfaProvider(final NetworkId network, final String apiBase) {
public AbstractEfaProvider(final NetworkId network, final HttpUrl apiBase) {
this(network, apiBase, null, null, null, null);
}
public AbstractEfaProvider(final NetworkId network, final String apiBase, final String departureMonitorEndpoint,
public AbstractEfaProvider(final NetworkId network, final HttpUrl apiBase, final String departureMonitorEndpoint,
final String tripEndpoint, final String stopFinderEndpoint, final String coordEndpoint) {
this(network,
apiBase + (departureMonitorEndpoint != null ? departureMonitorEndpoint
: DEFAULT_DEPARTURE_MONITOR_ENDPOINT), //
apiBase + (tripEndpoint != null ? tripEndpoint : DEFAULT_TRIP_ENDPOINT), //
apiBase + (stopFinderEndpoint != null ? stopFinderEndpoint : DEFAULT_STOPFINDER_ENDPOINT), //
apiBase + (coordEndpoint != null ? coordEndpoint : DEFAULT_COORD_ENDPOINT));
apiBase.newBuilder()
.addPathSegment(departureMonitorEndpoint != null ? departureMonitorEndpoint
: DEFAULT_DEPARTURE_MONITOR_ENDPOINT)
.build(),
apiBase.newBuilder().addPathSegment(tripEndpoint != null ? tripEndpoint : DEFAULT_TRIP_ENDPOINT)
.build(),
apiBase.newBuilder()
.addPathSegment(stopFinderEndpoint != null ? stopFinderEndpoint : DEFAULT_STOPFINDER_ENDPOINT)
.build(),
apiBase.newBuilder().addPathSegment(coordEndpoint != null ? coordEndpoint : DEFAULT_COORD_ENDPOINT)
.build());
}
public AbstractEfaProvider(final NetworkId network, final String departureMonitorEndpoint,
final String tripEndpoint, final String stopFinderEndpoint, final String coordEndpoint) {
public AbstractEfaProvider(final NetworkId network, final HttpUrl departureMonitorEndpoint,
final HttpUrl tripEndpoint, final HttpUrl stopFinderEndpoint, final HttpUrl coordEndpoint) {
super(network);
try {
@ -180,16 +182,6 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
return this;
}
protected AbstractEfaProvider setAdditionalQueryParameter(final String additionalQueryParameter) {
this.additionalQueryParameter = additionalQueryParameter;
return this;
}
protected AbstractEfaProvider setRequestUrlEncoding(final Charset requestUrlEncoding) {
this.requestUrlEncoding = requestUrlEncoding;
return this;
}
protected AbstractEfaProvider setHttpReferer(final String httpReferer) {
this.httpReferer = httpReferer;
this.httpRefererTrip = httpReferer;
@ -246,24 +238,21 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
return true;
}
private final void appendCommonRequestParams(final StringBuilder uri, final String outputFormat) {
uri.append("?outputFormat=").append(outputFormat);
uri.append("&language=").append(language);
uri.append("&stateless=1");
uri.append("&coordOutputFormat=WGS84");
if (additionalQueryParameter != null)
uri.append('&').append(additionalQueryParameter);
private final void appendCommonRequestParams(final HttpUrl.Builder url, final String outputFormat) {
url.addEncodedQueryParameter("outputFormat", outputFormat);
url.addEncodedQueryParameter("language", language);
url.addEncodedQueryParameter("stateless", "1");
url.addEncodedQueryParameter("coordOutputFormat", "WGS84");
}
protected SuggestLocationsResult jsonStopfinderRequest(final Location constraint) throws IOException {
final StringBuilder uri = new StringBuilder(stopFinderEndpoint);
final StringBuilder parameters = stopfinderRequestParameters(constraint, "JSON");
final HttpUrl.Builder url = stopFinderEndpoint.newBuilder();
appendStopfinderRequestParameters(url, constraint, "JSON");
final CharSequence page;
if (httpPost)
page = httpClient.get(HttpUrl.parse(uri.toString()), parameters.substring(1),
"application/x-www-form-urlencoded");
page = httpClient.get(url.build(), url.build().encodedQuery(), "application/x-www-form-urlencoded");
else
page = httpClient.get(HttpUrl.parse(uri.append(parameters).toString()));
page = httpClient.get(url.build());
final ResultHeader header = new ResultHeader(network, SERVER_PRODUCT);
try {
@ -310,7 +299,7 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
return new SuggestLocationsResult(header, locations);
} catch (final JSONException x) {
throw new RuntimeException("cannot parse: '" + page + "' on " + uri, x);
throw new RuntimeException("cannot parse: '" + page + "' on " + url, x);
}
}
@ -347,29 +336,28 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
return new SuggestedLocation(location, quality);
}
private StringBuilder stopfinderRequestParameters(final Location constraint, final String outputFormat) {
final StringBuilder parameters = new StringBuilder();
appendCommonRequestParams(parameters, outputFormat);
parameters.append("&locationServerActive=1");
private void appendStopfinderRequestParameters(final HttpUrl.Builder url, final Location constraint,
final String outputFormat) {
appendCommonRequestParams(url, outputFormat);
url.addEncodedQueryParameter("locationServerActive", "1");
if (includeRegionId)
parameters.append("&regionID_sf=1"); // prefer own region
appendLocation(parameters, constraint, "sf");
url.addEncodedQueryParameter("regionID_sf", "1"); // prefer own region
appendLocationParams(url, constraint, "sf");
if (constraint.type == LocationType.ANY) {
if (needsSpEncId)
parameters.append("&SpEncId=0");
url.addEncodedQueryParameter("SpEncId", "0");
// 1=place 2=stop 4=street 8=address 16=crossing 32=poi 64=postcode
parameters.append("&anyObjFilter_sf=").append(2 + 4 + 8 + 16 + 32 + 64);
parameters.append("&reducedAnyPostcodeObjFilter_sf=64&reducedAnyTooManyObjFilter_sf=2");
parameters.append("&useHouseNumberList=true");
parameters.append("&anyMaxSizeHitList=500");
url.addEncodedQueryParameter("anyObjFilter_sf", Integer.toString(2 + 4 + 8 + 16 + 32 + 64));
url.addEncodedQueryParameter("reducedAnyPostcodeObjFilter_sf", "64");
url.addEncodedQueryParameter("reducedAnyTooManyObjFilter_sf", "2");
url.addEncodedQueryParameter("useHouseNumberList", "true");
url.addEncodedQueryParameter("anyMaxSizeHitList", "500");
}
return parameters;
}
protected SuggestLocationsResult xmlStopfinderRequest(final Location constraint) throws IOException {
final StringBuilder uri = new StringBuilder(stopFinderEndpoint);
final StringBuilder parameters = stopfinderRequestParameters(constraint, "XML");
final HttpUrl.Builder url = stopFinderEndpoint.newBuilder();
appendStopfinderRequestParameters(url, constraint, "XML");
final AtomicReference<SuggestLocationsResult> result = new AtomicReference<SuggestLocationsResult>();
final HttpClient.Callback callback = new HttpClient.Callback() {
@ -401,17 +389,17 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
};
if (httpPost)
httpClient.getInputStream(callback, HttpUrl.parse(uri.toString()), parameters.substring(1),
httpClient.getInputStream(callback, url.build(), url.build().encodedQuery(),
"application/x-www-form-urlencoded", httpReferer);
else
httpClient.getInputStream(callback, HttpUrl.parse(uri.append(parameters).toString()), httpReferer);
httpClient.getInputStream(callback, url.build(), httpReferer);
return result.get();
}
protected SuggestLocationsResult mobileStopfinderRequest(final Location constraint) throws IOException {
final StringBuilder uri = new StringBuilder(stopFinderEndpoint);
final StringBuilder parameters = stopfinderRequestParameters(constraint, "XML");
final HttpUrl.Builder url = stopFinderEndpoint.newBuilder();
appendStopfinderRequestParameters(url, constraint, "XML");
final AtomicReference<SuggestLocationsResult> result = new AtomicReference<SuggestLocationsResult>();
final HttpClient.Callback callback = new HttpClient.Callback() {
@ -486,45 +474,42 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
};
if (httpPost)
httpClient.getInputStream(callback, HttpUrl.parse(uri.toString()), parameters.substring(1),
httpClient.getInputStream(callback, url.build(), url.build().encodedQuery(),
"application/x-www-form-urlencoded", httpReferer);
else
httpClient.getInputStream(callback, HttpUrl.parse(uri.append(parameters).toString()), httpReferer);
httpClient.getInputStream(callback, url.build(), httpReferer);
return result.get();
}
private StringBuilder xmlCoordRequestParameters(final EnumSet<LocationType> types, final int lat, final int lon,
final int maxDistance, final int maxLocations) {
final StringBuilder parameters = new StringBuilder();
appendCommonRequestParams(parameters, "XML");
parameters.append("&coord=")
.append(String.format(Locale.ENGLISH, "%2.6f:%2.6f:WGS84", latLonToDouble(lon), latLonToDouble(lat)));
private void appendXmlCoordRequestParameters(final HttpUrl.Builder url, final EnumSet<LocationType> types,
final int lat, final int lon, final int maxDistance, final int maxLocations) {
appendCommonRequestParams(url, "XML");
url.addEncodedQueryParameter("coord",
ParserUtils.urlEncode(
String.format(Locale.ENGLISH, "%2.6f:%2.6f:WGS84", latLonToDouble(lon), latLonToDouble(lat)),
requestUrlEncoding));
if (useStringCoordListOutputFormat)
parameters.append("&coordListOutputFormat=STRING");
parameters.append("&max=").append(maxLocations != 0 ? maxLocations : 50);
parameters.append("&inclFilter=1");
url.addEncodedQueryParameter("coordListOutputFormat", "STRING");
url.addEncodedQueryParameter("max", Integer.toString(maxLocations != 0 ? maxLocations : 50));
url.addEncodedQueryParameter("inclFilter", "1");
int i = 1;
for (final LocationType type : types) {
parameters.append("&radius_").append(i).append('=').append(maxDistance != 0 ? maxDistance : 1320);
parameters.append("&type_").append(i).append('=');
url.addEncodedQueryParameter("radius_" + i, Integer.toString(maxDistance != 0 ? maxDistance : 1320));
if (type == LocationType.STATION)
parameters.append("STOP");
url.addEncodedQueryParameter("type_" + i, "STOP");
else if (type == LocationType.POI)
parameters.append("POI_POINT");
url.addEncodedQueryParameter("type_" + i, "POI_POINT");
else
throw new IllegalArgumentException("cannot handle location type: " + type); // ENTRANCE,
// BUS_POINT
throw new IllegalArgumentException("cannot handle location type: " + type);
i++;
}
return parameters;
}
protected NearbyLocationsResult xmlCoordRequest(final EnumSet<LocationType> types, final int lat, final int lon,
final int maxDistance, final int maxStations) throws IOException {
final StringBuilder uri = new StringBuilder(coordEndpoint);
final StringBuilder parameters = xmlCoordRequestParameters(types, lat, lon, maxDistance, maxStations);
final HttpUrl.Builder url = coordEndpoint.newBuilder();
appendXmlCoordRequestParameters(url, types, lat, lon, maxDistance, maxStations);
final AtomicReference<NearbyLocationsResult> result = new AtomicReference<NearbyLocationsResult>();
final HttpClient.Callback callback = new HttpClient.Callback() {
@ -587,18 +572,18 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
};
if (httpPost)
httpClient.getInputStream(callback, HttpUrl.parse(uri.toString()), parameters.substring(1),
httpClient.getInputStream(callback, url.build(), url.build().encodedQuery(),
"application/x-www-form-urlencoded", httpReferer);
else
httpClient.getInputStream(callback, HttpUrl.parse(uri.append(parameters).toString()), httpReferer);
httpClient.getInputStream(callback, url.build(), httpReferer);
return result.get();
}
protected NearbyLocationsResult mobileCoordRequest(final EnumSet<LocationType> types, final int lat, final int lon,
final int maxDistance, final int maxStations) throws IOException {
final StringBuilder uri = new StringBuilder(coordEndpoint);
final StringBuilder parameters = xmlCoordRequestParameters(types, lat, lon, maxDistance, maxStations);
final HttpUrl.Builder url = coordEndpoint.newBuilder();
appendXmlCoordRequestParameters(url, types, lat, lon, maxDistance, maxStations);
final AtomicReference<NearbyLocationsResult> result = new AtomicReference<NearbyLocationsResult>();
final HttpClient.Callback callback = new HttpClient.Callback() {
@ -665,10 +650,10 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
};
if (httpPost)
httpClient.getInputStream(callback, HttpUrl.parse(uri.toString()), parameters.substring(1),
httpClient.getInputStream(callback, url.build(), url.build().encodedQuery(),
"application/x-www-form-urlencoded", httpReferer);
else
httpClient.getInputStream(callback, HttpUrl.parse(uri.append(parameters).toString()), httpReferer);
httpClient.getInputStream(callback, url.build(), httpReferer);
return result.get();
}
@ -864,17 +849,18 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
private NearbyLocationsResult nearbyStationsRequest(final String stationId, final int maxLocations)
throws IOException {
final StringBuilder uri = new StringBuilder(departureMonitorEndpoint);
final StringBuilder parameters = new StringBuilder();
appendCommonRequestParams(parameters, "XML");
parameters.append("&type_dm=stop&name_dm=").append(normalizeStationId(stationId));
parameters.append("&itOptionsActive=1");
parameters.append("&ptOptionsActive=1");
final HttpUrl.Builder url = departureMonitorEndpoint.newBuilder();
appendCommonRequestParams(url, "XML");
url.addEncodedQueryParameter("type_dm", "stop");
url.addEncodedQueryParameter("name_dm",
ParserUtils.urlEncode(normalizeStationId(stationId), requestUrlEncoding));
url.addEncodedQueryParameter("itOptionsActive", "1");
url.addEncodedQueryParameter("ptOptionsActive", "1");
if (useProxFootSearch)
parameters.append("&useProxFootSearch=1");
parameters.append("&mergeDep=1");
parameters.append("&useAllStops=1");
parameters.append("&mode=direct");
url.addEncodedQueryParameter("useProxFootSearch", "1");
url.addEncodedQueryParameter("mergeDep", "1");
url.addEncodedQueryParameter("useAllStops", "1");
url.addEncodedQueryParameter("mode", "direct");
final AtomicReference<NearbyLocationsResult> result = new AtomicReference<NearbyLocationsResult>();
final HttpClient.Callback callback = new HttpClient.Callback() {
@ -923,10 +909,10 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
};
if (httpPost)
httpClient.getInputStream(callback, HttpUrl.parse(uri.toString()), parameters.substring(1),
httpClient.getInputStream(callback, url.build(), url.build().encodedQuery(),
"application/x-www-form-urlencoded", httpReferer);
else
httpClient.getInputStream(callback, HttpUrl.parse(uri.append(parameters).toString()), httpReferer);
httpClient.getInputStream(callback, url.build(), httpReferer);
return result.get();
}
@ -1433,28 +1419,26 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
return xsltDepartureMonitorRequest(stationId, time, maxDepartures, equivs);
}
protected StringBuilder xsltDepartureMonitorRequestParameters(final String stationId, final @Nullable Date time,
final int maxDepartures, final boolean equivs) {
final StringBuilder parameters = new StringBuilder();
appendCommonRequestParams(parameters, "XML");
parameters.append("&type_dm=stop");
parameters.append("&name_dm=").append(normalizeStationId(stationId));
protected void appendXsltDepartureMonitorRequestParameters(final HttpUrl.Builder url, final String stationId,
final @Nullable Date time, final int maxDepartures, final boolean equivs) {
appendCommonRequestParams(url, "XML");
url.addEncodedQueryParameter("type_dm", "stop");
url.addEncodedQueryParameter("name_dm",
ParserUtils.urlEncode(normalizeStationId(stationId), requestUrlEncoding));
if (time != null)
appendItdDateTimeParameters(parameters, time);
parameters.append("&useRealtime=1");
parameters.append("&mode=direct");
parameters.append("&ptOptionsActive=1");
parameters.append("&deleteAssignedStops_dm=").append(equivs ? '0' : '1');
appendItdDateTimeParameters(url, time);
url.addEncodedQueryParameter("useRealtime", "1");
url.addEncodedQueryParameter("mode", "direct");
url.addEncodedQueryParameter("ptOptionsActive", "1");
url.addEncodedQueryParameter("deleteAssignedStops_dm", equivs ? "0" : "1");
if (useProxFootSearch)
parameters.append("&useProxFootSearch=").append(equivs ? '1' : '0');
parameters.append("&mergeDep=1"); // merge departures
url.addEncodedQueryParameter("useProxFootSearch", equivs ? "1" : "0");
url.addEncodedQueryParameter("mergeDep", "1"); // merge departures
if (maxDepartures > 0)
parameters.append("&limit=").append(maxDepartures);
return parameters;
url.addEncodedQueryParameter("limit", Integer.toString(maxDepartures));
}
private final void appendItdDateTimeParameters(final StringBuilder uri, final Date time) {
private final void appendItdDateTimeParameters(final HttpUrl.Builder url, final Date time) {
final Calendar c = new GregorianCalendar(timeZone);
c.setTime(time);
final int year = c.get(Calendar.YEAR);
@ -1462,14 +1446,14 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
final int day = c.get(Calendar.DAY_OF_MONTH);
final int hour = c.get(Calendar.HOUR_OF_DAY);
final int minute = c.get(Calendar.MINUTE);
uri.append("&itdDate=").append(String.format(Locale.ENGLISH, "%04d%02d%02d", year, month, day));
uri.append("&itdTime=").append(String.format(Locale.ENGLISH, "%02d%02d", hour, minute));
url.addEncodedQueryParameter("itdDate", String.format(Locale.ENGLISH, "%04d%02d%02d", year, month, day));
url.addEncodedQueryParameter("itdTime", String.format(Locale.ENGLISH, "%02d%02d", hour, minute));
}
private QueryDeparturesResult xsltDepartureMonitorRequest(final String stationId, final @Nullable Date time,
final int maxDepartures, final boolean equivs) throws IOException {
final StringBuilder uri = new StringBuilder(departureMonitorEndpoint);
final StringBuilder parameters = xsltDepartureMonitorRequestParameters(stationId, time, maxDepartures, equivs);
final HttpUrl.Builder url = departureMonitorEndpoint.newBuilder();
appendXsltDepartureMonitorRequestParameters(url, stationId, time, maxDepartures, equivs);
final AtomicReference<QueryDeparturesResult> result = new AtomicReference<QueryDeparturesResult>();
final HttpClient.Callback callback = new HttpClient.Callback() {
@ -1632,18 +1616,18 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
};
if (httpPost)
httpClient.getInputStream(callback, HttpUrl.parse(uri.toString()), parameters.substring(1),
httpClient.getInputStream(callback, url.build(), url.build().encodedQuery(),
"application/x-www-form-urlencoded", httpReferer);
else
httpClient.getInputStream(callback, HttpUrl.parse(uri.append(parameters).toString()), httpReferer);
httpClient.getInputStream(callback, url.build(), httpReferer);
return result.get();
}
protected QueryDeparturesResult queryDeparturesMobile(final String stationId, final @Nullable Date time,
final int maxDepartures, final boolean equivs) throws IOException {
final StringBuilder uri = new StringBuilder(departureMonitorEndpoint);
final StringBuilder parameters = xsltDepartureMonitorRequestParameters(stationId, time, maxDepartures, equivs);
final HttpUrl.Builder url = departureMonitorEndpoint.newBuilder();
appendXsltDepartureMonitorRequestParameters(url, stationId, time, maxDepartures, equivs);
final AtomicReference<QueryDeparturesResult> result = new AtomicReference<QueryDeparturesResult>();
final HttpClient.Callback callback = new HttpClient.Callback() {
@ -1716,10 +1700,10 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
};
if (httpPost)
httpClient.getInputStream(callback, HttpUrl.parse(uri.toString()), parameters.substring(1),
httpClient.getInputStream(callback, url.build(), url.build().encodedQuery(),
"application/x-www-form-urlencoded", httpReferer);
else
httpClient.getInputStream(callback, HttpUrl.parse(uri.append(parameters).toString()), httpReferer);
httpClient.getInputStream(callback, url.build(), httpReferer);
return result.get();
}
@ -1956,115 +1940,114 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
return (double) value / 1000000;
}
protected String xsltTripRequestParameters(final Location from, final @Nullable Location via, final Location to,
final Date time, final boolean dep, final @Nullable Collection<Product> products,
final @Nullable Optimize optimize, final @Nullable WalkSpeed walkSpeed,
final @Nullable Accessibility accessibility, final @Nullable Set<Option> options) {
final StringBuilder uri = new StringBuilder();
appendCommonRequestParams(uri, "XML");
protected void appendXsltTripRequestParameters(final HttpUrl.Builder url, final Location from,
final @Nullable Location via, final Location to, final Date time, final boolean dep,
final @Nullable Collection<Product> products, final @Nullable Optimize optimize,
final @Nullable WalkSpeed walkSpeed, final @Nullable Accessibility accessibility,
final @Nullable Set<Option> options) {
appendCommonRequestParams(url, "XML");
uri.append("&sessionID=0");
uri.append("&requestID=0");
url.addEncodedQueryParameter("sessionID", "0");
url.addEncodedQueryParameter("requestID", "0");
appendCommonXsltTripRequest2Params(uri);
appendCommonXsltTripRequest2Params(url);
appendLocation(uri, from, "origin");
appendLocation(uri, to, "destination");
appendLocationParams(url, from, "origin");
appendLocationParams(url, to, "destination");
if (via != null)
appendLocation(uri, via, "via");
appendLocationParams(url, via, "via");
appendItdDateTimeParameters(uri, time);
appendItdDateTimeParameters(url, time);
uri.append("&itdTripDateTimeDepArr=").append(dep ? "dep" : "arr");
url.addEncodedQueryParameter("itdTripDateTimeDepArr", dep ? "dep" : "arr");
uri.append("&calcNumberOfTrips=").append(numTripsRequested);
url.addEncodedQueryParameter("calcNumberOfTrips", Integer.toString(numTripsRequested));
uri.append("&ptOptionsActive=1"); // enable public transport options
uri.append("&itOptionsActive=1"); // enable individual transport options
url.addEncodedQueryParameter("ptOptionsActive", "1"); // enable public transport options
url.addEncodedQueryParameter("itOptionsActive", "1"); // enable individual transport options
if (optimize == Optimize.LEAST_DURATION)
uri.append("&routeType=LEASTTIME");
url.addEncodedQueryParameter("routeType", "LEASTTIME");
else if (optimize == Optimize.LEAST_CHANGES)
uri.append("&routeType=LEASTINTERCHANGE");
url.addEncodedQueryParameter("routeType", "LEASTINTERCHANGE");
else if (optimize == Optimize.LEAST_WALKING)
uri.append("&routeType=LEASTWALKING");
url.addEncodedQueryParameter("routeType", "LEASTWALKING");
else if (optimize != null)
log.info("Cannot handle " + optimize + ", ignoring.");
uri.append("&changeSpeed=").append(WALKSPEED_MAP.get(walkSpeed));
url.addEncodedQueryParameter("changeSpeed", WALKSPEED_MAP.get(walkSpeed));
if (accessibility == Accessibility.BARRIER_FREE)
uri.append("&imparedOptionsActive=1").append("&wheelchair=on").append("&noSolidStairs=on");
url.addEncodedQueryParameter("imparedOptionsActive", "1").addEncodedQueryParameter("wheelchair", "on")
.addEncodedQueryParameter("noSolidStairs", "on");
else if (accessibility == Accessibility.LIMITED)
uri.append("&imparedOptionsActive=1").append("&wheelchair=on").append("&lowPlatformVhcl=on")
.append("&noSolidStairs=on");
url.addEncodedQueryParameter("imparedOptionsActive", "1").addEncodedQueryParameter("wheelchair", "on")
.addEncodedQueryParameter("lowPlatformVhcl", "on").addEncodedQueryParameter("noSolidStairs", "on");
if (products != null) {
uri.append("&includedMeans=checkbox");
url.addEncodedQueryParameter("includedMeans", "checkbox");
boolean hasI = false;
for (final Product p : products) {
if (p == Product.HIGH_SPEED_TRAIN || p == Product.REGIONAL_TRAIN) {
uri.append("&inclMOT_0=on");
url.addEncodedQueryParameter("inclMOT_0", "on");
if (p == Product.HIGH_SPEED_TRAIN)
hasI = true;
}
if (p == Product.SUBURBAN_TRAIN)
uri.append("&inclMOT_1=on");
url.addEncodedQueryParameter("inclMOT_1", "on");
if (p == Product.SUBWAY)
uri.append("&inclMOT_2=on");
url.addEncodedQueryParameter("inclMOT_2", "on");
if (p == Product.TRAM)
uri.append("&inclMOT_3=on&inclMOT_4=on");
url.addEncodedQueryParameter("inclMOT_3", "on").addEncodedQueryParameter("inclMOT_4", "on");
if (p == Product.BUS)
uri.append("&inclMOT_5=on&inclMOT_6=on&inclMOT_7=on");
url.addEncodedQueryParameter("inclMOT_5", "on").addEncodedQueryParameter("inclMOT_6", "on")
.addEncodedQueryParameter("inclMOT_7", "on");
if (p == Product.ON_DEMAND)
uri.append("&inclMOT_10=on");
url.addEncodedQueryParameter("inclMOT_10", "on");
if (p == Product.FERRY)
uri.append("&inclMOT_9=on");
url.addEncodedQueryParameter("inclMOT_9", "on");
if (p == Product.CABLECAR)
uri.append("&inclMOT_8=on");
url.addEncodedQueryParameter("inclMOT_8", "on");
}
// workaround for highspeed trains: fails when you want highspeed, but not regional
if (useLineRestriction && !hasI)
uri.append("&lineRestriction=403"); // means: all but ice
url.addEncodedQueryParameter("lineRestriction", "403"); // means: all but ice
}
if (useProxFootSearch)
uri.append("&useProxFootSearch=1"); // walk if it makes journeys quicker
uri.append("&trITMOTvalue100=10"); // maximum time to walk to first or from last stop
url.addEncodedQueryParameter("useProxFootSearch", "1"); // walk if it makes journeys quicker
url.addEncodedQueryParameter("trITMOTvalue100", "10"); // maximum time to walk to first or from last
// stop
if (options != null && options.contains(Option.BIKE))
uri.append("&bikeTakeAlong=1");
url.addEncodedQueryParameter("bikeTakeAlong", "1");
uri.append("&locationServerActive=1");
uri.append("&useRealtime=1");
uri.append("&nextDepsPerLeg=1"); // next departure in case previous was missed
return uri.toString();
url.addEncodedQueryParameter("locationServerActive", "1");
url.addEncodedQueryParameter("useRealtime", "1");
url.addEncodedQueryParameter("nextDepsPerLeg", "1"); // next departure in case previous was missed
}
private String commandLink(final String sessionId, final String requestId) {
final StringBuilder uri = new StringBuilder(tripEndpoint);
uri.append("?sessionID=").append(sessionId);
uri.append("&requestID=").append(requestId);
uri.append("&calcNumberOfTrips=").append(numTripsRequested);
appendCommonXsltTripRequest2Params(uri);
return uri.toString();
private HttpUrl commandLink(final String sessionId, final String requestId) {
final HttpUrl.Builder url = tripEndpoint.newBuilder();
url.addEncodedQueryParameter("sessionID", sessionId);
url.addEncodedQueryParameter("requestID", requestId);
url.addEncodedQueryParameter("calcNumberOfTrips", Integer.toString(numTripsRequested));
appendCommonXsltTripRequest2Params(url);
return url.build();
}
private final void appendCommonXsltTripRequest2Params(final StringBuilder uri) {
private final void appendCommonXsltTripRequest2Params(final HttpUrl.Builder url) {
if (useStringCoordListOutputFormat)
uri.append("&coordListOutputFormat=STRING");
url.addEncodedQueryParameter("coordListOutputFormat", "STRING");
}
@Override
@ -2072,29 +2055,29 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
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) throws IOException {
final StringBuilder uri = new StringBuilder(tripEndpoint);
final String parameters = xsltTripRequestParameters(from, via, to, date, dep, products, optimize, walkSpeed,
accessibility, options);
final HttpUrl.Builder url = tripEndpoint.newBuilder();
appendXsltTripRequestParameters(url, from, via, to, date, dep, products, optimize, walkSpeed, accessibility,
options);
final AtomicReference<QueryTripsResult> result = new AtomicReference<QueryTripsResult>();
final HttpClient.Callback callback = new HttpClient.Callback() {
@Override
public void onSuccessful(final CharSequence bodyPeek, final ResponseBody body) throws IOException {
try {
result.set(queryTrips(uri.toString(), body.byteStream()));
result.set(queryTrips(url.build(), body.byteStream()));
} catch (final XmlPullParserException x) {
throw new ParserException("cannot parse xml: " + bodyPeek, x);
} catch (final RuntimeException x) {
throw new RuntimeException("uncategorized problem while processing " + uri, x);
throw new RuntimeException("uncategorized problem while processing " + url, x);
}
}
};
if (httpPost)
httpClient.getInputStream(callback, HttpUrl.parse(uri.toString()), parameters.substring(1),
httpClient.getInputStream(callback, url.build(), url.build().encodedQuery(),
"application/x-www-form-urlencoded", httpRefererTrip);
else
httpClient.getInputStream(callback, HttpUrl.parse(uri.append(parameters).toString()), httpRefererTrip);
httpClient.getInputStream(callback, url.build(), httpRefererTrip);
return result.get();
}
@ -2103,29 +2086,29 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
final Date date, final boolean dep, final @Nullable Collection<Product> products,
final @Nullable Optimize optimize, final @Nullable WalkSpeed walkSpeed,
final @Nullable Accessibility accessibility, final @Nullable Set<Option> options) throws IOException {
final StringBuilder uri = new StringBuilder(tripEndpoint);
final String parameters = xsltTripRequestParameters(from, via, to, date, dep, products, optimize, walkSpeed,
accessibility, options);
final HttpUrl.Builder url = tripEndpoint.newBuilder();
appendXsltTripRequestParameters(url, from, via, to, date, dep, products, optimize, walkSpeed, accessibility,
options);
final AtomicReference<QueryTripsResult> result = new AtomicReference<QueryTripsResult>();
final HttpClient.Callback callback = new HttpClient.Callback() {
@Override
public void onSuccessful(final CharSequence bodyPeek, final ResponseBody body) throws IOException {
try {
result.set(queryTripsMobile(uri.toString(), from, via, to, body.byteStream()));
result.set(queryTripsMobile(url.build(), from, via, to, body.byteStream()));
} catch (final XmlPullParserException x) {
throw new ParserException("cannot parse xml: " + bodyPeek, x);
} catch (final RuntimeException x) {
throw new RuntimeException("uncategorized problem while processing " + uri, x);
throw new RuntimeException("uncategorized problem while processing " + url, x);
}
}
};
if (httpPost)
httpClient.getInputStream(callback, HttpUrl.parse(uri.toString()), parameters.substring(1),
httpClient.getInputStream(callback, url.build(), url.build().encodedQuery(),
"application/x-www-form-urlencoded", httpRefererTrip);
else
httpClient.getInputStream(callback, HttpUrl.parse(uri.append(parameters).toString()), httpRefererTrip);
httpClient.getInputStream(callback, url.build(), httpRefererTrip);
return result.get();
}
@ -2133,25 +2116,25 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
@Override
public QueryTripsResult queryMoreTrips(final QueryTripsContext contextObj, final boolean later) throws IOException {
final Context context = (Context) contextObj;
final String commandUri = context.context;
final StringBuilder uri = new StringBuilder(commandUri);
uri.append("&command=").append(later ? "tripNext" : "tripPrev");
final HttpUrl commandUrl = HttpUrl.parse(context.context);
final HttpUrl.Builder url = commandUrl.newBuilder();
url.addEncodedQueryParameter("command", later ? "tripNext" : "tripPrev");
final AtomicReference<QueryTripsResult> result = new AtomicReference<QueryTripsResult>();
final HttpClient.Callback callback = new HttpClient.Callback() {
@Override
public void onSuccessful(final CharSequence bodyPeek, final ResponseBody body) throws IOException {
try {
result.set(queryTrips(uri.toString(), body.byteStream()));
result.set(queryTrips(url.build(), body.byteStream()));
} catch (final XmlPullParserException x) {
throw new ParserException("cannot parse xml: " + bodyPeek, x);
} catch (final RuntimeException x) {
throw new RuntimeException("uncategorized problem while processing " + uri, x);
throw new RuntimeException("uncategorized problem while processing " + url, x);
}
}
};
httpClient.getInputStream(callback, HttpUrl.parse(uri.toString()), httpRefererTrip);
httpClient.getInputStream(callback, url.build(), httpRefererTrip);
return result.get();
}
@ -2159,30 +2142,30 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
protected QueryTripsResult queryMoreTripsMobile(final QueryTripsContext contextObj, final boolean later)
throws IOException {
final Context context = (Context) contextObj;
final String commandUri = context.context;
final StringBuilder uri = new StringBuilder(commandUri);
uri.append("&command=").append(later ? "tripNext" : "tripPrev");
final HttpUrl commandUrl = HttpUrl.parse(context.context);
final HttpUrl.Builder url = commandUrl.newBuilder();
url.addEncodedQueryParameter("command", later ? "tripNext" : "tripPrev");
final AtomicReference<QueryTripsResult> result = new AtomicReference<QueryTripsResult>();
final HttpClient.Callback callback = new HttpClient.Callback() {
@Override
public void onSuccessful(final CharSequence bodyPeek, final ResponseBody body) throws IOException {
try {
result.set(queryTripsMobile(uri.toString(), null, null, null, body.byteStream()));
result.set(queryTripsMobile(url.build(), null, null, null, body.byteStream()));
} catch (final XmlPullParserException x) {
throw new ParserException("cannot parse xml: " + bodyPeek, x);
} catch (final RuntimeException x) {
throw new RuntimeException("uncategorized problem while processing " + uri, x);
throw new RuntimeException("uncategorized problem while processing " + url, x);
}
}
};
httpClient.getInputStream(callback, HttpUrl.parse(uri.toString()), httpRefererTrip);
httpClient.getInputStream(callback, url.build(), httpRefererTrip);
return result.get();
}
private QueryTripsResult queryTrips(final String uri, final InputStream is)
private QueryTripsResult queryTrips(final HttpUrl url, final InputStream is)
throws XmlPullParserException, IOException {
final XmlPullParser pp = parserFactory.newPullParser();
pp.setInput(is, null); // Read encoding from XML declaration
@ -2461,8 +2444,8 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
XmlPullUtil.next(pp);
}
return new QueryTripsResult(header, uri, from, via, to, new Context(commandLink((String) context, requestId)),
trips);
return new QueryTripsResult(header, url.toString(), from, via, to,
new Context(commandLink((String) context, requestId).toString()), trips);
}
private void processIndividualLeg(final XmlPullParser pp, final List<Leg> legs,
@ -2692,7 +2675,7 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
return cancelled;
}
private QueryTripsResult queryTripsMobile(final String uri, final Location from, final @Nullable Location via,
private QueryTripsResult queryTripsMobile(final HttpUrl url, final Location from, final @Nullable Location via,
final Location to, final InputStream is) throws XmlPullParserException, IOException {
final XmlPullParser pp = parserFactory.newPullParser();
pp.setInput(is, null); // Read encoding from XML declaration
@ -2921,8 +2904,8 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
if (trips.size() > 0) {
final String[] context = (String[]) header.context;
return new QueryTripsResult(header, uri, from, via, to, new Context(commandLink(context[0], context[1])),
trips);
return new QueryTripsResult(header, url.toString(), from, via, to,
new Context(commandLink(context[0], context[1]).toString()), trips);
} else {
return new QueryTripsResult(header, QueryTripsResult.Status.NO_TRIPS);
}
@ -3068,18 +3051,16 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider {
return super.parsePosition(position);
}
private void appendLocation(final StringBuilder uri, final Location location, final String paramSuffix) {
private void appendLocationParams(final HttpUrl.Builder url, final Location location, final String paramSuffix) {
final String name = locationValue(location);
if ((location.type == LocationType.ADDRESS || location.type == LocationType.COORD) && location.hasLocation()) {
uri.append("&type_").append(paramSuffix).append("=coord");
uri.append("&name_").append(paramSuffix).append("=")
.append(String.format(Locale.ENGLISH, "%.6f:%.6f", location.lon / 1E6, location.lat / 1E6))
.append(":WGS84");
url.addEncodedQueryParameter("type_" + paramSuffix, "coord");
url.addEncodedQueryParameter("name_" + paramSuffix, ParserUtils.urlEncode(
String.format(Locale.ENGLISH, "%.6f:%.6f", location.lon / 1E6, location.lat / 1E6) + ":WGS84",
requestUrlEncoding));
} else if (name != null) {
uri.append("&type_").append(paramSuffix).append("=").append(locationTypeValue(location));
uri.append("&name_").append(paramSuffix).append("=")
.append(ParserUtils.urlEncode(name, requestUrlEncoding));
url.addEncodedQueryParameter("type_" + paramSuffix, locationTypeValue(location));
url.addEncodedQueryParameter("name_" + paramSuffix, ParserUtils.urlEncode(name, requestUrlEncoding));
} else {
throw new IllegalArgumentException("cannot append location: " + location);
}

View file

@ -102,18 +102,18 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
protected static final int DEFAULT_MAX_DEPARTURES = 100;
protected static final int DEFAULT_MAX_LOCATIONS = 50;
protected String stationBoardEndpoint;
protected String getStopEndpoint;
protected String queryEndpoint;
protected final String mgateEndpoint;
private @Nullable String extXmlEndpoint = null;
protected HttpUrl stationBoardEndpoint;
protected HttpUrl getStopEndpoint;
protected HttpUrl queryEndpoint;
protected final HttpUrl mgateEndpoint;
private @Nullable HttpUrl extXmlEndpoint = null;
protected final String apiLanguage;
private Product[] productsMap;
private @Nullable String accessId = null;
private @Nullable String clientType = "ANDROID";
private @Nullable String jsonApiVersion;
private @Nullable String jsonApiAuthorization;
private @Nullable String jsonApiClient;
private Charset jsonGetStopsEncoding = Charsets.ISO_8859_1;
private boolean jsonGetStopsUseWeight = true;
private Charset jsonNearbyLocationsEncoding = Charsets.ISO_8859_1;
private boolean dominantPlanStopTime = false;
@ -207,33 +207,33 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
}
}
public AbstractHafasProvider(final NetworkId network, final String apiBase, final String apiLanguage,
public AbstractHafasProvider(final NetworkId network, final HttpUrl apiBase, final String apiLanguage,
final Product[] productsMap) {
super(network);
this.stationBoardEndpoint = apiBase + "stboard.exe/" + apiLanguage;
this.getStopEndpoint = apiBase + "ajax-getstop.exe/" + apiLanguage;
this.queryEndpoint = apiBase + "query.exe/" + apiLanguage;
this.mgateEndpoint = apiBase + "mgate.exe";
this.stationBoardEndpoint = apiBase.newBuilder().addPathSegment("stboard.exe").build();
this.getStopEndpoint = apiBase.newBuilder().addPathSegment("ajax-getstop.exe").build();
this.queryEndpoint = apiBase.newBuilder().addPathSegment("query.exe").build();
this.mgateEndpoint = apiBase.newBuilder().addPathSegment("mgate.exe").build();
this.apiLanguage = apiLanguage;
this.productsMap = productsMap;
}
protected AbstractHafasProvider setStationBoardEndpoint(final String stationBoardEndpoint) {
protected AbstractHafasProvider setStationBoardEndpoint(final HttpUrl stationBoardEndpoint) {
this.stationBoardEndpoint = stationBoardEndpoint;
return this;
}
protected AbstractHafasProvider setGetStopEndpoint(final String getStopEndpoint) {
protected AbstractHafasProvider setGetStopEndpoint(final HttpUrl getStopEndpoint) {
this.getStopEndpoint = getStopEndpoint;
return this;
}
protected AbstractHafasProvider setQueryEndpoint(final String queryEndpoint) {
protected AbstractHafasProvider setQueryEndpoint(final HttpUrl queryEndpoint) {
this.queryEndpoint = queryEndpoint;
return this;
}
protected AbstractHafasProvider setExtXmlEndpoint(final String extXmlEndpoint) {
protected AbstractHafasProvider setExtXmlEndpoint(final HttpUrl extXmlEndpoint) {
this.extXmlEndpoint = extXmlEndpoint;
return this;
}
@ -268,11 +268,6 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
return this;
}
protected AbstractHafasProvider setJsonGetStopsEncoding(final Charset jsonGetStopsEncoding) {
this.jsonGetStopsEncoding = jsonGetStopsEncoding;
return this;
}
protected AbstractHafasProvider setJsonGetStopsUseWeight(final boolean jsonGetStopsUseWeight) {
this.jsonGetStopsUseWeight = jsonGetStopsUseWeight;
return this;
@ -449,29 +444,28 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
@Override
public SuggestLocationsResult suggestLocations(final CharSequence constraint) throws IOException {
final StringBuilder uri = new StringBuilder(getStopEndpoint);
appendJsonGetStopsParameters(uri, checkNotNull(constraint), 0);
return jsonGetStops(uri.toString());
final HttpUrl.Builder url = getStopEndpoint.newBuilder().addPathSegment(apiLanguage);
appendJsonGetStopsParameters(url, checkNotNull(constraint), 0);
return jsonGetStops(url.build());
}
protected void appendJsonGetStopsParameters(final StringBuilder uri, final CharSequence constraint,
protected void appendJsonGetStopsParameters(final HttpUrl.Builder url, final CharSequence constraint,
final int maxStops) {
uri.append("?getstop=1");
uri.append("&REQ0JourneyStopsS0A=255");
uri.append("&REQ0JourneyStopsS0G=").append(ParserUtils.urlEncode(constraint.toString(), jsonGetStopsEncoding))
.append("?");
url.addQueryParameter("getstop", "1");
url.addQueryParameter("REQ0JourneyStopsS0A", "255");
url.addEncodedQueryParameter("REQ0JourneyStopsS0G",
ParserUtils.urlEncode(constraint.toString() + "?", requestUrlEncoding));
if (maxStops > 0)
uri.append("&REQ0JourneyStopsB=").append(maxStops);
uri.append("&js=true");
url.addQueryParameter("REQ0JourneyStopsB", Integer.toString(maxStops));
url.addQueryParameter("js", "true");
}
private static final Pattern P_AJAX_GET_STOPS_JSON = Pattern
.compile("SLs\\.sls\\s*=\\s*(.*?);\\s*SLs\\.showSuggestion\\(\\);", Pattern.DOTALL);
private static final Pattern P_AJAX_GET_STOPS_ID = Pattern.compile(".*?@L=0*(\\d+)@.*?");
protected final SuggestLocationsResult jsonGetStops(final String uri) throws IOException {
final CharSequence page = httpClient.get(HttpUrl.parse(uri));
protected final SuggestLocationsResult jsonGetStops(final HttpUrl url) throws IOException {
final CharSequence page = httpClient.get(url);
final Matcher mJson = P_AJAX_GET_STOPS_JSON.matcher(page);
if (mJson.matches()) {
@ -521,7 +515,7 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
location = null;
// don't know what to do
} else {
throw new IllegalStateException("unknown type " + type + " on " + uri);
throw new IllegalStateException("unknown type " + type + " on " + url);
}
if (location != null) {
@ -533,10 +527,10 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
return new SuggestLocationsResult(new ResultHeader(network, SERVER_PRODUCT), locations);
} catch (final JSONException x) {
throw new RuntimeException("cannot parse: '" + json + "' on " + uri, x);
throw new RuntimeException("cannot parse: '" + json + "' on " + url, x);
}
} else {
throw new RuntimeException("cannot parse: '" + page + "' on " + uri);
throw new RuntimeException("cannot parse: '" + page + "' on " + url);
}
}
@ -545,30 +539,30 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
final int maxDepartures, final boolean equivs) throws IOException {
checkNotNull(Strings.emptyToNull(stationId));
final StringBuilder uri = new StringBuilder(stationBoardEndpoint);
appendXmlStationBoardParameters(uri, time, stationId, maxDepartures, equivs, "vs_java3");
return xmlStationBoard(uri.toString(), stationId);
final HttpUrl.Builder url = stationBoardEndpoint.newBuilder().addPathSegment(apiLanguage);
appendXmlStationBoardParameters(url, time, stationId, maxDepartures, equivs, "vs_java3");
return xmlStationBoard(url.build(), stationId);
}
protected void appendXmlStationBoardParameters(final StringBuilder uri, final @Nullable Date time,
protected void appendXmlStationBoardParameters(final HttpUrl.Builder url, final @Nullable Date time,
final String stationId, final int maxDepartures, final boolean equivs, final @Nullable String styleSheet) {
uri.append("?productsFilter=").append(allProductsString());
uri.append("&boardType=dep");
url.addQueryParameter("productsFilter", allProductsString().toString());
url.addQueryParameter("boardType", "dep");
if (stationBoardCanDoEquivs)
uri.append("&disableEquivs=").append(equivs ? "0" : "1");
uri.append("&maxJourneys=").append(maxDepartures > 0 ? maxDepartures : DEFAULT_MAX_DEPARTURES);
uri.append("&input=").append(normalizeStationId(stationId));
appendDateTimeParameters(uri, time, "date", "time");
url.addQueryParameter("disableEquivs", equivs ? "0" : "1");
url.addQueryParameter("maxJourneys",
Integer.toString(maxDepartures > 0 ? maxDepartures : DEFAULT_MAX_DEPARTURES));
url.addEncodedQueryParameter("input", ParserUtils.urlEncode(normalizeStationId(stationId), requestUrlEncoding));
appendDateTimeParameters(url, time, "date", "time");
if (clientType != null)
uri.append("&clientType=").append(ParserUtils.urlEncode(clientType));
url.addEncodedQueryParameter("clientType", ParserUtils.urlEncode(clientType, requestUrlEncoding));
if (styleSheet != null)
uri.append("&L=").append(styleSheet);
uri.append("&hcount=0"); // prevents showing old departures
uri.append("&start=yes");
url.addQueryParameter("L", styleSheet);
url.addQueryParameter("hcount", "0"); // prevents showing old departures
url.addQueryParameter("start", "yes");
}
protected void appendDateTimeParameters(final StringBuilder uri, final Date time, final String dateParamName,
protected void appendDateTimeParameters(final HttpUrl.Builder url, final Date time, final String dateParamName,
final String timeParamName) {
final Calendar c = new GregorianCalendar(timeZone);
c.setTime(time);
@ -577,16 +571,19 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
final int day = c.get(Calendar.DAY_OF_MONTH);
final int hour = c.get(Calendar.HOUR_OF_DAY);
final int minute = c.get(Calendar.MINUTE);
uri.append('&').append(dateParamName).append('=');
uri.append(ParserUtils.urlEncode(useIso8601 ? String.format(Locale.ENGLISH, "%04d-%02d-%02d", year, month, day)
: String.format(Locale.ENGLISH, "%02d.%02d.%02d", day, month, year - 2000)));
uri.append('&').append(timeParamName).append('=');
uri.append(ParserUtils.urlEncode(String.format(Locale.ENGLISH, "%02d:%02d", hour, minute)));
url.addEncodedQueryParameter(dateParamName,
ParserUtils.urlEncode(
useIso8601 ? String.format(Locale.ENGLISH, "%04d-%02d-%02d", year, month, day)
: String.format(Locale.ENGLISH, "%02d.%02d.%02d", day, month, year - 2000),
requestUrlEncoding));
url.addEncodedQueryParameter(timeParamName,
ParserUtils.urlEncode(String.format(Locale.ENGLISH, "%02d:%02d", hour, minute), requestUrlEncoding));
}
private static final Pattern P_XML_STATION_BOARD_DELAY = Pattern.compile("(?:-|k\\.A\\.?|cancel|([+-]?\\s*\\d+))");
protected final QueryDeparturesResult xmlStationBoard(final String uri, final String stationId) throws IOException {
protected final QueryDeparturesResult xmlStationBoard(final HttpUrl url, final String stationId)
throws IOException {
final String normalizedStationId = normalizeStationId(stationId);
final AtomicReference<QueryDeparturesResult> result = new AtomicReference<QueryDeparturesResult>();
@ -819,7 +816,7 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
throw new ParserException("cannot parse xml: " + firstChars, x);
}
}
}, HttpUrl.parse(uri));
}, url);
return result.get();
}
@ -845,8 +842,8 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
+ "\"getPOIs\":" + getPOIs + "}", //
false);
final String uri = checkNotNull(mgateEndpoint);
final CharSequence page = httpClient.get(HttpUrl.parse(uri), request, "application/json");
final HttpUrl url = checkNotNull(mgateEndpoint);
final CharSequence page = httpClient.get(url, request, "application/json");
try {
final JSONObject head = new JSONObject(page.toString());
@ -886,7 +883,7 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
return new NearbyLocationsResult(header, locations);
} catch (final JSONException x) {
throw new ParserException("cannot parse json: '" + page + "' on " + uri, x);
throw new ParserException("cannot parse json: '" + page + "' on " + url, x);
}
}
@ -910,8 +907,8 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
+ getPasslist + "}",
false);
final String uri = checkNotNull(mgateEndpoint);
final CharSequence page = httpClient.get(HttpUrl.parse(uri), request, "application/json");
final HttpUrl url = checkNotNull(mgateEndpoint);
final CharSequence page = httpClient.get(url, request, "application/json");
try {
final JSONObject head = new JSONObject(page.toString());
@ -1001,7 +998,7 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
return result;
} catch (final JSONException x) {
throw new ParserException("cannot parse json: '" + page + "' on " + uri, x);
throw new ParserException("cannot parse json: '" + page + "' on " + url, x);
}
}
@ -1011,8 +1008,8 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
+ ",\"meta\":false},\"maxLoc\":" + DEFAULT_MAX_LOCATIONS + "}}",
true);
final String uri = checkNotNull(mgateEndpoint);
final CharSequence page = httpClient.get(HttpUrl.parse(uri), request, "application/json");
final HttpUrl url = checkNotNull(mgateEndpoint);
final CharSequence page = httpClient.get(url, request, "application/json");
try {
final JSONObject head = new JSONObject(page.toString());
@ -1044,7 +1041,7 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
return new SuggestLocationsResult(header, suggestedLocations);
} catch (final JSONException x) {
throw new ParserException("cannot parse json: '" + page + "' on " + uri, x);
throw new ParserException("cannot parse json: '" + page + "' on " + url, x);
}
}
@ -1103,8 +1100,8 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
+ "\"getPolyline\":false,\"getPasslist\":true,\"getIST\":false,\"getEco\":false,\"extChgTime\":-1}", //
false);
final String uri = checkNotNull(mgateEndpoint);
final CharSequence page = httpClient.get(HttpUrl.parse(uri), request, "application/json");
final HttpUrl url = checkNotNull(mgateEndpoint);
final CharSequence page = httpClient.get(url, request, "application/json");
try {
final JSONObject head = new JSONObject(page.toString());
@ -1233,7 +1230,7 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
res.optString("outCtxScrB"));
return new QueryTripsResult(header, null, from, null, to, context, trips);
} catch (final JSONException x) {
throw new ParserException("cannot parse json: '" + page + "' on " + uri, x);
throw new ParserException("cannot parse json: '" + page + "' on " + url, x);
}
}
@ -1524,7 +1521,8 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
final CharSequence conReq, final Location from, final @Nullable Location via, final Location to)
throws IOException {
final String request = wrapReqC(conReq, null);
final String endpoint = extXmlEndpoint != null ? extXmlEndpoint : queryEndpoint;
final HttpUrl endpoint = extXmlEndpoint != null ? extXmlEndpoint
: queryEndpoint.newBuilder().addPathSegment(apiLanguage).build();
final AtomicReference<QueryTripsResult> result = new AtomicReference<QueryTripsResult>();
httpClient.getInputStream(new HttpClient.Callback() {
@Override
@ -1917,7 +1915,7 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
throw new ParserException("cannot parse xml: " + bodyPeek, x);
}
}
}, HttpUrl.parse(endpoint), request, "application/xml", null);
}, endpoint, request, "application/xml", null);
return result.get();
}
@ -2028,65 +2026,61 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
throw new IllegalArgumentException(location.type.toString());
}
protected void appendQueryTripsBinaryParameters(final StringBuilder uri, final Location from,
protected void appendQueryTripsBinaryParameters(final HttpUrl.Builder url, final Location from,
final @Nullable Location via, final Location to, final Date date, final boolean dep,
final @Nullable Set<Product> products, final @Nullable Accessibility accessibility,
final @Nullable Set<Option> options) {
uri.append("?start=Suchen");
uri.append("&REQ0JourneyStopsS0ID=").append(ParserUtils.urlEncode(locationId(from), Charsets.ISO_8859_1));
uri.append("&REQ0JourneyStopsZ0ID=").append(ParserUtils.urlEncode(locationId(to), Charsets.ISO_8859_1));
url.addQueryParameter("start", "Suchen");
url.addEncodedQueryParameter("REQ0JourneyStopsS0ID",
ParserUtils.urlEncode(locationId(from), requestUrlEncoding));
url.addEncodedQueryParameter("REQ0JourneyStopsZ0ID", ParserUtils.urlEncode(locationId(to), requestUrlEncoding));
if (via != null) {
// workaround, for there does not seem to be a REQ0JourneyStops1.0ID parameter
uri.append("&REQ0JourneyStops1.0A=").append(locationType(via));
url.addQueryParameter("REQ0JourneyStops1.0A", Integer.toString(locationType(via)));
if (via.type == LocationType.STATION && via.hasId()) {
uri.append("&REQ0JourneyStops1.0L=").append(via.id);
url.addQueryParameter("REQ0JourneyStops1.0L", via.id);
} else if (via.hasLocation()) {
uri.append("&REQ0JourneyStops1.0X=").append(via.lon);
uri.append("&REQ0JourneyStops1.0Y=").append(via.lat);
url.addQueryParameter("REQ0JourneyStops1.0X", Integer.toString(via.lon));
url.addQueryParameter("REQ0JourneyStops1.0Y", Integer.toString(via.lat));
if (via.name == null)
uri.append("&REQ0JourneyStops1.0O=")
.append(ParserUtils.urlEncode(
String.format(Locale.ENGLISH, "%.6f, %.6f", via.lat / 1E6, via.lon / 1E6),
Charsets.ISO_8859_1));
url.addQueryParameter("REQ0JourneyStops1.0O",
String.format(Locale.ENGLISH, "%.6f, %.6f", via.lat / 1E6, via.lon / 1E6));
} else if (via.name != null) {
uri.append("&REQ0JourneyStops1.0G=").append(ParserUtils.urlEncode(via.name, Charsets.ISO_8859_1));
if (via.type != LocationType.ANY)
uri.append('!');
url.addEncodedQueryParameter("REQ0JourneyStops1.0G", ParserUtils
.urlEncode(via.name + (via.type != LocationType.ANY ? "!" : ""), requestUrlEncoding));
}
}
uri.append("&REQ0HafasSearchForw=").append(dep ? "1" : "0");
url.addQueryParameter("REQ0HafasSearchForw", dep ? "1" : "0");
appendDateTimeParameters(uri, date, "REQ0JourneyDate", "REQ0JourneyTime");
appendDateTimeParameters(url, date, "REQ0JourneyDate", "REQ0JourneyTime");
final CharSequence productsStr;
if (products != null)
productsStr = productsString(products);
else
productsStr = allProductsString();
uri.append("&REQ0JourneyProduct_prod_list_1=").append(productsStr);
url.addQueryParameter("REQ0JourneyProduct_prod_list_1", productsStr.toString());
if (accessibility != null && accessibility != Accessibility.NEUTRAL) {
if (accessibility == Accessibility.LIMITED)
uri.append("&REQ0AddParamBaimprofile=1");
url.addQueryParameter("REQ0AddParamBaimprofile", "1");
else if (accessibility == Accessibility.BARRIER_FREE)
uri.append("&REQ0AddParamBaimprofile=0");
url.addQueryParameter("REQ0AddParamBaimprofile", "0");
}
if (options != null && options.contains(Option.BIKE))
uri.append("&REQ0JourneyProduct_opt3=1");
url.addQueryParameter("REQ0JourneyProduct_opt3", "1");
appendCommonQueryTripsBinaryParameters(uri);
appendCommonQueryTripsBinaryParameters(url);
}
protected void appendCommonQueryTripsBinaryParameters(final StringBuilder uri) {
uri.append("&h2g-direct=11");
protected void appendCommonQueryTripsBinaryParameters(final HttpUrl.Builder url) {
url.addQueryParameter("h2g-direct", "11");
if (clientType != null)
uri.append("&clientType=").append(ParserUtils.urlEncode(clientType));
url.addEncodedQueryParameter("clientType", ParserUtils.urlEncode(clientType, requestUrlEncoding));
}
private final static int QUERY_TRIPS_BINARY_BUFFER_SIZE = 384 * 1024;
@ -2124,32 +2118,28 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
to = locations.get(0);
}
final StringBuilder uri = new StringBuilder(queryEndpoint);
appendQueryTripsBinaryParameters(uri, from, via, to, date, dep, products, accessibility, options);
return queryTripsBinary(uri.toString(), from, via, to, QUERY_TRIPS_BINARY_BUFFER_SIZE);
final HttpUrl.Builder url = queryEndpoint.newBuilder().addPathSegment(apiLanguage);
appendQueryTripsBinaryParameters(url, from, via, to, date, dep, products, accessibility, options);
return queryTripsBinary(url.build(), from, via, to, QUERY_TRIPS_BINARY_BUFFER_SIZE);
}
protected void appendQueryMoreTripsBinaryParameters(final StringBuilder uri, final QueryTripsBinaryContext context,
final boolean later) {
uri.append("?seqnr=").append(context.seqNr);
uri.append("&ident=").append(context.ident);
protected void appendQueryMoreTripsBinaryParameters(final HttpUrl.Builder url,
final QueryTripsBinaryContext context, final boolean later) {
url.addQueryParameter("seqnr", Integer.toString(context.seqNr));
url.addQueryParameter("ident", context.ident);
if (context.ld != null)
uri.append("&ld=").append(context.ld);
uri.append("&REQ0HafasScrollDir=").append(later ? 1 : 2);
appendCommonQueryTripsBinaryParameters(uri);
url.addQueryParameter("ld", context.ld);
url.addQueryParameter("REQ0HafasScrollDir", later ? "1" : "2");
appendCommonQueryTripsBinaryParameters(url);
}
protected QueryTripsResult queryMoreTripsBinary(final QueryTripsContext contextObj, final boolean later)
throws IOException {
final QueryTripsBinaryContext context = (QueryTripsBinaryContext) contextObj;
final StringBuilder uri = new StringBuilder(queryEndpoint);
appendQueryMoreTripsBinaryParameters(uri, context, later);
return queryTripsBinary(uri.toString(), null, null, null,
QUERY_TRIPS_BINARY_BUFFER_SIZE + context.usedBufferSize);
final HttpUrl.Builder url = queryEndpoint.newBuilder().addPathSegment(apiLanguage);
appendQueryMoreTripsBinaryParameters(url, context, later);
return queryTripsBinary(url.build(), null, null, null, QUERY_TRIPS_BINARY_BUFFER_SIZE + context.usedBufferSize);
}
private class CustomBufferedInputStream extends BufferedInputStream {
@ -2162,7 +2152,7 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
}
}
private QueryTripsResult queryTripsBinary(final String uri, final Location from, final @Nullable Location via,
private QueryTripsResult queryTripsBinary(final HttpUrl url, final Location from, final @Nullable Location via,
final Location to, final int expectedBufferSize) throws IOException {
/*
* Many thanks to Malte Starostik and Robert, who helped a lot with analyzing this API!
@ -2228,7 +2218,8 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
final int numTrips = is.readShortReverse();
if (numTrips == 0) {
result.set(new QueryTripsResult(header, uri, from, via, to, null, new LinkedList<Trip>()));
result.set(new QueryTripsResult(header, url.toString(), from, via, to, null,
new LinkedList<Trip>()));
return;
}
@ -2655,7 +2646,7 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
final boolean canQueryMore = trips.size() != 1 || trips.get(0).legs.size() != 1
|| !(trips.get(0).legs.get(0) instanceof Trip.Individual);
result.set(new QueryTripsResult(header, uri, from, via, to,
result.set(new QueryTripsResult(header, url.toString(), from, via, to,
new QueryTripsBinaryContext(requestId, seqNr, ld, bis.getCount(), canQueryMore), trips));
} else {
log.debug("Hafas error: {}", errorCode);
@ -2749,11 +2740,11 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
result.set(new QueryTripsResult(header, QueryTripsResult.Status.SERVICE_DOWN));
return;
} else {
throw new IllegalStateException("error " + errorCode + " on " + uri);
throw new IllegalStateException("error " + errorCode + " on " + url);
}
}
}
}, HttpUrl.parse(uri));
}, url);
return result.get();
}
@ -2958,34 +2949,34 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
protected final NearbyLocationsResult nearbyLocationsByCoordinate(final EnumSet<LocationType> types, final int lat,
final int lon, final int maxDistance, final int maxLocations) throws IOException {
if (types.contains(LocationType.STATION)) {
final StringBuilder uri = new StringBuilder(queryEndpoint);
appendJsonNearbyStationsParameters(uri, lat, lon, maxDistance, maxLocations);
return jsonNearbyLocations(uri.toString());
final HttpUrl.Builder url = queryEndpoint.newBuilder().addPathSegment(apiLanguage + "y");
appendJsonNearbyStationsParameters(url, lat, lon, maxDistance, maxLocations);
return jsonNearbyLocations(url.build());
} else if (types.contains(LocationType.POI)) {
final StringBuilder uri = new StringBuilder(queryEndpoint);
appendJsonNearbyPOIsParameters(uri, lat, lon, maxDistance, maxLocations);
return jsonNearbyLocations(uri.toString());
final HttpUrl.Builder url = queryEndpoint.newBuilder().addPathSegment(apiLanguage + "y");
appendJsonNearbyPOIsParameters(url, lat, lon, maxDistance, maxLocations);
return jsonNearbyLocations(url.build());
} else {
return new NearbyLocationsResult(null, Collections.<Location> emptyList());
}
}
protected NearbyLocationsResult nearbyStationsById(final String id, final int maxDistance) throws IOException {
final StringBuilder uri = new StringBuilder(stationBoardEndpoint);
appendXmlNearbyStationsParameters(uri, id);
return xmlNearbyStations(uri.toString());
final HttpUrl.Builder url = stationBoardEndpoint.newBuilder().addPathSegment(apiLanguage);
appendXmlNearbyStationsParameters(url, id);
return xmlNearbyStations(url.build());
}
protected final void appendXmlNearbyStationsParameters(final StringBuilder uri, final String stationId) {
uri.append("?productsFilter=").append(allProductsString());
uri.append("&boardType=dep");
uri.append("&input=").append(normalizeStationId(stationId));
uri.append("&sTI=1&start=yes&hcount=0&L=vs_java3");
protected final void appendXmlNearbyStationsParameters(final HttpUrl.Builder url, final String stationId) {
url.addQueryParameter("productsFilter", allProductsString().toString());
url.addQueryParameter("boardType", "dep");
url.addEncodedQueryParameter("input", ParserUtils.urlEncode(normalizeStationId(stationId), requestUrlEncoding));
url.addQueryParameter("sTI", "1");
url.addQueryParameter("start", "yes");
url.addQueryParameter("hcount", "0");
url.addQueryParameter("L", "vs_java3");
if (clientType != null)
uri.append("&clientType=").append(ParserUtils.urlEncode(clientType));
url.addEncodedQueryParameter("clientType", ParserUtils.urlEncode(clientType, requestUrlEncoding));
}
private static final Pattern P_XML_NEARBY_STATIONS_COARSE = Pattern.compile("\\G<\\s*St\\s*(.*?)/?>(?:\n|\\z)",
@ -3000,9 +2991,9 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
private static final Pattern P_XML_NEARBY_STATIONS_MESSAGES = Pattern
.compile("<Err code=\"([^\"]*)\" text=\"([^\"]*)\"");
protected final NearbyLocationsResult xmlNearbyStations(final String uri) throws IOException {
protected final NearbyLocationsResult xmlNearbyStations(final HttpUrl url) throws IOException {
// scrape page
final CharSequence page = httpClient.get(HttpUrl.parse(uri));
final CharSequence page = httpClient.get(url);
final List<Location> stations = new ArrayList<Location>();
@ -3041,44 +3032,44 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
stations.add(new Location(LocationType.STATION, parsedId, parsedLat, parsedLon, placeAndName[0],
placeAndName[1]));
} else {
throw new IllegalArgumentException("cannot parse '" + mCoarse.group(1) + "' on " + uri);
throw new IllegalArgumentException("cannot parse '" + mCoarse.group(1) + "' on " + url);
}
}
return new NearbyLocationsResult(null, stations);
}
protected void appendJsonNearbyStationsParameters(final StringBuilder uri, final int lat, final int lon,
protected void appendJsonNearbyStationsParameters(final HttpUrl.Builder url, final int lat, final int lon,
final int maxDistance, final int maxStations) {
uri.append('y');
uri.append("?performLocating=2&tpl=stop2json");
uri.append("&look_stopclass=").append(allProductsInt());
uri.append("&look_nv=get_stopweight|yes");
url.addQueryParameter("performLocating", "2");
url.addQueryParameter("tpl", "stop2json");
url.addQueryParameter("look_stopclass", Integer.toString(allProductsInt()));
url.addQueryParameter("look_nv", "get_stopweight|yes");
// get_shortjson|yes
// get_lines|yes
// combinemode|2
// density|80
// get_stopweight|yes
// get_infotext|yes
uri.append("&look_x=").append(lon);
uri.append("&look_y=").append(lat);
uri.append("&look_maxno=").append(maxStations != 0 ? maxStations : 200);
uri.append("&look_maxdist=").append(maxDistance != 0 ? maxDistance : 5000);
url.addQueryParameter("look_x", Integer.toString(lon));
url.addQueryParameter("look_y", Integer.toString(lat));
url.addQueryParameter("look_maxno", Integer.toString(maxStations != 0 ? maxStations : 200));
url.addQueryParameter("look_maxdist", Integer.toString(maxDistance != 0 ? maxDistance : 5000));
}
protected void appendJsonNearbyPOIsParameters(final StringBuilder uri, final int lat, final int lon,
protected void appendJsonNearbyPOIsParameters(final HttpUrl.Builder url, final int lat, final int lon,
final int maxDistance, final int maxStations) {
uri.append('y');
uri.append("?performLocating=4&tpl=poi2json");
uri.append("&look_pois="); // all categories
uri.append("&look_x=").append(lon);
uri.append("&look_y=").append(lat);
uri.append("&look_maxno=").append(maxStations != 0 ? maxStations : 200);
uri.append("&look_maxdist=").append(maxDistance != 0 ? maxDistance : 5000);
url.addQueryParameter("performLocating", "4");
url.addQueryParameter("tpl", "poi2json");
url.addQueryParameter("look_pois", ""); // all categories
url.addQueryParameter("look_x", Integer.toString(lon));
url.addQueryParameter("look_y", Integer.toString(lat));
url.addQueryParameter("look_maxno", Integer.toString(maxStations != 0 ? maxStations : 200));
url.addQueryParameter("look_maxdist", Integer.toString(maxDistance != 0 ? maxDistance : 5000));
}
protected final NearbyLocationsResult jsonNearbyLocations(final String uri) throws IOException {
final CharSequence page = httpClient.get(HttpUrl.parse(uri));
protected final NearbyLocationsResult jsonNearbyLocations(final HttpUrl url) throws IOException {
final CharSequence page = httpClient.get(url);
try {
final JSONObject head = new JSONObject(page.toString());
@ -3138,7 +3129,7 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
}
} catch (final JSONException x) {
x.printStackTrace();
throw new RuntimeException("cannot parse: '" + page + "' on " + uri, x);
throw new RuntimeException("cannot parse: '" + page + "' on " + url, x);
}
}
@ -3157,10 +3148,10 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
private static final Pattern P_HTML_NEARBY_STATIONS_MESSAGES = Pattern
.compile("(Ihre Eingabe kann nicht interpretiert werden)");
protected final NearbyLocationsResult htmlNearbyStations(final String uri) throws IOException {
protected final NearbyLocationsResult htmlNearbyStations(final HttpUrl url) throws IOException {
final List<Location> stations = new ArrayList<Location>();
final CharSequence page = httpClient.get(HttpUrl.parse(uri));
final CharSequence page = httpClient.get(url);
String oldZebra = null;
final Matcher mCoarse = htmlNearbyStationsPattern.matcher(page);
@ -3197,7 +3188,7 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider {
stations.add(new Location(LocationType.STATION, parsedId, parsedLat, parsedLon, placeAndName[0],
placeAndName[1]));
} else {
throw new IllegalArgumentException("cannot parse '" + mCoarse.group(2) + "' on " + uri);
throw new IllegalArgumentException("cannot parse '" + mCoarse.group(2) + "' on " + url);
}
}

View file

@ -64,7 +64,6 @@ import de.schildbach.pte.dto.Trip.Leg;
import de.schildbach.pte.dto.Trip.Public;
import de.schildbach.pte.exception.NotFoundException;
import de.schildbach.pte.exception.ParserException;
import de.schildbach.pte.util.ParserUtils;
import okhttp3.HttpUrl;
@ -77,7 +76,8 @@ public abstract class AbstractNavitiaProvider extends AbstractNetworkProvider {
protected final static String SERVER_PRODUCT = "navitia";
protected final static String SERVER_VERSION = "v1";
protected String apiBase = "https://api.navitia.io/" + SERVER_VERSION + "/";
protected HttpUrl apiBase = HttpUrl.parse("https://api.navitia.io/").newBuilder().addPathSegment(SERVER_VERSION)
.build();
private enum PlaceType {
ADDRESS, ADMINISTRATIVE_REGION, POI, STOP_POINT, STOP_AREA
@ -125,7 +125,7 @@ public abstract class AbstractNavitiaProvider extends AbstractNetworkProvider {
}
}
public AbstractNavitiaProvider(final NetworkId network, final String apiBase, final String authorization) {
public AbstractNavitiaProvider(final NetworkId network, final HttpUrl apiBase, final String authorization) {
this(network, authorization);
this.apiBase = apiBase;
@ -163,12 +163,8 @@ public abstract class AbstractNavitiaProvider extends AbstractNetworkProvider {
}
}
private String uri() {
return apiBase + "coverage/" + region() + "/";
}
private String tripUri() {
return apiBase;
private HttpUrl.Builder url() {
return apiBase.newBuilder().addPathSegment("coverage").addPathSegment(region());
}
private Point parseCoord(final JSONObject coord) throws IOException {
@ -644,8 +640,9 @@ public abstract class AbstractNavitiaProvider extends AbstractNetworkProvider {
}
private String getStopAreaId(final String stopPointId) throws IOException {
final String uri = uri() + "stop_points/" + ParserUtils.urlEncode(stopPointId) + "?depth=1";
final CharSequence page = httpClient.get(HttpUrl.parse(uri));
final HttpUrl.Builder url = url().addPathSegment("stop_points").addPathSegment(stopPointId);
url.addQueryParameter("depth", "1");
final CharSequence page = httpClient.get(url.build());
try {
final JSONObject head = new JSONObject(page.toString());
@ -672,37 +669,33 @@ public abstract class AbstractNavitiaProvider extends AbstractNetworkProvider {
int maxDistance, final int maxLocations) throws IOException {
final ResultHeader resultHeader = new ResultHeader(network, SERVER_PRODUCT, SERVER_VERSION, null, 0, null);
// Build query uri depending of location type.
final StringBuilder queryUri = new StringBuilder(uri());
// Build url depending of location type.
final HttpUrl.Builder url = url();
if (location.type == LocationType.COORD || location.type == LocationType.ADDRESS
|| location.type == LocationType.ANY) {
if (!location.hasLocation())
throw new IllegalArgumentException();
final double lon = location.lon / 1E6;
final double lat = location.lat / 1E6;
queryUri.append("coords/").append(lon).append(';').append(lat);
url.addPathSegment("coords").addPathSegment(lon + ";" + lat);
} else if (location.type == LocationType.STATION) {
if (!location.isIdentified())
throw new IllegalArgumentException();
queryUri.append("stop_points/").append(location.id);
url.addPathSegment("stop_points").addPathSegment(location.id);
} else if (location.type == LocationType.POI) {
if (!location.isIdentified())
throw new IllegalArgumentException();
queryUri.append("pois/").append(location.id);
url.addPathSegment("pois").addPathSegment(location.id);
} else {
throw new IllegalArgumentException("Unhandled location type: " + location.type);
}
queryUri.append('/');
if (maxDistance == 0)
maxDistance = 50000;
queryUri.append("places_nearby?type[]=stop_point");
queryUri.append("&distance=").append(maxDistance);
url.addPathSegment("places_nearby");
url.addQueryParameter("type[]", "stop_point");
url.addQueryParameter("distance", Integer.toString(maxDistance == 0 ? 50000 : maxDistance));
if (maxLocations > 0)
queryUri.append("&count=").append(maxLocations);
queryUri.append("&depth=3");
final CharSequence page = httpClient.get(HttpUrl.parse(queryUri.toString()));
url.addQueryParameter("count", Integer.toString(maxLocations));
url.addQueryParameter("depth", "3");
final CharSequence page = httpClient.get(url.build());
try {
final JSONObject head = new JSONObject(page.toString());
@ -747,37 +740,28 @@ public abstract class AbstractNavitiaProvider extends AbstractNetworkProvider {
final QueryDeparturesResult result = new QueryDeparturesResult(resultHeader,
QueryDeparturesResult.Status.OK);
final String dateTime = printDate(time);
// If equivs is equal to true, get stop_area corresponding
// to stop_point and query departures.
final StringBuilder queryUri = new StringBuilder();
queryUri.append(uri());
final HttpUrl.Builder url = url();
final String header = stationId.substring(0, stationId.indexOf(":"));
if (equivs && header.equals("stop_point")) {
final String stopAreaId = getStopAreaId(stationId);
queryUri.append("stop_areas/");
queryUri.append(stopAreaId);
queryUri.append("/");
url.addPathSegment("stop_areas");
url.addPathSegment(stopAreaId);
} else if (header.equals("stop_area")) {
url.addPathSegment("stop_areas");
url.addPathSegment(stationId);
} else {
if (header.equals("stop_area")) {
queryUri.append("stop_areas/");
queryUri.append(stationId);
queryUri.append("/");
} else {
queryUri.append("stop_points/");
queryUri.append(stationId);
queryUri.append("/");
}
url.addPathSegment("stop_points");
url.addPathSegment(stationId);
}
queryUri.append("departures?from_datetime=");
queryUri.append(dateTime);
queryUri.append("&count=");
queryUri.append(maxDepartures);
queryUri.append("&duration=86400");
queryUri.append("&depth=0");
url.addPathSegment("departures");
url.addQueryParameter("from_datetime", printDate(time));
url.addQueryParameter("count", Integer.toString(maxDepartures));
url.addQueryParameter("duration", "86400");
url.addQueryParameter("depth", "0");
final CharSequence page = httpClient.get(HttpUrl.parse(queryUri.toString()));
final CharSequence page = httpClient.get(url.build());
final JSONObject head = new JSONObject(page.toString());
@ -843,9 +827,14 @@ public abstract class AbstractNavitiaProvider extends AbstractNetworkProvider {
public SuggestLocationsResult suggestLocations(final CharSequence constraint) throws IOException {
final String nameCstr = constraint.toString();
final String queryUri = uri() + "places?q=" + ParserUtils.urlEncode(nameCstr)
+ "&type[]=stop_area&type[]=address&type[]=poi&type[]=administrative_region" + "&depth=1";
final CharSequence page = httpClient.get(HttpUrl.parse(queryUri));
final HttpUrl.Builder url = url().addPathSegment("places");
url.addQueryParameter("q", nameCstr);
url.addQueryParameter("type[]", "stop_area");
url.addQueryParameter("type[]", "address");
url.addQueryParameter("type[]", "poi");
url.addQueryParameter("type[]", "administrative_region");
url.addQueryParameter("depth", "1");
final CharSequence page = httpClient.get(url.build());
try {
final List<SuggestedLocation> locations = new ArrayList<SuggestedLocation>();
@ -881,13 +870,13 @@ public abstract class AbstractNavitiaProvider extends AbstractNetworkProvider {
try {
if (from != null && from.isIdentified() && to != null && to.isIdentified()) {
final StringBuilder queryUri = new StringBuilder(tripUri()).append("journeys");
queryUri.append("?from=").append(ParserUtils.urlEncode(printLocation(from)));
queryUri.append("&to=").append(ParserUtils.urlEncode(printLocation(to)));
queryUri.append("&datetime=").append(printDate(date));
queryUri.append("&datetime_represents=").append(dep ? "departure" : "arrival");
queryUri.append("&count=").append(this.numTripsRequested);
queryUri.append("&depth=0");
final HttpUrl.Builder url = apiBase.newBuilder().addPathSegment("journeys");
url.addQueryParameter("from", printLocation(from));
url.addQueryParameter("to", printLocation(to));
url.addQueryParameter("datetime", printDate(date));
url.addQueryParameter("datetime_represents", dep ? "departure" : "arrival");
url.addQueryParameter("count", Integer.toString(this.numTripsRequested));
url.addQueryParameter("depth", "0");
// Set walking speed.
if (walkSpeed != null) {
@ -905,51 +894,51 @@ public abstract class AbstractNavitiaProvider extends AbstractNetworkProvider {
break;
}
queryUri.append("&walking_speed=").append(walkingSpeed);
url.addQueryParameter("walking_speed", Double.toString(walkingSpeed));
}
if (options != null && options.contains(Option.BIKE)) {
queryUri.append("&first_section_mode=bike");
queryUri.append("&last_section_mode=bike");
url.addQueryParameter("first_section_mode", "bike");
url.addQueryParameter("last_section_mode", "bike");
}
// Set forbidden physical modes.
if (products != null && !products.equals(Product.ALL)) {
queryUri.append("&forbidden_uris[]=physical_mode:Air");
queryUri.append("&forbidden_uris[]=physical_mode:Boat");
url.addQueryParameter("forbidden_uris[]", "physical_mode:Air");
url.addQueryParameter("forbidden_uris[]", "physical_mode:Boat");
if (!products.contains(Product.REGIONAL_TRAIN)) {
queryUri.append("&forbidden_uris[]=physical_mode:Localdistancetrain");
queryUri.append("&forbidden_uris[]=physical_mode:Train");
url.addQueryParameter("forbidden_uris[]", "physical_mode:Localdistancetrain");
url.addQueryParameter("forbidden_uris[]", "physical_mode:Train");
}
if (!products.contains(Product.SUBURBAN_TRAIN)) {
queryUri.append("&forbidden_uris[]=physical_mode:Localtrain");
queryUri.append("&forbidden_uris[]=physical_mode:Train");
queryUri.append("&forbidden_uris[]=physical_mode:Rapidtransit");
url.addQueryParameter("forbidden_uris[]", "physical_mode:Localtrain");
url.addQueryParameter("forbidden_uris[]", "physical_mode:Train");
url.addQueryParameter("forbidden_uris[]", "physical_mode:Rapidtransit");
}
if (!products.contains(Product.SUBWAY)) {
queryUri.append("&forbidden_uris[]=physical_mode:Metro");
url.addQueryParameter("forbidden_uris[]", "physical_mode:Metro");
}
if (!products.contains(Product.TRAM)) {
queryUri.append("&forbidden_uris[]=physical_mode:Tramway");
url.addQueryParameter("forbidden_uris[]", "physical_mode:Tramway");
}
if (!products.contains(Product.BUS)) {
queryUri.append("&forbidden_uris[]=physical_mode:Bus");
queryUri.append("&forbidden_uris[]=physical_mode:Busrapidtransit");
queryUri.append("&forbidden_uris[]=physical_mode:Coach");
queryUri.append("&forbidden_uris[]=physical_mode:Shuttle");
url.addQueryParameter("forbidden_uris[]", "physical_mode:Bus");
url.addQueryParameter("forbidden_uris[]", "physical_mode:Busrapidtransit");
url.addQueryParameter("forbidden_uris[]", "physical_mode:Coach");
url.addQueryParameter("forbidden_uris[]", "physical_mode:Shuttle");
}
if (!products.contains(Product.FERRY)) {
queryUri.append("&forbidden_uris[]=physical_mode:Ferry");
url.addQueryParameter("forbidden_uris[]", "physical_mode:Ferry");
}
if (!products.contains(Product.CABLECAR)) {
queryUri.append("&forbidden_uris[]=physical_mode:Funicular");
url.addQueryParameter("forbidden_uris[]", "physical_mode:Funicular");
}
if (!products.contains(Product.ON_DEMAND)) {
queryUri.append("&forbidden_uris[]=physical_mode:Taxi");
url.addQueryParameter("forbidden_uris[]", "physical_mode:Taxi");
}
}
final CharSequence page = httpClient.get(HttpUrl.parse(queryUri.toString()));
final CharSequence page = httpClient.get(url.build());
try {
final JSONObject head = new JSONObject(page.toString());
@ -964,21 +953,22 @@ public abstract class AbstractNavitiaProvider extends AbstractNetworkProvider {
throw new IllegalArgumentException("Unhandled error id: " + id);
} else {
// Fill context.
String prevQueryUri = null;
String nextQueryUri = null;
HttpUrl prevQueryUrl = null;
HttpUrl nextQueryUrl = null;
final JSONArray links = head.getJSONArray("links");
for (int i = 0; i < links.length(); ++i) {
final JSONObject link = links.getJSONObject(i);
final String type = link.getString("type");
if (type.equals("prev")) {
prevQueryUri = link.getString("href");
prevQueryUrl = HttpUrl.parse(link.getString("href"));
} else if (type.equals("next")) {
nextQueryUri = link.getString("href");
nextQueryUrl = HttpUrl.parse(link.getString("href"));
}
}
final QueryTripsResult result = new QueryTripsResult(resultHeader, queryUri.toString(), from,
null, to, new Context(from, to, prevQueryUri, nextQueryUri), new LinkedList<Trip>());
final QueryTripsResult result = new QueryTripsResult(resultHeader, url.build().toString(), from,
null, to, new Context(from, to, prevQueryUrl.toString(), nextQueryUrl.toString()),
new LinkedList<Trip>());
parseQueryTripsResult(head, from, to, result);
@ -1051,8 +1041,8 @@ public abstract class AbstractNavitiaProvider extends AbstractNetworkProvider {
final Context context = (Context) contextObj;
final Location from = context.from;
final Location to = context.to;
final String queryUri = later ? context.nextQueryUri : context.prevQueryUri;
final CharSequence page = httpClient.get(HttpUrl.parse(queryUri));
final HttpUrl queryUrl = HttpUrl.parse(later ? context.nextQueryUri : context.prevQueryUri);
final CharSequence page = httpClient.get(queryUrl);
try {
if (from.isIdentified() && to.isIdentified()) {
@ -1061,12 +1051,13 @@ public abstract class AbstractNavitiaProvider extends AbstractNetworkProvider {
// Fill context.
final JSONArray links = head.getJSONArray("links");
final JSONObject prev = links.getJSONObject(0);
final String prevQueryUri = prev.getString("href");
final HttpUrl prevQueryUrl = HttpUrl.parse(prev.getString("href"));
final JSONObject next = links.getJSONObject(1);
final String nextQueryUri = next.getString("href");
final HttpUrl nextQueryUrl = HttpUrl.parse(next.getString("href"));
final QueryTripsResult result = new QueryTripsResult(resultHeader, queryUri, from, null, to,
new Context(from, to, prevQueryUri, nextQueryUri), new LinkedList<Trip>());
final QueryTripsResult result = new QueryTripsResult(resultHeader, queryUrl.toString(), from, null, to,
new Context(from, to, prevQueryUrl.toString(), nextQueryUrl.toString()),
new LinkedList<Trip>());
parseQueryTripsResult(head, from, to, result);
@ -1081,8 +1072,8 @@ public abstract class AbstractNavitiaProvider extends AbstractNetworkProvider {
@Override
public Point[] getArea() throws IOException {
final String queryUri = uri();
final CharSequence page = httpClient.get(HttpUrl.parse(queryUri));
final HttpUrl.Builder url = url();
final CharSequence page = httpClient.get(url.build());
try {
// Get shape string.

View file

@ -19,6 +19,7 @@ package de.schildbach.pte;
import java.io.IOException;
import java.net.Proxy;
import java.nio.charset.Charset;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
@ -28,6 +29,7 @@ import java.util.regex.Pattern;
import javax.annotation.Nullable;
import com.google.common.base.Charsets;
import com.google.common.base.Strings;
import de.schildbach.pte.dto.Point;
@ -43,6 +45,7 @@ public abstract class AbstractNetworkProvider implements NetworkProvider {
protected final NetworkId network;
protected final HttpClient httpClient = new HttpClient();
protected Charset requestUrlEncoding = Charsets.ISO_8859_1;
protected TimeZone timeZone = TimeZone.getTimeZone("CET");
protected int numTripsRequested = 6;
private @Nullable Map<String, Style> styles = null;
@ -85,6 +88,11 @@ public abstract class AbstractNetworkProvider implements NetworkProvider {
return this;
}
protected AbstractNetworkProvider setRequestUrlEncoding(final Charset requestUrlEncoding) {
this.requestUrlEncoding = requestUrlEncoding;
return this;
}
protected AbstractNetworkProvider setTimeZone(final String timeZoneId) {
this.timeZone = TimeZone.getTimeZone(timeZoneId);
return this;

View file

@ -40,8 +40,6 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.google.common.base.Charsets;
import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Location;
import de.schildbach.pte.dto.LocationType;
@ -57,7 +55,6 @@ import de.schildbach.pte.dto.SuggestLocationsResult;
import de.schildbach.pte.dto.SuggestedLocation;
import de.schildbach.pte.dto.Trip;
import de.schildbach.pte.exception.ParserException;
import de.schildbach.pte.util.ParserUtils;
import okhttp3.HttpUrl;
@ -122,8 +119,8 @@ public abstract class AbstractTsiProvider extends AbstractNetworkProvider {
}
}
private static final String DEFAULT_STOPFINDER_ENDPOINT = "/Transport/v2/";
private static final String DEFAULT_TRIP_ENDPOINT = "/journeyplanner/v2/";
private static final String DEFAULT_STOPFINDER_ENDPOINT = "Transport/v2";
private static final String DEFAULT_TRIP_ENDPOINT = "journeyplanner/v2";
private static final String SERVER_PRODUCT = "tsi";
private static Map<String, Product> TRANSPORT_MODES = new HashMap<String, Product>();
@ -160,15 +157,15 @@ public abstract class AbstractTsiProvider extends AbstractNetworkProvider {
}
private final @Nullable String apiKey;
private final String stopFinderEndpoint;
private final String tripEndpoint;
private final HttpUrl stopFinderEndpoint;
private final HttpUrl tripEndpoint;
public AbstractTsiProvider(final NetworkId network, final String apiKey, final String apiBase) {
public AbstractTsiProvider(final NetworkId network, final String apiKey, final HttpUrl apiBase) {
this(network, apiKey, apiBase, null, null);
}
public AbstractTsiProvider(final NetworkId network, final String apiKey, final String tripEndpoint,
final String stopFinderEndpoint) {
public AbstractTsiProvider(final NetworkId network, final String apiKey, final HttpUrl tripEndpoint,
final HttpUrl stopFinderEndpoint) {
super(network);
this.apiKey = apiKey;
@ -176,10 +173,14 @@ public abstract class AbstractTsiProvider extends AbstractNetworkProvider {
this.stopFinderEndpoint = stopFinderEndpoint;
}
public AbstractTsiProvider(final NetworkId network, final String apiKey, final String apiBase,
public AbstractTsiProvider(final NetworkId network, final String apiKey, final HttpUrl apiBase,
final String tripEndpoint, final String stopFinderEndpoint) {
this(network, apiKey, apiBase + (tripEndpoint != null ? tripEndpoint : DEFAULT_TRIP_ENDPOINT), //
apiBase + (stopFinderEndpoint != null ? stopFinderEndpoint : DEFAULT_STOPFINDER_ENDPOINT));
this(network, apiKey,
apiBase.newBuilder().addPathSegments(tripEndpoint != null ? tripEndpoint : DEFAULT_TRIP_ENDPOINT)
.build(),
apiBase.newBuilder()
.addPathSegments(stopFinderEndpoint != null ? stopFinderEndpoint : DEFAULT_STOPFINDER_ENDPOINT)
.build());
}
@Override
@ -192,14 +193,12 @@ public abstract class AbstractTsiProvider extends AbstractNetworkProvider {
@Override
public SuggestLocationsResult suggestLocations(final CharSequence constraint) throws IOException {
final StringBuilder parameters = buildCommonRequestParams("SearchTripPoint", "json");
parameters.append("&MaxItems=").append(50); // XXX good value?
parameters.append("&Keywords=").append(ParserUtils.urlEncode(constraint.toString(), Charsets.UTF_8));
final HttpUrl.Builder url = stopFinderEndpoint.newBuilder().addPathSegments("SearchTripPoint/json");
appendCommonRequestParams(url);
url.addQueryParameter("MaxItems", "50"); // XXX good value?
url.addQueryParameter("Keywords", constraint.toString());
final StringBuilder uri = new StringBuilder(stopFinderEndpoint);
uri.append(parameters);
final CharSequence page = httpClient.get(HttpUrl.parse(uri.toString()));
final CharSequence page = httpClient.get(url.build());
try {
final List<SuggestedLocation> locations = new ArrayList<SuggestedLocation>();
final JSONObject head = new JSONObject(page.toString());
@ -227,11 +226,8 @@ public abstract class AbstractTsiProvider extends AbstractNetworkProvider {
}
}
private final StringBuilder buildCommonRequestParams(final String method, final String outputFormat) {
final StringBuilder uri = new StringBuilder(method);
uri.append('/').append(outputFormat);
uri.append("?Key=").append(apiKey);
return uri;
private final void appendCommonRequestParams(final HttpUrl.Builder url) {
url.addQueryParameter("Key", apiKey);
}
private Line createLine(final String id, final String mode, final String number, final String name,
@ -269,17 +265,15 @@ public abstract class AbstractTsiProvider extends AbstractNetworkProvider {
private NearbyLocationsResult jsonCoordRequest(final int lat, final int lon, final int maxDistance,
final int maxStations) throws IOException {
final StringBuilder parameters = buildCommonRequestParams("SearchTripPoint", "json");
parameters.append(String.format(Locale.FRENCH, "&Latitude=%2.6f&Longitude=%2.6f", latLonToDouble(lat),
latLonToDouble(lon)));
parameters.append("&MaxItems=").append(maxStations != 0 ? maxStations : 50);
parameters.append("&Perimeter=").append(maxDistance != 0 ? maxDistance : 1320);
parameters.append("&PointTypes=Stop_Place");
final HttpUrl.Builder url = stopFinderEndpoint.newBuilder().addPathSegments("SearchTripPoint/json");
appendCommonRequestParams(url);
url.addQueryParameter("Latitude", String.format(Locale.FRENCH, "%2.6f", latLonToDouble(lat)));
url.addQueryParameter("Longitude", String.format(Locale.FRENCH, "%2.6f", latLonToDouble(lon)));
url.addQueryParameter("MaxItems", Integer.toString(maxStations != 0 ? maxStations : 50));
url.addQueryParameter("Perimeter", Integer.toString(maxDistance != 0 ? maxDistance : 1320));
url.addQueryParameter("PointTypes", "Stop_Place");
final StringBuilder uri = new StringBuilder(stopFinderEndpoint);
uri.append(parameters);
final CharSequence page = httpClient.get(HttpUrl.parse(uri.toString()));
final CharSequence page = httpClient.get(url.build());
try {
final List<Location> stations = new ArrayList<Location>();
final JSONObject head = new JSONObject(page.toString());
@ -310,14 +304,12 @@ public abstract class AbstractTsiProvider extends AbstractNetworkProvider {
}
private Location jsonStationRequestCoord(final String id) throws IOException {
final StringBuilder parameters = buildCommonRequestParams("GetTripPoint", "json");
parameters.append("&TripPointId=").append(id);
parameters.append("&PointType=Stop_Place");
final HttpUrl.Builder url = stopFinderEndpoint.newBuilder().addPathSegments("GetTripPoint/json");
appendCommonRequestParams(url);
url.addQueryParameter("TripPointId", id);
url.addQueryParameter("PointType", "Stop_Place");
final StringBuilder uri = new StringBuilder(stopFinderEndpoint);
uri.append(parameters);
final CharSequence page = httpClient.get(HttpUrl.parse(uri.toString()));
final CharSequence page = httpClient.get(url.build());
try {
final JSONObject head = new JSONObject(page.toString());
@ -621,62 +613,59 @@ public abstract class AbstractTsiProvider extends AbstractNetworkProvider {
mode = null;
}
final String walkSpeedStr = translateWalkSpeed(context.walkSpeed);
final StringBuilder parameters = buildCommonRequestParams("PlanTrip", "json");
parameters.append("&Disruptions=").append(0); // XXX what does this even mean?
parameters.append("&Algorithm=FASTEST");
parameters.append("&MaxWalkDist=1000"); // XXX good value? (in meters)
final HttpUrl.Builder url = tripEndpoint.newBuilder().addPathSegments("PlanTrip/json");
appendCommonRequestParams(url);
url.addQueryParameter("Disruptions", "0"); // XXX what does this even mean?
url.addQueryParameter("Algorithm", "FASTEST");
url.addQueryParameter("MaxWalkDist", "1000"); // XXX good value? (in meters)
if (context.from.type == LocationType.STATION) {
parameters.append("&DepType=STOP_PLACE&DepId=").append(context.from.id);
parameters.append("%240"); // "$0"
url.addQueryParameter("DepType", "STOP_PLACE");
url.addQueryParameter("DepId", context.from.id + "$0");
} else if (context.from.type == LocationType.POI) {
parameters.append("&DepType=POI&DepId=").append(context.from.id);
parameters.append("%240"); // "$0"
url.addQueryParameter("DepType", "POI");
url.addQueryParameter("DepId", context.from.id + "$0");
} else {
parameters.append("&DepLat=").append(latLonToDouble(context.from.lat));
parameters.append("&DepLon=").append(latLonToDouble(context.from.lon));
url.addQueryParameter("DepLat", Double.toString(latLonToDouble(context.from.lat)));
url.addQueryParameter("DepLon", Double.toString(latLonToDouble(context.from.lon)));
}
if (context.to.type == LocationType.STATION) {
parameters.append("&ArrType=STOP_PLACE&ArrId=").append(context.to.id);
parameters.append("%240"); // "$0"
url.addQueryParameter("ArrType", "STOP_PLACE");
url.addQueryParameter("ArrId", context.to.id + "$0");
} else if (context.to.type == LocationType.POI) {
parameters.append("&ArrType=POI&ArrId=").append(context.to.id);
parameters.append("%240"); // "$0"
url.addQueryParameter("ArrType", "POI");
url.addQueryParameter("ArrId", context.to.id + "$0");
} else {
parameters.append("&ArrLat=").append(latLonToDouble(context.to.lat));
parameters.append("&ArrLon=").append(latLonToDouble(context.to.lon));
url.addQueryParameter("ArrLat", Double.toString(latLonToDouble(context.to.lat)));
url.addQueryParameter("ArrLon", Double.toString(latLonToDouble(context.to.lon)));
}
if (context.via != null) {
if (context.via.type == LocationType.STATION) {
parameters.append("&ViaType=STOP_PLACE&ViaId=").append(context.via.id);
parameters.append("%240"); // "$0"
url.addQueryParameter("ViaType", "STOP_PLACE");
url.addQueryParameter("ViaId", context.via.id + "$0");
} else if (context.via.type == LocationType.POI) {
parameters.append("&ViaType=POI&ViaId=").append(context.via.id);
parameters.append("%240"); // "$0"
url.addQueryParameter("ViaType", "POI");
url.addQueryParameter("ViaId", context.via.id + "$0");
} else {
parameters.append("&ViaLat=").append(latLonToDouble(context.via.lat));
parameters.append("&ViaLon=").append(latLonToDouble(context.via.lon));
url.addQueryParameter("ViaLat", Double.toString(latLonToDouble(context.via.lat)));
url.addQueryParameter("ViaLon", Double.toString(latLonToDouble(context.via.lon)));
}
}
final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
parameters.append("&date=").append(dateFormat.format(date));
url.addQueryParameter("date", dateFormat.format(date));
final DateFormat timeFormat = new SimpleDateFormat("HH-mm", Locale.US);
parameters.append(dep ? "&DepartureTime=" : "&ArrivalTime=").append(timeFormat.format(date));
url.addQueryParameter(dep ? "DepartureTime" : "ArrivalTime", timeFormat.format(date));
parameters.append("&WalkSpeed=").append(walkSpeedStr);
url.addQueryParameter("WalkSpeed", translateWalkSpeed(context.walkSpeed));
if (mode != null)
parameters.append("&Modes=").append(ParserUtils.urlEncode(mode.toString(), Charsets.UTF_8));
url.addQueryParameter("Modes", mode);
final StringBuilder uri = new StringBuilder(tripEndpoint);
uri.append(parameters);
final CharSequence page = httpClient.get(HttpUrl.parse(uri.toString()));
final CharSequence page = httpClient.get(url.build());
try {
final JSONObject head = new JSONObject(page.toString());
@ -711,7 +700,8 @@ public abstract class AbstractTsiProvider extends AbstractNetworkProvider {
context.updateLatestDeparture(trips.get(trips.size() - 1).getFirstDepartureTime());
}
return new QueryTripsResult(header, uri.toString(), context.from, context.via, context.to, context, trips);
return new QueryTripsResult(header, url.build().toString(), context.from, context.via, context.to, context,
trips);
} catch (final JSONException x) {
throw new ParserException(x);
}

View file

@ -17,12 +17,13 @@
package de.schildbach.pte;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class AtcProvider extends AbstractEfaProvider {
private final static String API_BASE = "http://82.187.83.50/TravelPlanner/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://82.187.83.50/TravelPlanner/");
// http://cisium.webhop.net/TravelPlanner/
public AtcProvider() {

View file

@ -30,11 +30,13 @@ import de.schildbach.pte.dto.Location;
import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.Style;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class AvvProvider extends AbstractEfaProvider {
private final static String API_BASE = "https://efa.avv-augsburg.de/avv2/";
private static final HttpUrl API_BASE = HttpUrl.parse("https://efa.avv-augsburg.de/avv2/");
public AvvProvider() {
super(NetworkId.AVV, API_BASE);
@ -44,21 +46,19 @@ public class AvvProvider extends AbstractEfaProvider {
}
@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,
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));
uri.append("&inclMOT_11=on"); // night bus
uri.append("&inclMOT_13=on");
uri.append("&inclMOT_14=on");
uri.append("&inclMOT_15=on");
uri.append("&inclMOT_16=on");
uri.append("&inclMOT_17=on");
return uri.toString();
protected void appendXsltTripRequestParameters(final HttpUrl.Builder url, final Location from,
final @Nullable Location via, final Location to, final Date time, final boolean dep,
final @Nullable Collection<Product> products, final @Nullable Optimize optimize,
final @Nullable WalkSpeed walkSpeed, final @Nullable Accessibility accessibility,
final @Nullable Set<Option> options) {
super.appendXsltTripRequestParameters(url, from, via, to, time, dep, products, optimize, walkSpeed,
accessibility, options);
url.addEncodedQueryParameter("inclMOT_11", "on"); // night bus
url.addEncodedQueryParameter("inclMOT_13", "on");
url.addEncodedQueryParameter("inclMOT_14", "on");
url.addEncodedQueryParameter("inclMOT_15", "on");
url.addEncodedQueryParameter("inclMOT_16", "on");
url.addEncodedQueryParameter("inclMOT_17", "on");
}
@Override

View file

@ -23,11 +23,13 @@ import java.util.regex.Pattern;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public final class BahnProvider extends AbstractHafasProvider {
private static final String API_BASE = "https://reiseauskunft.bahn.de/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("https://reiseauskunft.bahn.de/bin/");
private static final Product[] PRODUCTS_MAP = { Product.HIGH_SPEED_TRAIN, Product.HIGH_SPEED_TRAIN,
Product.REGIONAL_TRAIN, Product.REGIONAL_TRAIN, Product.SUBURBAN_TRAIN, Product.BUS, Product.FERRY,
Product.SUBWAY, Product.TRAM, Product.ON_DEMAND, null, null, null, null };
@ -35,7 +37,7 @@ public final class BahnProvider extends AbstractHafasProvider {
public BahnProvider() {
super(NetworkId.DB, API_BASE, "dn", PRODUCTS_MAP);
setStationBoardEndpoint("https://mobile.bahn.de/bin/mobil/bhftafel.exe/dn");
setStationBoardEndpoint(HttpUrl.parse("https://mobile.bahn.de/bin/mobil/bhftafel.exe"));
setStationBoardHasStationTable(false);
setJsonGetStopsUseWeight(false);
}

View file

@ -40,12 +40,13 @@ import de.schildbach.pte.dto.QueryTripsContext;
import de.schildbach.pte.dto.QueryTripsResult;
import de.schildbach.pte.dto.SuggestLocationsResult;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class BayernProvider extends AbstractEfaProvider {
private final static String API_BASE = "http://mobile.defas-fgi.de/beg/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://mobile.defas-fgi.de/beg/");
// http://mobile.defas-fgi.de/xml/
private static final String DEPARTURE_MONITOR_ENDPOINT = "XML_DM_REQUEST";
@ -135,29 +136,24 @@ public class BayernProvider extends AbstractEfaProvider {
}
@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,
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));
protected void appendXsltTripRequestParameters(final HttpUrl.Builder url, final Location from,
final @Nullable Location via, final Location to, final Date time, final boolean dep,
final @Nullable Collection<Product> products, final @Nullable Optimize optimize,
final @Nullable WalkSpeed walkSpeed, final @Nullable Accessibility accessibility,
final @Nullable Set<Option> options) {
super.appendXsltTripRequestParameters(url, from, via, to, time, dep, products, optimize, walkSpeed,
accessibility, options);
if (products != null) {
for (final Product p : products) {
if (p == Product.HIGH_SPEED_TRAIN)
uri.append("&inclMOT_15=on&inclMOT_16=on");
url.addEncodedQueryParameter("inclMOT_15", "on").addEncodedQueryParameter("inclMOT_16", "on");
if (p == Product.REGIONAL_TRAIN)
uri.append("&inclMOT_13=on");
url.addEncodedQueryParameter("inclMOT_13", "on");
}
}
uri.append("&inclMOT_11=on");
uri.append("&inclMOT_14=on");
uri.append("&calcOneDirection=1");
return uri.toString();
url.addEncodedQueryParameter("inclMOT_11", "on");
url.addEncodedQueryParameter("inclMOT_14", "on");
url.addEncodedQueryParameter("calcOneDirection", "1");
}
@Override

View file

@ -31,11 +31,13 @@ import de.schildbach.pte.dto.Location;
import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.Style;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class BsvagProvider extends AbstractEfaProvider {
private final static String API_BASE = "https://bsvg.efa.de/bsvagstd/";
private static final HttpUrl API_BASE = HttpUrl.parse("https://bsvg.efa.de/bsvagstd/");
public BsvagProvider() {
super(NetworkId.BSVAG, API_BASE);
@ -47,16 +49,14 @@ public class BsvagProvider extends AbstractEfaProvider {
}
@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,
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));
uri.append("&inclMOT_11=on");
return uri.toString();
protected void appendXsltTripRequestParameters(final HttpUrl.Builder url, final Location from,
final @Nullable Location via, final Location to, final Date time, final boolean dep,
final @Nullable Collection<Product> products, final @Nullable Optimize optimize,
final @Nullable WalkSpeed walkSpeed, final @Nullable Accessibility accessibility,
final @Nullable Set<Option> options) {
super.appendXsltTripRequestParameters(url, from, via, to, time, dep, products, optimize, walkSpeed,
accessibility, options);
url.addEncodedQueryParameter("inclMOT_11", "on");
}
private static final Map<String, Style> STYLES = new HashMap<String, Style>();

View file

@ -23,11 +23,13 @@ import de.schildbach.pte.dto.Location;
import de.schildbach.pte.dto.LocationType;
import de.schildbach.pte.dto.SuggestLocationsResult;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class BvbProvider extends AbstractEfaProvider {
private final static String API_BASE = "http://www.efa-bvb.ch/bvb/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://www.efa-bvb.ch/bvb/");
public BvbProvider() {
super(NetworkId.BVB, API_BASE);

View file

@ -31,19 +31,21 @@ import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.Style;
import de.schildbach.pte.dto.Style.Shape;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public final class BvgProvider extends AbstractHafasProvider {
private static final String API_BASE = "http://bvg-apps.hafas.de/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://bvg-apps.hafas.de/bin/");
private static final Product[] PRODUCTS_MAP = { Product.SUBURBAN_TRAIN, Product.SUBWAY, Product.TRAM, Product.BUS,
Product.FERRY, Product.HIGH_SPEED_TRAIN, Product.REGIONAL_TRAIN, Product.ON_DEMAND };
public BvgProvider() {
super(NetworkId.BVG, API_BASE, "dn", PRODUCTS_MAP);
setRequestUrlEncoding(Charsets.UTF_8);
setJsonGetStopsUseWeight(false);
setJsonGetStopsEncoding(Charsets.UTF_8);
setJsonNearbyLocationsEncoding(Charsets.UTF_8);
setStyles(STYLES);
}

View file

@ -17,11 +17,13 @@
package de.schildbach.pte;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class DingProvider extends AbstractEfaProvider {
private final static String API_BASE = "http://www.ding-ulm.de/ding2/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://www.ding-ulm.de/ding2/");
// http://www.ding.eu/swu

View file

@ -22,11 +22,13 @@ import java.util.regex.Matcher;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class DsbProvider extends AbstractHafasProvider {
private static final String API_BASE = "http://mobil.rejseplanen.dk/mobil-bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://mobil.rejseplanen.dk/mobil-bin/");
// http://dk.hafas.de/bin/fat/
// http://mobil.rejseplanen.dk/mobil-bin/
// http://www.dsb.dk/Rejseplan/bin/

View file

@ -17,11 +17,13 @@
package de.schildbach.pte;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class DubProvider extends AbstractEfaProvider {
private final static String API_BASE = "http://wojhati.rta.ae/dub/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://wojhati.rta.ae/dub/");
public DubProvider() {
super(NetworkId.DUB, API_BASE);

View file

@ -31,13 +31,15 @@ import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.QueryTripsContext;
import de.schildbach.pte.dto.QueryTripsResult;
import okhttp3.HttpUrl;
/**
* Ireland, Dublin
*
* @author Andreas Schildbach
*/
public class EireannProvider extends AbstractHafasProvider {
private static final String API_BASE = "http://journeyplanner.buseireann.ie/jp/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://journeyplanner.buseireann.ie/jp/bin/");
private static final Product[] PRODUCTS_MAP = { null, null, null, Product.BUS };
public EireannProvider() {

View file

@ -21,6 +21,8 @@ import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.Style;
import de.schildbach.pte.dto.Style.Shape;
import okhttp3.HttpUrl;
/**
* @author Nicolas Derive
* @author Stéphane Guillou
@ -29,7 +31,7 @@ public class FranceNorthEastProvider extends AbstractNavitiaProvider {
private static String API_REGION = "fr-ne";
// dataset available at: https://navitia.opendatasoft.com/explore/dataset/fr-ne/
public FranceNorthEastProvider(final String apiBase, final String authorization) {
public FranceNorthEastProvider(final HttpUrl apiBase, final String authorization) {
super(NetworkId.FRANCENORTHEAST, apiBase, authorization);
setTimeZone("Europe/Paris");

View file

@ -17,13 +17,15 @@
package de.schildbach.pte;
import okhttp3.HttpUrl;
/**
* @author Patrick Kanzler
*/
public class FranceNorthWestProvider extends AbstractNavitiaProvider {
private static String API_REGION = "fr-nw";
public FranceNorthWestProvider(final String apiBase, final String authorization) {
public FranceNorthWestProvider(final HttpUrl apiBase, final String authorization) {
super(NetworkId.FRANCENORTHWEST, apiBase, authorization);
setTimeZone("Europe/Paris");

View file

@ -21,13 +21,15 @@ import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.Style;
import de.schildbach.pte.dto.Style.Shape;
import okhttp3.HttpUrl;
/**
* @author Anthony Chaput
*/
public class FranceSouthEastProvider extends AbstractNavitiaProvider {
private static String API_REGION = "fr-se";
public FranceSouthEastProvider(final String apiBase, final String authorization) {
public FranceSouthEastProvider(final HttpUrl apiBase, final String authorization) {
super(NetworkId.FRANCESOUTHEAST, apiBase, authorization);
setTimeZone("Europe/Paris");

View file

@ -21,13 +21,15 @@ import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.Style;
import de.schildbach.pte.dto.Style.Shape;
import okhttp3.HttpUrl;
/**
* @author Nicolas Derive
*/
public class FranceSouthWestProvider extends AbstractNavitiaProvider {
private static String API_REGION = "fr-sw";
public FranceSouthWestProvider(final String apiBase, final String authorization) {
public FranceSouthWestProvider(final HttpUrl apiBase, final String authorization) {
super(NetworkId.FRANCESOUTHWEST, apiBase, authorization);
setTimeZone("Europe/Paris");

View file

@ -26,12 +26,13 @@ import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.Style;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class GvhProvider extends AbstractEfaProvider {
private static final String API_BASE = "http://bhb.efa.de/bhb/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://bhb.efa.de/bhb/");
// http://www.efa.de/efaws2/cmsembedded_gvh/
// http://bhb.efa.de/bhb/
// http://mobil.efa.de/mobile3/
@ -40,7 +41,7 @@ public class GvhProvider extends AbstractEfaProvider {
this(API_BASE);
}
public GvhProvider(final String apiBase) {
public GvhProvider(final HttpUrl apiBase) {
super(NetworkId.GVH, apiBase);
setIncludeRegionId(false);

View file

@ -18,7 +18,6 @@
package de.schildbach.pte;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@ -70,7 +69,7 @@ import okhttp3.ResponseBody;
* @author Mats Sjöberg <mats@sjoberg.fi>
*/
public class HslProvider extends AbstractNetworkProvider {
private static final String API_BASE = "http://api.reittiopas.fi/hsl/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://api.reittiopas.fi/hsl/");
private static final String SERVER_PRODUCT = "hsl";
private static final String SERVER_VERSION = "1_2_0";
private static final int EARLIER_TRIPS_MINUTE_OFFSET = 5;
@ -100,16 +99,16 @@ public class HslProvider extends AbstractNetworkProvider {
return true;
}
private StringBuilder apiUri(final String request) {
StringBuilder uri = new StringBuilder(API_BASE);
uri.append(SERVER_VERSION + "/");
uri.append("?user=" + user);
uri.append("&pass=" + pass);
uri.append("&request=").append(request);
uri.append("&epsg_out=wgs84");
uri.append("&epsg_in=wgs84");
uri.append("&format=xml");
return uri;
private HttpUrl.Builder apiUrl(final String request) {
final HttpUrl.Builder url = API_BASE.newBuilder();
url.addPathSegment(SERVER_VERSION);
url.addQueryParameter("user", user);
url.addQueryParameter("pass", pass);
url.addQueryParameter("request", request);
url.addQueryParameter("epsg_out", "wgs84");
url.addQueryParameter("epsg_in", "wgs84");
url.addQueryParameter("format", "xml");
return url;
}
private Point coordStrToPoint(final String coordStr) {
@ -139,9 +138,9 @@ public class HslProvider extends AbstractNetworkProvider {
}
private Location queryStop(final String stationId) throws IOException {
final StringBuilder uri = apiUri("stop");
uri.append("&code=").append(stationId);
uri.append(String.format("&dep_limit=1"));
final HttpUrl.Builder url = apiUrl("stop");
url.addQueryParameter("code", stationId);
url.addQueryParameter("dep_limit", "1");
final AtomicReference<Location> result = new AtomicReference<Location>();
final HttpClient.Callback callback = new HttpClient.Callback() {
@ -164,7 +163,7 @@ public class HslProvider extends AbstractNetworkProvider {
}
};
httpClient.getInputStream(callback, HttpUrl.parse(uri.toString()));
httpClient.getInputStream(callback, url.build());
return result.get();
}
@ -174,7 +173,7 @@ public class HslProvider extends AbstractNetworkProvider {
@Override
public NearbyLocationsResult queryNearbyLocations(EnumSet<LocationType> types, Location location, int maxDistance,
int maxStations) throws IOException {
final StringBuilder uri = apiUri("stops_area");
final HttpUrl.Builder url = apiUrl("stops_area");
if (!location.hasLocation()) {
if (location.type != LocationType.STATION)
throw new IllegalArgumentException("cannot handle: " + location.type);
@ -182,9 +181,9 @@ public class HslProvider extends AbstractNetworkProvider {
throw new IllegalArgumentException("at least one of stationId or lat/lon " + "must be given");
location = queryStop(location.id);
}
uri.append("&center_coordinate=").append(locationToCoords(location));
uri.append(String.format("&limit=%d", maxStations));
uri.append(String.format("&diameter=%d", maxDistance * 2));
url.addQueryParameter("center_coordinate", locationToCoords(location));
url.addQueryParameter("limit", Integer.toString(maxStations));
url.addQueryParameter("diameter", Integer.toString(maxDistance * 2));
final AtomicReference<NearbyLocationsResult> result = new AtomicReference<NearbyLocationsResult>();
final HttpClient.Callback callback = new HttpClient.Callback() {
@ -219,7 +218,7 @@ public class HslProvider extends AbstractNetworkProvider {
}
};
httpClient.getInputStream(callback, HttpUrl.parse(uri.toString()));
httpClient.getInputStream(callback, url.build());
return result.get();
}
@ -256,13 +255,13 @@ public class HslProvider extends AbstractNetworkProvider {
@Override
public QueryDeparturesResult queryDepartures(String stationId, @Nullable Date queryDate, final int maxDepartures,
boolean equivs) throws IOException {
final StringBuilder uri = apiUri("stop");
uri.append("&code=").append(stationId);
final HttpUrl.Builder url = apiUrl("stop");
url.addQueryParameter("code", stationId);
if (queryDate != null) {
uri.append("&date=").append(new SimpleDateFormat("yyyyMMdd").format(queryDate));
uri.append("&time=").append(new SimpleDateFormat("HHmm").format(queryDate));
url.addQueryParameter("date", new SimpleDateFormat("yyyyMMdd").format(queryDate));
url.addQueryParameter("time", new SimpleDateFormat("HHmm").format(queryDate));
}
uri.append(String.format("&dep_limit=%d", maxDepartures));
url.addQueryParameter("dep_limit", Integer.toString(maxDepartures));
final AtomicReference<QueryDeparturesResult> result = new AtomicReference<QueryDeparturesResult>();
final HttpClient.Callback callback = new HttpClient.Callback() {
@ -321,7 +320,7 @@ public class HslProvider extends AbstractNetworkProvider {
}
};
httpClient.getInputStream(callback, HttpUrl.parse(uri.toString()));
httpClient.getInputStream(callback, url.build());
return result.get();
}
@ -335,13 +334,13 @@ public class HslProvider extends AbstractNetworkProvider {
*/
@Override
public SuggestLocationsResult suggestLocations(CharSequence constraint) throws IOException {
final StringBuilder uri = apiUri("geocode");
final HttpUrl.Builder url = apiUrl("geocode");
// Since HSL is picky about the input we clean out any
// character that isn't alphabetic, numeral, -, ', /
// or a space. Those should be all chars needed for a
// name.
String constraintStr = constraint.toString().replaceAll("[^\\p{Ll}\\p{Lu}\\p{Lt}\\p{Lo}\\p{Nd}\\d-'/ ]", "");
uri.append("&key=").append(URLEncoder.encode(constraintStr, "utf-8"));
url.addQueryParameter("key", constraintStr);
final AtomicReference<SuggestLocationsResult> result = new AtomicReference<SuggestLocationsResult>();
final HttpClient.Callback callback = new HttpClient.Callback() {
@ -396,7 +395,7 @@ public class HslProvider extends AbstractNetworkProvider {
}
};
httpClient.getInputStream(callback, HttpUrl.parse(uri.toString()));
httpClient.getInputStream(callback, url.build());
return result.get();
}
@ -467,18 +466,18 @@ public class HslProvider extends AbstractNetworkProvider {
to = locations.get(0);
}
final StringBuilder uri = apiUri("route");
final HttpUrl.Builder url = apiUrl("route");
uri.append("&from=").append(locationToCoords(from));
url.addQueryParameter("from", locationToCoords(from));
if (via != null)
uri.append("&via=").append(locationToCoords(via));
uri.append("&to=").append(locationToCoords(to));
url.addQueryParameter("via", locationToCoords(via));
url.addQueryParameter("to", locationToCoords(to));
uri.append("&timetype=").append(dep ? "departure" : "arrival");
url.addQueryParameter("timetype", dep ? "departure" : "arrival");
if (walkSpeed != WalkSpeed.NORMAL)
uri.append(String.format("&walk_speed=%d", walkSpeed == WalkSpeed.SLOW ? 30 : 100));
uri.append("&show=5");
url.addQueryParameter("walk_speed", Integer.toString(walkSpeed == WalkSpeed.SLOW ? 30 : 100));
url.addQueryParameter("show", "5");
if (products != null && products.size() > 0) {
List<String> tt = new ArrayList<String>();
@ -495,10 +494,10 @@ public class HslProvider extends AbstractNetworkProvider {
tt.add("ferry");
if (tt.size() > 0)
uri.append("&transport_types=").append(Joiner.on("|").join(tt));
url.addQueryParameter("transport_types", Joiner.on("|").join(tt));
}
QueryTripsHslContext context = new QueryTripsHslContext(uri.toString(), from, via, to, date);
QueryTripsHslContext context = new QueryTripsHslContext(url.build().toString(), from, via, to, date);
return queryHslTrips(from, via, to, context, date, true);
}
@ -548,9 +547,9 @@ public class HslProvider extends AbstractNetworkProvider {
private QueryTripsResult queryHslTrips(final Location from, final Location via, final Location to,
final QueryTripsHslContext context, Date date, final boolean later) throws IOException {
final StringBuilder uri = new StringBuilder(context.uri);
uri.append("&date=").append(new SimpleDateFormat("yyyyMMdd").format(date));
uri.append("&time=").append(new SimpleDateFormat("HHmm").format(date));
final HttpUrl.Builder url = HttpUrl.parse(context.uri).newBuilder();
url.addQueryParameter("date", new SimpleDateFormat("yyyyMMdd").format(date));
url.addQueryParameter("time", new SimpleDateFormat("HHmm").format(date));
final AtomicReference<QueryTripsResult> result = new AtomicReference<QueryTripsResult>();
final HttpClient.Callback callback = new HttpClient.Callback() {
@ -697,7 +696,7 @@ public class HslProvider extends AbstractNetworkProvider {
context.prevDate = firstDate;
context.trips = trips;
result.set(new QueryTripsResult(header, uri.toString(), from, via, to, context, trips));
result.set(new QueryTripsResult(header, url.build().toString(), from, via, to, context, trips));
} catch (final XmlPullParserException x) {
throw new ParserException("cannot parse xml: " + bodyPeek, x);
}
@ -706,7 +705,7 @@ public class HslProvider extends AbstractNetworkProvider {
context.date = date;
httpClient.getInputStream(callback, HttpUrl.parse(uri.toString()));
httpClient.getInputStream(callback, url.build());
return result.get();
}
}

View file

@ -60,7 +60,7 @@ import okhttp3.HttpUrl;
* @author Andreas Schildbach
*/
public class InvgProvider extends AbstractHafasProvider {
private static final String API_BASE = "http://fpa.invg.de/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://fpa.invg.de/bin/");
// http://invg.hafas.de/bin/
private static final Product[] PRODUCTS_MAP = { null, null, null, null, null, null, null, null, null, null };
private static final long PARSER_DAY_ROLLOVER_THRESHOLD_MS = 12 * 60 * 60 * 1000;
@ -68,11 +68,11 @@ public class InvgProvider extends AbstractHafasProvider {
public InvgProvider() {
super(NetworkId.INVG, API_BASE, "dn", PRODUCTS_MAP);
setRequestUrlEncoding(Charsets.UTF_8);
setStationBoardCanDoEquivs(false);
setJsonGetStopsEncoding(Charsets.UTF_8);
setJsonNearbyLocationsEncoding(Charsets.UTF_8);
setStyles(STYLES);
setExtXmlEndpoint(API_BASE + "extxml.exe");
setExtXmlEndpoint(API_BASE.newBuilder().addPathSegment("extxml.exe").build());
}
@Override
@ -120,12 +120,11 @@ public class InvgProvider extends AbstractHafasProvider {
public NearbyLocationsResult queryNearbyLocations(final EnumSet<LocationType> types, final Location location,
final int maxDistance, final int maxStations) throws IOException {
if (location.type == LocationType.STATION && location.hasId()) {
final StringBuilder uri = new StringBuilder(stationBoardEndpoint);
uri.append("?near=Anzeigen");
uri.append("&distance=").append(maxDistance != 0 ? maxDistance / 1000 : 50);
uri.append("&input=").append(normalizeStationId(location.id));
return htmlNearbyStations(uri.toString());
final HttpUrl.Builder url = stationBoardEndpoint.newBuilder().addPathSegment(apiLanguage);
url.addQueryParameter("near", "Anzeigen");
url.addQueryParameter("distance", Integer.toString(maxDistance != 0 ? maxDistance / 1000 : 50));
url.addQueryParameter("input", normalizeStationId(location.id));
return htmlNearbyStations(url.build());
} else {
throw new IllegalArgumentException("cannot handle: " + location);
}
@ -171,9 +170,9 @@ public class InvgProvider extends AbstractHafasProvider {
final QueryDeparturesResult result = new QueryDeparturesResult(header);
// scrape page
final StringBuilder uri = new StringBuilder(stationBoardEndpoint);
appendXmlStationBoardParameters(uri, time, stationId, maxDepartures, false, null);
final CharSequence page = httpClient.get(HttpUrl.parse(uri.toString()));
final HttpUrl.Builder url = stationBoardEndpoint.newBuilder().addPathSegment(apiLanguage);
appendXmlStationBoardParameters(url, time, stationId, maxDepartures, false, null);
final CharSequence page = httpClient.get(url.build());
// parse page
final Matcher mHeadCoarse = P_DEPARTURES_HEAD_COARSE.matcher(page);

View file

@ -19,13 +19,15 @@ package de.schildbach.pte;
import de.schildbach.pte.util.WordUtils;
import okhttp3.HttpUrl;
/**
* @author Antonio El Khoury
*/
public class ItalyProvider extends AbstractNavitiaProvider {
private static String API_REGION = "it";
public ItalyProvider(final String apiBase, final String authorization) {
public ItalyProvider(final HttpUrl apiBase, final String authorization) {
super(NetworkId.IT, apiBase, authorization);
setTimeZone("Europe/Rome");

View file

@ -17,11 +17,13 @@
package de.schildbach.pte;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class IvbProvider extends AbstractEfaProvider {
private final static String API_BASE = "http://efa.ivb.at/ivb/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://efa.ivb.at/ivb/");
public IvbProvider() {
super(NetworkId.IVB, API_BASE);

View file

@ -28,17 +28,19 @@ import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Style;
import de.schildbach.pte.dto.Style.Shape;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class KvvProvider extends AbstractEfaProvider {
private final static String API_BASE = "http://213.144.24.66/kvv2/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://213.144.24.66/kvv2/");
public KvvProvider() {
this(API_BASE);
}
public KvvProvider(final String apiBase) {
public KvvProvider(final HttpUrl apiBase) {
super(NetworkId.KVV, apiBase);
setStyles(STYLES);

View file

@ -22,12 +22,13 @@ import java.util.Map;
import de.schildbach.pte.dto.Style;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class LinzProvider extends AbstractEfaProvider {
public static final String API_BASE = "https://www.linzag.at/linz2/";
private static final HttpUrl API_BASE = HttpUrl.parse("https://www.linzag.at/linz2/");
// http://www.linzag.at/static/
public LinzProvider() {

View file

@ -23,11 +23,13 @@ import com.google.common.base.Charsets;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class LuProvider extends AbstractHafasProvider {
private static final String API_BASE = "http://mobiliteitszentral.hafas.de/hafas/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://mobiliteitszentral.hafas.de/hafas/");
private static final Product[] PRODUCTS_MAP = { Product.HIGH_SPEED_TRAIN, Product.HIGH_SPEED_TRAIN,
Product.HIGH_SPEED_TRAIN, Product.REGIONAL_TRAIN, Product.REGIONAL_TRAIN, Product.BUS, Product.BUS,
Product.BUS, Product.BUS };
@ -35,7 +37,7 @@ public class LuProvider extends AbstractHafasProvider {
public LuProvider() {
super(NetworkId.LU, API_BASE, "fn", PRODUCTS_MAP);
setJsonGetStopsEncoding(Charsets.UTF_8);
setRequestUrlEncoding(Charsets.UTF_8);
setJsonNearbyLocationsEncoding(Charsets.UTF_8);
}

View file

@ -29,11 +29,13 @@ import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Position;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class MerseyProvider extends AbstractEfaProvider {
private final static String API_BASE = "http://jp.merseytravel.gov.uk/nwm/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://jp.merseytravel.gov.uk/nwm/");
public MerseyProvider() {
super(NetworkId.MERSEY, API_BASE);

View file

@ -28,13 +28,15 @@ import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.Style;
import okhttp3.HttpUrl;
/**
* Has been renamed to PTV (Public Transport Vicoria).
*
* @author Andreas Schildbach
*/
public class MetProvider extends AbstractEfaProvider {
private final static String API_BASE = "http://jp.ptv.vic.gov.au/ptv/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://jp.ptv.vic.gov.au/ptv/");
public MetProvider() {
super(NetworkId.MET, API_BASE);

View file

@ -19,11 +19,13 @@ package de.schildbach.pte;
import de.schildbach.pte.dto.Position;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class MvgProvider extends AbstractEfaProvider {
private static final String API_BASE = "http://mobil.mvg-online.de/mvgMobil/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://mobil.mvg-online.de/mvgMobil/");
public MvgProvider() {
super(NetworkId.MVG, API_BASE);

View file

@ -30,17 +30,19 @@ import de.schildbach.pte.dto.Position;
import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.Style;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class MvvProvider extends AbstractEfaProvider {
private static final String API_BASE = "http://efa.mvv-muenchen.de/mobile/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://efa.mvv-muenchen.de/mobile/");
public MvvProvider() {
this(API_BASE);
}
public MvvProvider(final String apiBase) {
public MvvProvider(final HttpUrl apiBase) {
super(NetworkId.MVV, apiBase);
setIncludeRegionId(false);

View file

@ -29,11 +29,13 @@ import de.schildbach.pte.dto.NearbyLocationsResult;
import de.schildbach.pte.dto.Product;
import de.schildbach.pte.util.StringReplaceReader;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class NasaProvider extends AbstractHafasProvider {
private static final String API_BASE = "http://reiseauskunft.insa.de/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://reiseauskunft.insa.de/bin/");
private static final Product[] PRODUCTS_MAP = { Product.HIGH_SPEED_TRAIN, Product.HIGH_SPEED_TRAIN,
Product.REGIONAL_TRAIN, Product.REGIONAL_TRAIN, Product.SUBURBAN_TRAIN, Product.TRAM, Product.BUS,
Product.ON_DEMAND };
@ -41,7 +43,7 @@ public class NasaProvider extends AbstractHafasProvider {
public NasaProvider() {
super(NetworkId.NASA, API_BASE, "dn", PRODUCTS_MAP);
setJsonGetStopsEncoding(Charsets.UTF_8);
setRequestUrlEncoding(Charsets.UTF_8);
setJsonNearbyLocationsEncoding(Charsets.UTF_8);
setStationBoardHasLocation(true);
}
@ -79,12 +81,11 @@ public class NasaProvider extends AbstractHafasProvider {
if (location.hasLocation()) {
return nearbyLocationsByCoordinate(types, location.lat, location.lon, maxDistance, maxLocations);
} else if (location.type == LocationType.STATION && location.hasId()) {
final StringBuilder uri = new StringBuilder(stationBoardEndpoint);
uri.append("?near=Anzeigen");
uri.append("&distance=").append(maxDistance != 0 ? maxDistance / 1000 : 50);
uri.append("&input=").append(normalizeStationId(location.id));
return htmlNearbyStations(uri.toString());
final HttpUrl.Builder url = stationBoardEndpoint.newBuilder().addPathSegment(apiLanguage);
url.addQueryParameter("near", "Anzeigen");
url.addQueryParameter("distance", Integer.toString(maxDistance != 0 ? maxDistance / 1000 : 50));
url.addQueryParameter("input", normalizeStationId(location.id));
return htmlNearbyStations(url.build());
} else {
throw new IllegalArgumentException("cannot handle: " + location);
}

View file

@ -30,18 +30,20 @@ import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.QueryTripsContext;
import de.schildbach.pte.dto.QueryTripsResult;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class NriProvider extends AbstractHafasProvider {
private static final String API_BASE = "http://hafas.websrv05.reiseinfo.no/bin/dev/nri/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://hafas.websrv05.reiseinfo.no/bin/dev/nri/");
private static final Product[] PRODUCTS_MAP = { Product.HIGH_SPEED_TRAIN, Product.REGIONAL_TRAIN, Product.BUS,
Product.TRAM, Product.SUBWAY, Product.FERRY, Product.FERRY, Product.FERRY };
public NriProvider() {
super(NetworkId.NRI, API_BASE, "on", PRODUCTS_MAP);
setJsonGetStopsEncoding(Charsets.UTF_8);
setRequestUrlEncoding(Charsets.UTF_8);
}
private static final String[] PLACES = { "Oslo", "Bergen" };

View file

@ -27,11 +27,13 @@ import de.schildbach.pte.dto.LocationType;
import de.schildbach.pte.dto.NearbyLocationsResult;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class NsProvider extends AbstractHafasProvider {
private static final String API_BASE = "http://hafas.bene-system.com/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://hafas.bene-system.com/bin/");
private static final Product[] PRODUCTS_MAP = { Product.HIGH_SPEED_TRAIN, Product.HIGH_SPEED_TRAIN,
Product.HIGH_SPEED_TRAIN, Product.REGIONAL_TRAIN, Product.SUBURBAN_TRAIN, Product.BUS, Product.FERRY,
Product.SUBWAY, Product.TRAM, Product.ON_DEMAND };
@ -49,13 +51,12 @@ public class NsProvider extends AbstractHafasProvider {
public NearbyLocationsResult queryNearbyLocations(final EnumSet<LocationType> types, final Location location,
final int maxDistance, final int maxLocations) throws IOException {
if (location.type == LocationType.STATION && location.hasId()) {
final StringBuilder uri = new StringBuilder(stationBoardEndpoint);
uri.append("?near=Anzeigen");
uri.append("&distance=").append(maxDistance != 0 ? maxDistance / 1000 : 50);
uri.append("&input=").append(normalizeStationId(location.id));
uri.append("&L=profi");
return htmlNearbyStations(uri.toString());
final HttpUrl.Builder url = stationBoardEndpoint.newBuilder().addPathSegment(apiLanguage);
url.addQueryParameter("near", "Anzeigen");
url.addQueryParameter("distance", Integer.toString(maxDistance != 0 ? maxDistance / 1000 : 50));
url.addQueryParameter("input", normalizeStationId(location.id));
url.addQueryParameter("L", "profi");
return htmlNearbyStations(url.build());
} else {
throw new IllegalArgumentException("cannot handle: " + location);
}

View file

@ -31,18 +31,22 @@ import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.QueryTripsContext;
import de.schildbach.pte.dto.QueryTripsResult;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class NvbwProvider extends AbstractEfaProvider {
private final static String API_BASE = "http://www.efa-bw.de/nvbw/"; // no intermeditate stops
private final static String API_BASE_MOBILE = "http://www.efa-bw.de/android/";
// no intermeditate stops
private final static HttpUrl API_BASE = HttpUrl.parse("http://www.efa-bw.de/nvbw/");
private final static HttpUrl API_BASE_MOBILE = HttpUrl.parse("http://www.efa-bw.de/android/");
// http://efa2.naldo.de/naldo/
public NvbwProvider() {
super(NetworkId.NVBW, API_BASE + DEFAULT_DEPARTURE_MONITOR_ENDPOINT, API_BASE_MOBILE + DEFAULT_TRIP_ENDPOINT,
API_BASE + DEFAULT_STOPFINDER_ENDPOINT, API_BASE + DEFAULT_COORD_ENDPOINT);
super(NetworkId.NVBW, API_BASE.newBuilder().addPathSegment(DEFAULT_DEPARTURE_MONITOR_ENDPOINT).build(),
API_BASE_MOBILE.newBuilder().addPathSegment(DEFAULT_TRIP_ENDPOINT).build(),
API_BASE.newBuilder().addPathSegment(DEFAULT_STOPFINDER_ENDPOINT).build(),
API_BASE.newBuilder().addPathSegment(DEFAULT_COORD_ENDPOINT).build());
setIncludeRegionId(false);
setUseRouteIndexAsTripId(false);

View file

@ -29,11 +29,13 @@ import de.schildbach.pte.dto.NearbyLocationsResult;
import de.schildbach.pte.dto.Product;
import de.schildbach.pte.util.StringReplaceReader;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class NvvProvider extends AbstractHafasProvider {
private static final String API_BASE = "https://auskunft.nvv.de/auskunft/bin/jp/";
private static final HttpUrl API_BASE = HttpUrl.parse("https://auskunft.nvv.de/auskunft/bin/jp/");
private static final Product[] PRODUCTS_MAP = { Product.HIGH_SPEED_TRAIN, Product.HIGH_SPEED_TRAIN,
Product.REGIONAL_TRAIN, Product.SUBURBAN_TRAIN, Product.SUBWAY, Product.TRAM, Product.BUS, Product.BUS,
Product.FERRY, Product.ON_DEMAND, Product.REGIONAL_TRAIN, Product.REGIONAL_TRAIN };
@ -41,7 +43,7 @@ public class NvvProvider extends AbstractHafasProvider {
public NvvProvider() {
super(NetworkId.NVV, API_BASE, "dn", PRODUCTS_MAP);
setJsonGetStopsEncoding(Charsets.UTF_8);
setRequestUrlEncoding(Charsets.UTF_8);
setJsonNearbyLocationsEncoding(Charsets.UTF_8);
httpClient.setSslAcceptAllHostnames(true);
}
@ -83,12 +85,12 @@ public class NvvProvider extends AbstractHafasProvider {
if (location.hasLocation()) {
return nearbyLocationsByCoordinate(types, location.lat, location.lon, maxDistance, maxLocations);
} else if (location.type == LocationType.STATION && location.hasId()) {
final StringBuilder uri = new StringBuilder(stationBoardEndpoint);
uri.append("?L=vs_rmv&near=Anzeigen");
uri.append("&distance=").append(maxDistance != 0 ? maxDistance / 1000 : 50);
uri.append("&input=").append(normalizeStationId(location.id));
return htmlNearbyStations(uri.toString());
final HttpUrl.Builder url = stationBoardEndpoint.newBuilder().addPathSegment(apiLanguage);
url.addQueryParameter("near", "Anzeigen");
url.addQueryParameter("distance", Integer.toString(maxDistance != 0 ? maxDistance / 1000 : 50));
url.addQueryParameter("input", normalizeStationId(location.id));
url.addQueryParameter("L", "vs_rmv");
return htmlNearbyStations(url.build());
} else {
throw new IllegalArgumentException("cannot handle: " + location);
}

View file

@ -27,11 +27,13 @@ import de.schildbach.pte.dto.LocationType;
import de.schildbach.pte.dto.NearbyLocationsResult;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class OebbProvider extends AbstractHafasProvider {
private static final String API_BASE = "http://fahrplan.oebb.at/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://fahrplan.oebb.at/bin/");
private static final Product[] PRODUCTS_MAP = { Product.HIGH_SPEED_TRAIN, Product.HIGH_SPEED_TRAIN,
Product.HIGH_SPEED_TRAIN, Product.REGIONAL_TRAIN, Product.REGIONAL_TRAIN, Product.SUBURBAN_TRAIN,
Product.BUS, Product.FERRY, Product.SUBWAY, Product.TRAM, Product.HIGH_SPEED_TRAIN, Product.ON_DEMAND,
@ -49,12 +51,11 @@ public class OebbProvider extends AbstractHafasProvider {
if (location.hasLocation()) {
return nearbyLocationsByCoordinate(types, location.lat, location.lon, maxDistance, maxLocations);
} else if (location.type == LocationType.STATION && location.hasId()) {
final StringBuilder uri = new StringBuilder(stationBoardEndpoint);
uri.append("?near=Suchen");
uri.append("&distance=").append(maxDistance != 0 ? maxDistance / 1000 : 50);
uri.append("&input=").append(normalizeStationId(location.id));
return htmlNearbyStations(uri.toString());
final HttpUrl.Builder url = stationBoardEndpoint.newBuilder().addPathSegment(apiLanguage);
url.addQueryParameter("near", "Suchen");
url.addQueryParameter("distance", Integer.toString(maxDistance != 0 ? maxDistance / 1000 : 50));
url.addQueryParameter("input", normalizeStationId(location.id));
return htmlNearbyStations(url.build());
} else {
throw new IllegalArgumentException("cannot handle: " + location);
}

View file

@ -17,13 +17,15 @@
package de.schildbach.pte;
import okhttp3.HttpUrl;
/**
* @author Stephane Berube
*/
public class OntarioProvider extends AbstractNavitiaProvider {
private static String API_REGION = "ca-on";
public OntarioProvider(final String apiBase, final String authorization) {
public OntarioProvider(final HttpUrl apiBase, final String authorization) {
super(NetworkId.ONTARIO, apiBase, authorization);
setTimeZone("America/Toronto");

View file

@ -37,11 +37,13 @@ import de.schildbach.pte.dto.QueryTripsContext;
import de.schildbach.pte.dto.QueryTripsResult;
import de.schildbach.pte.dto.SuggestLocationsResult;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class OoevvProvider extends AbstractHafasProvider {
private static final String API_BASE = "https://verkehrsauskunft.ooevv.at/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("https://verkehrsauskunft.ooevv.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 };

View file

@ -19,12 +19,14 @@ package de.schildbach.pte;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Kjell Braden <afflux@pentabarf.de>
*/
public class PacaProvider extends AbstractTsiProvider {
public PacaProvider() {
super(NetworkId.PACA, "PACA", "http://www.pacamobilite.fr/WebServices/TransinfoService/api");
super(NetworkId.PACA, "PACA", HttpUrl.parse("http://www.pacamobilite.fr/WebServices/TransinfoService/api"));
}
@Override

View file

@ -22,13 +22,15 @@ import de.schildbach.pte.dto.Style;
import de.schildbach.pte.dto.Style.Shape;
import de.schildbach.pte.util.WordUtils;
import okhttp3.HttpUrl;
/**
* @author Antonio El Khoury
*/
public class ParisProvider extends AbstractNavitiaProvider {
private static String API_REGION = "fr-idf";
public ParisProvider(final String apiBase, final String authorization) {
public ParisProvider(final HttpUrl apiBase, final String authorization) {
super(NetworkId.PARIS, apiBase, authorization);
setTimeZone("Europe/Paris");

View file

@ -24,18 +24,20 @@ import com.google.common.base.Charsets;
import de.schildbach.pte.dto.Product;
import de.schildbach.pte.util.StringReplaceReader;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class PlProvider extends AbstractHafasProvider {
private static final String API_BASE = "http://rozklad.bilkom.pl/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://rozklad.bilkom.pl/bin/");
private static final Product[] PRODUCTS_MAP = { Product.HIGH_SPEED_TRAIN, Product.HIGH_SPEED_TRAIN,
Product.REGIONAL_TRAIN, Product.SUBURBAN_TRAIN, Product.BUS, Product.BUS, Product.FERRY };
public PlProvider() {
super(NetworkId.PL, API_BASE, "pn", PRODUCTS_MAP);
setJsonGetStopsEncoding(Charsets.UTF_8);
setRequestUrlEncoding(Charsets.UTF_8);
setJsonNearbyLocationsEncoding(Charsets.UTF_8);
}

View file

@ -17,13 +17,15 @@
package de.schildbach.pte;
import okhttp3.HttpUrl;
/**
* @author Stephane Berube
*/
public class QuebecProvider extends AbstractNavitiaProvider {
private static String API_REGION = "ca-qc";
public QuebecProvider(final String apiBase, final String authorization) {
public QuebecProvider(final HttpUrl apiBase, final String authorization) {
super(NetworkId.QUEBEC, apiBase, authorization);
setTimeZone("America/Montreal");

View file

@ -22,11 +22,13 @@ import java.util.regex.Pattern;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class RtProvider extends AbstractHafasProvider {
private static final String API_BASE = "http://railteam.hafas.de/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://railteam.hafas.de/bin/");
private static final Product[] PRODUCTS_MAP = { Product.HIGH_SPEED_TRAIN, Product.HIGH_SPEED_TRAIN,
Product.HIGH_SPEED_TRAIN, Product.REGIONAL_TRAIN, Product.SUBURBAN_TRAIN, Product.BUS, Product.FERRY,
Product.SUBWAY, Product.TRAM, Product.ON_DEMAND };

View file

@ -22,12 +22,14 @@ import javax.annotation.Nullable;
import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class RtaChicagoProvider extends AbstractEfaProvider {
private final static String API_BASE = "http://tripplanner.rtachicago.com/ccg3/";
// "http://elb-jpinstances-1463028547.us-east-1.elb.amazonaws.com/ccg3/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://tripplanner.rtachicago.com/ccg3/");
// http://elb-jpinstances-1463028547.us-east-1.elb.amazonaws.com/ccg3/
public RtaChicagoProvider() {
super(NetworkId.RTACHICAGO, API_BASE);

View file

@ -22,11 +22,13 @@ import java.util.regex.Matcher;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class SbbProvider extends AbstractHafasProvider {
private static final String API_BASE = "http://fahrplan.sbb.ch/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://fahrplan.sbb.ch/bin/");
private static final Product[] PRODUCTS_MAP = { Product.HIGH_SPEED_TRAIN, Product.HIGH_SPEED_TRAIN,
Product.HIGH_SPEED_TRAIN, Product.REGIONAL_TRAIN, Product.FERRY, Product.SUBURBAN_TRAIN, Product.BUS,
Product.CABLECAR, Product.REGIONAL_TRAIN, Product.TRAM };

View file

@ -26,11 +26,13 @@ import com.google.common.base.Charsets;
import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class SeProvider extends AbstractHafasProvider {
private static final String API_BASE = "https://reseplanerare.resrobot.se/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("https://reseplanerare.resrobot.se/bin/");
// http://samtrafiken.hafas.de/bin/
// http://reseplanerare.resrobot.se/bin/
// http://api.vasttrafik.se/bin/
@ -41,7 +43,7 @@ public class SeProvider extends AbstractHafasProvider {
public SeProvider() {
super(NetworkId.SE, API_BASE, "sn", PRODUCTS_MAP);
setJsonGetStopsEncoding(Charsets.UTF_8);
setRequestUrlEncoding(Charsets.UTF_8);
setJsonNearbyLocationsEncoding(Charsets.UTF_8);
setUseIso8601(true);
setStationBoardHasStationTable(false);

View file

@ -57,7 +57,7 @@ import okhttp3.HttpUrl;
* @author Andreas Schildbach
*/
public class SeptaProvider extends AbstractHafasProvider {
private static final String API_BASE = "http://airs1.septa.org/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://airs1.septa.org/bin/");
private static final Product[] PRODUCTS_MAP = { Product.SUBWAY, Product.TRAM, Product.BUS, Product.SUBURBAN_TRAIN };
private static final long PARSER_DAY_ROLLOVER_THRESHOLD_MS = 12 * 60 * 60 * 1000;
@ -72,19 +72,18 @@ public class SeptaProvider extends AbstractHafasProvider {
public NearbyLocationsResult queryNearbyLocations(final EnumSet<LocationType> types, final Location location,
final int maxDistance, final int maxLocations) throws IOException {
if (location.type == LocationType.STATION && location.hasId()) {
final StringBuilder uri = new StringBuilder(stationBoardEndpoint);
uri.append("?near=Anzeigen");
uri.append("&distance=").append(maxDistance != 0 ? maxDistance / 1000 : 50);
uri.append("&input=").append(normalizeStationId(location.id));
return htmlNearbyStations(uri.toString());
final HttpUrl.Builder url = stationBoardEndpoint.newBuilder().addPathSegment(apiLanguage);
url.addQueryParameter("near", "Anzeigen");
url.addQueryParameter("distance", Integer.toString(maxDistance != 0 ? maxDistance / 1000 : 50));
url.addQueryParameter("input", normalizeStationId(location.id));
return htmlNearbyStations(url.build());
} else {
throw new IllegalArgumentException("cannot handle: " + location);
}
}
@Override
protected void appendDateTimeParameters(final StringBuilder uri, final Date time, final String dateParamName,
protected void appendDateTimeParameters(final HttpUrl.Builder url, final Date time, final String dateParamName,
final String timeParamName) {
final Calendar c = new GregorianCalendar(timeZone);
c.setTime(time);
@ -94,10 +93,8 @@ public class SeptaProvider extends AbstractHafasProvider {
final int hour = c.get(Calendar.HOUR);
final int minute = c.get(Calendar.MINUTE);
final String amPm = c.get(Calendar.AM_PM) == Calendar.AM ? "am" : "pm";
uri.append('&').append(dateParamName).append('=');
uri.append(ParserUtils.urlEncode(String.format(Locale.ENGLISH, "%02d%02d%04d", month, day, year)));
uri.append('&').append(timeParamName).append('=');
uri.append(ParserUtils.urlEncode(String.format(Locale.ENGLISH, "%02d:%02d %s", hour, minute, amPm)));
url.addQueryParameter(dateParamName, String.format(Locale.ENGLISH, "%02d%02d%04d", month, day, year));
url.addQueryParameter(timeParamName, String.format(Locale.ENGLISH, "%02d:%02d %s", hour, minute, amPm));
}
private static final Pattern P_DEPARTURES_PAGE_COARSE = Pattern.compile(".*?" //
@ -134,9 +131,9 @@ public class SeptaProvider extends AbstractHafasProvider {
final QueryDeparturesResult result = new QueryDeparturesResult(header);
// scrape page
final StringBuilder uri = new StringBuilder(stationBoardEndpoint);
appendXmlStationBoardParameters(uri, time, stationId, maxDepartures, false, null);
final CharSequence page = httpClient.get(HttpUrl.parse(uri.toString()));
final HttpUrl.Builder url = stationBoardEndpoint.newBuilder().addPathSegment(apiLanguage);
appendXmlStationBoardParameters(url, time, stationId, maxDepartures, false, null);
final CharSequence page = httpClient.get(url.build());
// parse page
final Matcher mPageCoarse = P_DEPARTURES_PAGE_COARSE.matcher(page);

View file

@ -42,11 +42,13 @@ import de.schildbach.pte.dto.QueryTripsResult;
import de.schildbach.pte.dto.Style;
import de.schildbach.pte.dto.SuggestLocationsResult;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class ShProvider extends AbstractHafasProvider {
private static final String API_BASE = "http://nah.sh.hafas.de/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://nah.sh.hafas.de/bin/");
private static final Product[] PRODUCTS_MAP = { Product.HIGH_SPEED_TRAIN, Product.HIGH_SPEED_TRAIN,
Product.HIGH_SPEED_TRAIN, Product.REGIONAL_TRAIN, Product.SUBURBAN_TRAIN, Product.BUS, Product.FERRY,
Product.SUBWAY, Product.TRAM, Product.ON_DEMAND };
@ -57,7 +59,6 @@ public class ShProvider extends AbstractHafasProvider {
setJsonApiVersion("1.10");
setJsonApiClient("{\"id\":\"NAHSH\"}");
setJsonApiAuthorization(jsonApiAuthorization);
setJsonGetStopsEncoding(Charsets.UTF_8);
setJsonNearbyLocationsEncoding(Charsets.UTF_8);
setStyles(STYLES);
}

View file

@ -29,11 +29,13 @@ import de.schildbach.pte.dto.LocationType;
import de.schildbach.pte.dto.NearbyLocationsResult;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class SncbProvider extends AbstractHafasProvider {
private static final String API_BASE = "http://www.belgianrail.be/jp/sncb-nmbs-routeplanner/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://www.belgianrail.be/jp/sncb-nmbs-routeplanner/");
// http://hari.b-rail.be/hafas/bin/
private static final Product[] PRODUCTS_MAP = { Product.HIGH_SPEED_TRAIN, null, Product.HIGH_SPEED_TRAIN, null,
null, Product.BUS, Product.REGIONAL_TRAIN, null, Product.SUBWAY, Product.BUS, Product.TRAM, null, null,
@ -42,7 +44,7 @@ public class SncbProvider extends AbstractHafasProvider {
public SncbProvider() {
super(NetworkId.SNCB, API_BASE, "nn", PRODUCTS_MAP);
setJsonGetStopsEncoding(Charsets.UTF_8);
setRequestUrlEncoding(Charsets.UTF_8);
setJsonNearbyLocationsEncoding(Charsets.UTF_8);
setStationBoardHasLocation(true);
}
@ -73,12 +75,11 @@ public class SncbProvider extends AbstractHafasProvider {
if (location.hasLocation()) {
return nearbyLocationsByCoordinate(types, location.lat, location.lon, maxDistance, maxLocations);
} else if (location.type == LocationType.STATION && location.hasId()) {
final StringBuilder uri = new StringBuilder(stationBoardEndpoint);
uri.append("?near=Zoek");
uri.append("&distance=").append(maxDistance != 0 ? maxDistance / 1000 : 50);
uri.append("&input=").append(normalizeStationId(location.id));
return htmlNearbyStations(uri.toString());
final HttpUrl.Builder url = stationBoardEndpoint.newBuilder().addPathSegment(apiLanguage);
url.addQueryParameter("near", "Zoek");
url.addQueryParameter("distance", Integer.toString(maxDistance != 0 ? maxDistance / 1000 : 50));
url.addQueryParameter("input", normalizeStationId(location.id));
return htmlNearbyStations(url.build());
} else {
throw new IllegalArgumentException("cannot handle: " + location);
}

View file

@ -37,11 +37,13 @@ import de.schildbach.pte.dto.QueryTripsContext;
import de.schildbach.pte.dto.QueryTripsResult;
import de.schildbach.pte.dto.SuggestLocationsResult;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class StvProvider extends AbstractEfaProvider {
private final static String API_BASE = "http://appefa10.verbundlinie.at/android/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://appefa10.verbundlinie.at/android/");
public StvProvider() {
super(NetworkId.STV, API_BASE);

View file

@ -40,11 +40,13 @@ import de.schildbach.pte.dto.QueryTripsResult;
import de.schildbach.pte.dto.Style;
import de.schildbach.pte.dto.SuggestLocationsResult;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class SvvProvider extends AbstractHafasProvider {
private static final String API_BASE = "https://fahrplan.salzburg-verkehr.at/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("https://fahrplan.salzburg-verkehr.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 };

View file

@ -30,11 +30,13 @@ import de.schildbach.pte.dto.Location;
import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.Style;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class SydneyProvider extends AbstractEfaProvider {
private final static String API_BASE = "https://tp.transportnsw.info/nsw/";
private static final HttpUrl API_BASE = HttpUrl.parse("https://tp.transportnsw.info/nsw/");
public SydneyProvider() {
super(NetworkId.SYDNEY, API_BASE);
@ -47,27 +49,24 @@ public class SydneyProvider extends AbstractEfaProvider {
}
@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,
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));
protected void appendXsltTripRequestParameters(final HttpUrl.Builder url, final Location from,
final @Nullable Location via, final Location to, final Date time, final boolean dep,
final @Nullable Collection<Product> products, final @Nullable Optimize optimize,
final @Nullable WalkSpeed walkSpeed, final @Nullable Accessibility accessibility,
final @Nullable Set<Option> options) {
super.appendXsltTripRequestParameters(url, 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"); // school bus
url.addEncodedQueryParameter("inclMOT_11", "on"); // school bus
}
}
uri.append("&inclMOT_13=on");
uri.append("&inclMOT_14=on");
uri.append("&inclMOT_15=on");
uri.append("&inclMOT_16=on");
uri.append("&inclMOT_17=on");
return uri.toString();
url.addEncodedQueryParameter("inclMOT_13", "on");
url.addEncodedQueryParameter("inclMOT_14", "on");
url.addEncodedQueryParameter("inclMOT_15", "on");
url.addEncodedQueryParameter("inclMOT_16", "on");
url.addEncodedQueryParameter("inclMOT_17", "on");
}
@Override

View file

@ -24,11 +24,13 @@ import javax.annotation.Nullable;
import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class TfiProvider extends AbstractEfaProvider {
private static final String API_BASE = "http://www.journeyplanner.transportforireland.ie/nta/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://www.journeyplanner.transportforireland.ie/nta/");
// http://www.journeyplanner.transportforireland.ie/ultraLite/

View file

@ -29,12 +29,13 @@ import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.Style;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class TlemProvider extends AbstractEfaProvider {
private final static String API_BASE = "http://www.travelineeastmidlands.co.uk/em/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://www.travelineeastmidlands.co.uk/em/");
// http://www.travelineeastmidlands.co.uk/em/
// http://www.travelinesw.com/swe/
// http://www.travelinesoutheast.org.uk/se/

View file

@ -27,11 +27,13 @@ import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.Style;
import de.schildbach.pte.dto.Style.Shape;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class VagfrProvider extends AbstractEfaProvider {
private final static String API_BASE = "https://efaserver.vag-freiburg.de/vagfr/";
private static final HttpUrl API_BASE = HttpUrl.parse("https://efaserver.vag-freiburg.de/vagfr/");
public VagfrProvider() {
super(NetworkId.VAGFR, API_BASE);

View file

@ -40,11 +40,13 @@ import de.schildbach.pte.dto.QueryTripsResult;
import de.schildbach.pte.dto.Style;
import de.schildbach.pte.dto.SuggestLocationsResult;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class VaoProvider extends AbstractHafasProvider {
private static final String API_BASE = "https://app.verkehrsauskunft.at/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("https://app.verkehrsauskunft.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 };

View file

@ -27,11 +27,13 @@ import com.google.common.base.Charsets;
import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class VbbProvider extends AbstractHafasProvider {
private static final String API_BASE = "http://fahrinfo.vbb.de/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://fahrinfo.vbb.de/bin/");
private static final Product[] PRODUCTS_MAP = { Product.SUBURBAN_TRAIN, Product.SUBWAY, Product.TRAM, Product.BUS,
Product.FERRY, Product.HIGH_SPEED_TRAIN, Product.REGIONAL_TRAIN };
private static final Set<Product> ALL_EXCEPT_HIGHSPEED_AND_ONDEMAND = EnumSet
@ -40,8 +42,8 @@ public class VbbProvider extends AbstractHafasProvider {
public VbbProvider() {
super(NetworkId.VBB, API_BASE, "dn", PRODUCTS_MAP);
setRequestUrlEncoding(Charsets.UTF_8);
setJsonGetStopsUseWeight(false);
setJsonGetStopsEncoding(Charsets.UTF_8);
setJsonNearbyLocationsEncoding(Charsets.UTF_8);
setClientType(null);
}

View file

@ -22,11 +22,13 @@ import javax.annotation.Nullable;
import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class VblProvider extends AbstractEfaProvider {
private final static String API_BASE = "http://mobil.vbl.ch/vblmobil/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://mobil.vbl.ch/vblmobil/");
public VblProvider() {
super(NetworkId.VBL, API_BASE);

View file

@ -40,11 +40,13 @@ import de.schildbach.pte.dto.Style;
import de.schildbach.pte.dto.Style.Shape;
import de.schildbach.pte.dto.SuggestLocationsResult;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class VbnProvider extends AbstractHafasProvider {
private static final String API_BASE = "https://fahrplaner.vbn.de/hafas/";
private static final HttpUrl API_BASE = HttpUrl.parse("https://fahrplaner.vbn.de/hafas/");
// http://fahrplaner.vsninfo.de/hafas/
// http://fahrplan.rsag-online.de/hafas/
// http://fahrplanauskunft.verkehrsverbund-warnow.de/bin/

View file

@ -30,6 +30,8 @@ import de.schildbach.pte.dto.LocationType;
import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.SuggestLocationsResult;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
@ -37,7 +39,7 @@ public class VgnProvider extends AbstractEfaProvider {
private static final String DEPARTURE_MONITOR_ENDPOINT = "XML_DM_REQUEST";
private static final String TRIP_ENDPOINT = "XML_TRIP_REQUEST2";
public VgnProvider(final String apiBase) {
public VgnProvider(final HttpUrl apiBase) {
super(NetworkId.VGN, apiBase, DEPARTURE_MONITOR_ENDPOINT, TRIP_ENDPOINT, null, null);
}
@ -63,11 +65,13 @@ public class VgnProvider extends AbstractEfaProvider {
}
@Override
protected String xsltTripRequestParameters(final Location from, final @Nullable Location via, final Location to,
final Date date, final boolean dep, final @Nullable Collection<Product> products,
final @Nullable Optimize optimize, final @Nullable WalkSpeed walkSpeed,
final @Nullable Accessibility accessibility, final @Nullable Set<Option> options) {
return super.xsltTripRequestParameters(from, via, to, date, dep, products, optimize, walkSpeed, accessibility,
options) + "&itdLPxx_showTariffLevel=1";
protected void appendXsltTripRequestParameters(final HttpUrl.Builder url, final Location from,
final @Nullable Location via, final Location to, final Date date, final boolean dep,
final @Nullable Collection<Product> products, final @Nullable Optimize optimize,
final @Nullable WalkSpeed walkSpeed, final @Nullable Accessibility accessibility,
final @Nullable Set<Option> options) {
super.appendXsltTripRequestParameters(url, from, via, to, date, dep, products, optimize, walkSpeed,
accessibility, options);
url.addEncodedQueryParameter("itdLPxx_showTariffLevel", "1");
}
}

View file

@ -26,11 +26,14 @@ import de.schildbach.pte.dto.LocationType;
import de.schildbach.pte.dto.NearbyLocationsResult;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class VgsProvider extends AbstractHafasProvider {
private static final String API_BASE = "http://www.saarfahrplan.de/cgi-bin/"; // http://www.vgs-online.de/cgi-bin/
private static final HttpUrl API_BASE = HttpUrl.parse("http://www.saarfahrplan.de/cgi-bin/");
// http://www.vgs-online.de/cgi-bin/
private static final Product[] PRODUCTS_MAP = { Product.HIGH_SPEED_TRAIN, Product.HIGH_SPEED_TRAIN,
Product.HIGH_SPEED_TRAIN, Product.REGIONAL_TRAIN, Product.SUBURBAN_TRAIN, Product.SUBWAY, Product.TRAM,
Product.BUS, Product.CABLECAR, Product.ON_DEMAND, Product.BUS };
@ -74,12 +77,11 @@ public class VgsProvider extends AbstractHafasProvider {
if (location.hasLocation()) {
return nearbyLocationsByCoordinate(types, location.lat, location.lon, maxDistance, maxLocations);
} else if (location.type == LocationType.STATION && location.hasId()) {
final StringBuilder uri = new StringBuilder(stationBoardEndpoint);
uri.append("?near=Anzeigen");
uri.append("&distance=").append(maxDistance != 0 ? maxDistance / 1000 : 50);
uri.append("&input=").append(normalizeStationId(location.id));
return htmlNearbyStations(uri.toString());
final HttpUrl.Builder url = stationBoardEndpoint.newBuilder().addPathSegment(apiLanguage);
url.addQueryParameter("near", "Anzeigen");
url.addQueryParameter("distance", Integer.toString(maxDistance != 0 ? maxDistance / 1000 : 50));
url.addQueryParameter("input", normalizeStationId(location.id));
return htmlNearbyStations(url.build());
} else {
throw new IllegalArgumentException("cannot handle: " + location);
}

View file

@ -37,11 +37,13 @@ import de.schildbach.pte.dto.QueryTripsContext;
import de.schildbach.pte.dto.QueryTripsResult;
import de.schildbach.pte.dto.SuggestLocationsResult;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class VmobilProvider extends AbstractHafasProvider {
private static final String API_BASE = "https://fahrplan.vmobil.at/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("https://fahrplan.vmobil.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 };

View file

@ -27,11 +27,13 @@ import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Location;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class VmsProvider extends AbstractEfaProvider {
private static final String API_BASE = "http://www.vms.de/vms2/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://www.vms.de/vms2/");
public VmsProvider() {
super(NetworkId.VMS, API_BASE);
@ -40,21 +42,19 @@ public class VmsProvider extends AbstractEfaProvider {
}
@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,
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));
uri.append("&inclMOT_11=on");
uri.append("&inclMOT_13=on");
uri.append("&inclMOT_14=on");
uri.append("&inclMOT_15=on");
uri.append("&inclMOT_16=on");
uri.append("&inclMOT_17=on");
return uri.toString();
protected void appendXsltTripRequestParameters(final HttpUrl.Builder url, final Location from,
final @Nullable Location via, final Location to, final Date time, final boolean dep,
final @Nullable Collection<Product> products, final @Nullable Optimize optimize,
final @Nullable WalkSpeed walkSpeed, final @Nullable Accessibility accessibility,
final @Nullable Set<Option> options) {
super.appendXsltTripRequestParameters(url, from, via, to, time, dep, products, optimize, walkSpeed,
accessibility, options);
url.addEncodedQueryParameter("inclMOT_11", "on");
url.addEncodedQueryParameter("inclMOT_13", "on");
url.addEncodedQueryParameter("inclMOT_14", "on");
url.addEncodedQueryParameter("inclMOT_15", "on");
url.addEncodedQueryParameter("inclMOT_16", "on");
url.addEncodedQueryParameter("inclMOT_17", "Fon");
}
@Override

View file

@ -17,11 +17,13 @@
package de.schildbach.pte;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class VmvProvider extends AbstractEfaProvider {
private static final String API_BASE = "http://80.146.180.107/vmv2/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://80.146.180.107/vmv2/");
// http://80.146.180.107/vmv/
// http://80.146.180.107/delfi/

View file

@ -40,11 +40,13 @@ import de.schildbach.pte.dto.QueryTripsResult;
import de.schildbach.pte.dto.Style;
import de.schildbach.pte.dto.SuggestLocationsResult;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class VorProvider extends AbstractHafasProvider {
private static final String API_BASE = "https://anachb.vor.at/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("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 };

View file

@ -29,11 +29,13 @@ import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.Style;
import de.schildbach.pte.dto.Style.Shape;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class VrnProvider extends AbstractEfaProvider {
private static final String API_BASE = "https://www.vrn.de/mngvrn/";
private static final HttpUrl API_BASE = HttpUrl.parse("https://www.vrn.de/mngvrn/");
public VrnProvider() {
super(NetworkId.VRN, API_BASE);

View file

@ -33,19 +33,20 @@ import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.Style;
import de.schildbach.pte.dto.Style.Shape;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class VrrProvider extends AbstractEfaProvider {
private static final String API_BASE = "http://efa.vrr.de/standard/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://efa.vrr.de/standard/");
// http://app.vrr.de/companion-vrr/
public VrrProvider() {
this(API_BASE);
}
public VrrProvider(final String apiBase) {
public VrrProvider(final HttpUrl apiBase) {
super(NetworkId.VRR, apiBase);
setIncludeRegionId(false);
@ -58,21 +59,19 @@ public class VrrProvider extends AbstractEfaProvider {
}
@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,
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));
protected void appendXsltTripRequestParameters(final HttpUrl.Builder url, final Location from,
final @Nullable Location via, final Location to, final Date time, final boolean dep,
final @Nullable Collection<Product> products, final @Nullable Optimize optimize,
final @Nullable WalkSpeed walkSpeed, final @Nullable Accessibility accessibility,
final @Nullable Set<Option> options) {
super.appendXsltTripRequestParameters(url, from, via, to, time, dep, products, optimize, walkSpeed,
accessibility, options);
if (products != null) {
for (final Product p : products) {
if (p == Product.CABLECAR)
uri.append("&inclMOT_11=on"); // Schwebebahn
url.addEncodedQueryParameter("inclMOT_11", "on"); // Schwebebahn
}
}
return uri.toString();
}
@Override

View file

@ -72,7 +72,6 @@ import de.schildbach.pte.dto.SuggestLocationsResult;
import de.schildbach.pte.dto.SuggestedLocation;
import de.schildbach.pte.dto.Trip;
import de.schildbach.pte.dto.Trip.Leg;
import de.schildbach.pte.util.ParserUtils;
import okhttp3.HttpUrl;
@ -150,7 +149,7 @@ public class VrsProvider extends AbstractNetworkProvider {
// encrypted with
// client certificate)
// performance comparison March 2015 showed www.vrsinfo.de to be fastest for trips
protected static final String API_BASE = "http://android.vrsinfo.de/index.php";
protected static final HttpUrl API_BASE = HttpUrl.parse("http://android.vrsinfo.de/index.php");
protected static final String SERVER_PRODUCT = "vrs";
@SuppressWarnings("serial")
@ -361,24 +360,24 @@ public class VrsProvider extends AbstractNetworkProvider {
public NearbyLocationsResult queryNearbyLocations(EnumSet<LocationType> types /* only STATION supported */,
Location location, int maxDistance, int maxLocations) throws IOException {
// g=p means group by product; not used here
final StringBuilder uri = new StringBuilder(API_BASE);
uri.append("?eID=tx_vrsinfo_ass2_timetable");
final HttpUrl.Builder url = API_BASE.newBuilder();
url.addQueryParameter("eID", "tx_vrsinfo_ass2_timetable");
if (location.hasLocation()) {
uri.append("&r=")
.append(String.format(Locale.ENGLISH, "%.6f,%.6f", location.lat / 1E6, location.lon / 1E6));
url.addQueryParameter("r",
String.format(Locale.ENGLISH, "%.6f,%.6f", location.lat / 1E6, location.lon / 1E6));
} else if (location.type == LocationType.STATION && location.hasId()) {
uri.append("&i=").append(ParserUtils.urlEncode(location.id));
url.addQueryParameter("i", location.id);
} else {
throw new IllegalArgumentException("at least one of stationId or lat/lon must be given");
}
// c=1 limits the departures at each stop to 1 - actually we don't need any at this point
uri.append("&c=1");
url.addQueryParameter("c", "1");
if (maxLocations > 0) {
// s=number of stops
uri.append("&s=").append(Math.min(16, maxLocations)); // artificial server limit
// s=number of stops, artificially limited by server
url.addQueryParameter("s", Integer.toString(Math.min(16, maxLocations)));
}
final CharSequence page = httpClient.get(HttpUrl.parse(uri.toString()));
final CharSequence page = httpClient.get(url.build());
try {
final List<Location> locations = new ArrayList<Location>();
@ -411,9 +410,9 @@ public class VrsProvider extends AbstractNetworkProvider {
final ResultHeader header = new ResultHeader(NetworkId.VRS, SERVER_PRODUCT, null, null, serverTime, null);
return new NearbyLocationsResult(header, locations);
} catch (final JSONException x) {
throw new RuntimeException("cannot parse: '" + page + "' on " + uri, x);
throw new RuntimeException("cannot parse: '" + page + "' on " + url, x);
} catch (final ParseException e) {
throw new RuntimeException("cannot parse: '" + page + "' on " + uri, e);
throw new RuntimeException("cannot parse: '" + page + "' on " + url, e);
}
}
@ -427,14 +426,14 @@ public class VrsProvider extends AbstractNetworkProvider {
// g=p means group by product; not used here
// d=minutes overwrites c=count and returns departures for the next d minutes
final StringBuilder uri = new StringBuilder(API_BASE);
uri.append("?eID=tx_vrsinfo_ass2_timetable&i=").append(ParserUtils.urlEncode(stationId));
uri.append("&c=").append(maxDepartures);
final HttpUrl.Builder url = API_BASE.newBuilder();
url.addQueryParameter("eID", "tx_vrsinfo_ass2_timetable");
url.addQueryParameter("i", stationId);
url.addQueryParameter("c", Integer.toString(maxDepartures));
if (time != null) {
uri.append("&t=");
appendDate(uri, time);
url.addQueryParameter("t", formatDate(time));
}
final CharSequence page = httpClient.get(HttpUrl.parse(uri.toString()));
final CharSequence page = httpClient.get(url.build());
try {
final JSONObject head = new JSONObject(page.toString());
@ -511,9 +510,9 @@ public class VrsProvider extends AbstractNetworkProvider {
return result;
} catch (final JSONException x) {
throw new RuntimeException("cannot parse: '" + page + "' on " + uri, x);
throw new RuntimeException("cannot parse: '" + page + "' on " + url, x);
} catch (final ParseException e) {
throw new RuntimeException("cannot parse: '" + page + "' on " + uri, e);
throw new RuntimeException("cannot parse: '" + page + "' on " + url, e);
}
}
@ -522,10 +521,11 @@ public class VrsProvider extends AbstractNetworkProvider {
for (LineDestination lineDestionation : lineDestinations) {
lineNumbersAlreadyKnown.add(lineDestionation.line.label);
}
final StringBuilder uri = new StringBuilder(API_BASE);
uri.append("?eID=tx_vrsinfo_his_info&i=").append(ParserUtils.urlEncode(stationId));
final HttpUrl.Builder url = API_BASE.newBuilder();
url.addQueryParameter("eID", "tx_vrsinfo_his_info");
url.addQueryParameter("i", stationId);
final CharSequence page = httpClient.get(HttpUrl.parse(uri.toString()));
final CharSequence page = httpClient.get(url.build());
try {
final JSONObject head = new JSONObject(page.toString());
@ -560,7 +560,7 @@ public class VrsProvider extends AbstractNetworkProvider {
}
}
} catch (final JSONException x) {
throw new RuntimeException("cannot parse: '" + page + "' on " + uri, x);
throw new RuntimeException("cannot parse: '" + page + "' on " + url, x);
}
Collections.sort(lineDestinations, new LineDestinationComparator());
}
@ -581,10 +581,15 @@ public class VrsProvider extends AbstractNetworkProvider {
// pc = points of interest count
final int pc = 5;
// t = sap (stops and/or addresses and/or pois)
final String uri = API_BASE + "?eID=tx_vrsinfo_ass2_objects&sc=" + sc + "&ac=" + ac + "&pc=" + ac + "&t=sap&q="
+ ParserUtils.urlEncode(new Location(LocationType.ANY, null, null, constraint.toString()).name);
final HttpUrl.Builder url = API_BASE.newBuilder();
url.addQueryParameter("eID", "tx_vrsinfo_ass2_objects");
url.addQueryParameter("sc", Integer.toString(sc));
url.addQueryParameter("ac", Integer.toString(ac));
url.addQueryParameter("pc", Integer.toString(pc));
url.addQueryParameter("t", "sap");
url.addQueryParameter("q", constraint.toString());
final CharSequence page = httpClient.get(HttpUrl.parse(uri));
final CharSequence page = httpClient.get(url.build());
try {
final List<SuggestedLocation> locations = new ArrayList<SuggestedLocation>();
@ -628,7 +633,7 @@ public class VrsProvider extends AbstractNetworkProvider {
final ResultHeader header = new ResultHeader(NetworkId.VRS, SERVER_PRODUCT);
return new SuggestLocationsResult(header, locations);
} catch (final JSONException x) {
throw new RuntimeException("cannot parse: '" + page + "' on " + uri, x);
throw new RuntimeException("cannot parse: '" + page + "' on " + url, x);
}
}
@ -683,26 +688,22 @@ public class VrsProvider extends AbstractNetworkProvider {
QueryTripsResult.Status.UNKNOWN_TO);
}
final StringBuilder uri = new StringBuilder(API_BASE);
uri.append("?eID=tx_vrsinfo_ass2_router&f=").append(fromString).append("&t=").append(toString);
final HttpUrl.Builder url = API_BASE.newBuilder();
url.addQueryParameter("eID", "tx_vrsinfo_ass2_router");
url.addQueryParameter("f", fromString);
url.addQueryParameter("t", toString);
if (via != null) {
uri.append("&v=").append(via.id);
url.addQueryParameter("v", via.id);
}
if (dep) {
uri.append("&d=");
} else {
uri.append("&a=");
}
appendDate(uri, date);
uri.append("&s=t");
uri.append("&p=");
uri.append(generateProducts(products));
uri.append("&o=v");
url.addQueryParameter(dep ? "d" : "a", formatDate(date));
url.addQueryParameter("s", "t");
url.addQueryParameter("p", generateProducts(products));
url.addQueryParameter("o", "v");
if (EXACT_POINTS) {
uri.append("p");
url.addQueryParameter("p", "");
}
final CharSequence page = httpClient.get(HttpUrl.parse(uri.toString()));
final CharSequence page = httpClient.get(url.build());
try {
final List<Trip> trips = new ArrayList<Trip>();
@ -891,11 +892,11 @@ public class VrsProvider extends AbstractNetworkProvider {
else
context.disableEarlier();
}
return new QueryTripsResult(header, uri.toString(), from, via, to, context, trips);
return new QueryTripsResult(header, url.build().toString(), from, via, to, context, trips);
} catch (final JSONException x) {
throw new RuntimeException("cannot parse: '" + page + "' on " + uri, x);
throw new RuntimeException("cannot parse: '" + page + "' on " + url, x);
} catch (final ParseException e) {
throw new RuntimeException("cannot parse: '" + page + "' on " + uri, e);
throw new RuntimeException("cannot parse: '" + page + "' on " + url, e);
}
}
@ -1126,7 +1127,7 @@ public class VrsProvider extends AbstractNetworkProvider {
}
}
private final static void appendDate(final StringBuilder uri, final Date time) {
private final static String formatDate(final Date time) {
final Calendar c = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
c.setTime(time);
final int year = c.get(Calendar.YEAR);
@ -1135,8 +1136,7 @@ public class VrsProvider extends AbstractNetworkProvider {
final int hour = c.get(Calendar.HOUR_OF_DAY);
final int minute = c.get(Calendar.MINUTE);
final int second = c.get(Calendar.SECOND);
uri.append(ParserUtils.urlEncode(String.format(Locale.ENGLISH, "%04d-%02d-%02dT%02d:%02d:%02dZ", year, month,
day, hour, minute, second)));
return String.format(Locale.ENGLISH, "%04d-%02d-%02dT%02d:%02d:%02dZ", year, month, day, hour, minute, second);
}
private final static Date parseDateTime(final String dateTimeStr) throws ParseException {

View file

@ -17,11 +17,13 @@
package de.schildbach.pte;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class VvmProvider extends AbstractEfaProvider {
private final static String API_BASE = "http://efa.mobilitaetsverbund.de/web/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://efa.mobilitaetsverbund.de/web/");
public VvmProvider() {
super(NetworkId.VVM, API_BASE);

View file

@ -24,17 +24,19 @@ import com.google.common.base.Charsets;
import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class VvoProvider extends AbstractEfaProvider {
private final static String API_BASE = "http://efa.vvo-online.de:8080/dvb/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://efa.vvo-online.de:8080/dvb/");
public VvoProvider() {
this(API_BASE);
}
public VvoProvider(final String apiBase) {
public VvoProvider(final HttpUrl apiBase) {
super(NetworkId.VVO, apiBase);
setRequestUrlEncoding(Charsets.UTF_8);

View file

@ -23,17 +23,19 @@ import de.schildbach.pte.dto.Line;
import de.schildbach.pte.dto.Point;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class VvsProvider extends AbstractEfaProvider {
private static final String API_BASE = "http://www2.vvs.de/vvs/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://www2.vvs.de/vvs/");
public VvsProvider() {
this(API_BASE);
}
public VvsProvider(final String apiBase) {
public VvsProvider(final HttpUrl apiBase) {
super(NetworkId.VVS, apiBase);
setIncludeRegionId(false);

View file

@ -37,11 +37,13 @@ import de.schildbach.pte.dto.QueryTripsContext;
import de.schildbach.pte.dto.QueryTripsResult;
import de.schildbach.pte.dto.SuggestLocationsResult;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class VvtProvider extends AbstractHafasProvider {
private static final String API_BASE = "https://fahrplan.vvt.at/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("https://fahrplan.vvt.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 };

View file

@ -17,13 +17,15 @@
package de.schildbach.pte;
import okhttp3.HttpUrl;
/**
* Verkehrsverbund Vogtland
*
* @author Andreas Schildbach
*/
public class VvvProvider extends AbstractEfaProvider {
private final static String API_BASE = "http://195.30.98.162:8081/vvv2/";
private static final HttpUrl API_BASE = HttpUrl.parse("http://195.30.98.162:8081/vvv2/");
public VvvProvider() {
super(NetworkId.VVV, API_BASE);

View file

@ -31,11 +31,13 @@ import de.schildbach.pte.dto.Location;
import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.Style;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class WienProvider extends AbstractEfaProvider {
private final static String API_BASE = "https://www.wienerlinien.at/ogd_routing/";
private static final HttpUrl API_BASE = HttpUrl.parse("https://www.wienerlinien.at/ogd_routing/");
public WienProvider() {
super(NetworkId.WIEN, API_BASE);
@ -46,21 +48,19 @@ public class WienProvider extends AbstractEfaProvider {
}
@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,
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));
protected void appendXsltTripRequestParameters(final HttpUrl.Builder url, final Location from,
final @Nullable Location via, final Location to, final Date time, final boolean dep,
final @Nullable Collection<Product> products, final @Nullable Optimize optimize,
final @Nullable WalkSpeed walkSpeed, final @Nullable Accessibility accessibility,
final @Nullable Set<Option> options) {
super.appendXsltTripRequestParameters(url, 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
url.addEncodedQueryParameter("inclMOT_11", "on"); // night bus
}
}
return uri.toString();
}
private static final Map<String, Style> STYLES = new HashMap<String, Style>();

View file

@ -31,11 +31,13 @@ import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.Style;
import de.schildbach.pte.dto.Style.Shape;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class ZvvProvider extends AbstractHafasProvider {
private static final String API_BASE = "https://online.fahrplan.zvv.ch/bin/";
private static final HttpUrl API_BASE = HttpUrl.parse("https://online.fahrplan.zvv.ch/bin/");
private static final Product[] PRODUCTS_MAP = { Product.HIGH_SPEED_TRAIN, Product.HIGH_SPEED_TRAIN,
Product.REGIONAL_TRAIN, Product.REGIONAL_TRAIN, Product.FERRY, Product.SUBURBAN_TRAIN, Product.BUS,
Product.CABLECAR, Product.SUBWAY, Product.TRAM };
@ -43,7 +45,7 @@ public class ZvvProvider extends AbstractHafasProvider {
public ZvvProvider() {
super(NetworkId.ZVV, API_BASE, "dn", PRODUCTS_MAP);
setJsonGetStopsEncoding(Charsets.UTF_8);
setRequestUrlEncoding(Charsets.UTF_8);
setJsonNearbyLocationsEncoding(Charsets.UTF_8);
setStyles(STYLES);
}

View file

@ -254,14 +254,6 @@ public final class ParserUtils {
}
}
public static String urlEncode(final String str) {
try {
return URLEncoder.encode(str, "utf-8");
} catch (final UnsupportedEncodingException x) {
throw new RuntimeException(x);
}
}
public static String urlEncode(final String str, final Charset encoding) {
try {
return URLEncoder.encode(str, encoding.name());

View file

@ -35,12 +35,14 @@ import de.schildbach.pte.dto.QueryDeparturesResult;
import de.schildbach.pte.dto.QueryTripsResult;
import de.schildbach.pte.dto.SuggestLocationsResult;
import okhttp3.HttpUrl;
/**
* @author Andreas Schildbach
*/
public class VgnProviderLiveTest extends AbstractProviderLiveTest {
public VgnProviderLiveTest() {
super(new VgnProvider(secretProperty("vgn.api_base")));
super(new VgnProvider(HttpUrl.parse(secretProperty("vgn.api_base"))));
}
@Test