From 4f7bd832e68527a343710d69d11b179cd49116a6 Mon Sep 17 00:00:00 2001 From: Andreas Schildbach Date: Mon, 2 Jan 2017 19:15:29 +0100 Subject: [PATCH] Use HttpUrl and HttpUrl.Builder where possible. --- .../schildbach/pte/AbstractEfaProvider.java | 419 +++++++++--------- .../schildbach/pte/AbstractHafasProvider.java | 325 +++++++------- .../pte/AbstractNavitiaProvider.java | 177 ++++---- .../pte/AbstractNetworkProvider.java | 8 + .../schildbach/pte/AbstractTsiProvider.java | 138 +++--- .../src/de/schildbach/pte/AtcProvider.java | 5 +- .../src/de/schildbach/pte/AvvProvider.java | 32 +- .../src/de/schildbach/pte/BahnProvider.java | 6 +- .../src/de/schildbach/pte/BayernProvider.java | 34 +- .../src/de/schildbach/pte/BsvagProvider.java | 22 +- .../src/de/schildbach/pte/BvbProvider.java | 4 +- .../src/de/schildbach/pte/BvgProvider.java | 6 +- .../src/de/schildbach/pte/DingProvider.java | 4 +- .../src/de/schildbach/pte/DsbProvider.java | 4 +- .../src/de/schildbach/pte/DubProvider.java | 4 +- .../de/schildbach/pte/EireannProvider.java | 4 +- .../pte/FranceNorthEastProvider.java | 4 +- .../pte/FranceNorthWestProvider.java | 4 +- .../pte/FranceSouthEastProvider.java | 4 +- .../pte/FranceSouthWestProvider.java | 4 +- .../src/de/schildbach/pte/GvhProvider.java | 7 +- .../src/de/schildbach/pte/HslProvider.java | 87 ++-- .../src/de/schildbach/pte/InvgProvider.java | 23 +- .../src/de/schildbach/pte/ItalyProvider.java | 4 +- .../src/de/schildbach/pte/IvbProvider.java | 4 +- .../src/de/schildbach/pte/KvvProvider.java | 6 +- .../src/de/schildbach/pte/LinzProvider.java | 5 +- enabler/src/de/schildbach/pte/LuProvider.java | 6 +- .../src/de/schildbach/pte/MerseyProvider.java | 4 +- .../src/de/schildbach/pte/MetProvider.java | 4 +- .../src/de/schildbach/pte/MvgProvider.java | 4 +- .../src/de/schildbach/pte/MvvProvider.java | 6 +- .../src/de/schildbach/pte/NasaProvider.java | 17 +- .../src/de/schildbach/pte/NriProvider.java | 6 +- enabler/src/de/schildbach/pte/NsProvider.java | 17 +- .../src/de/schildbach/pte/NvbwProvider.java | 14 +- .../src/de/schildbach/pte/NvvProvider.java | 18 +- .../src/de/schildbach/pte/OebbProvider.java | 15 +- .../de/schildbach/pte/OntarioProvider.java | 4 +- .../src/de/schildbach/pte/OoevvProvider.java | 4 +- .../src/de/schildbach/pte/PacaProvider.java | 4 +- .../src/de/schildbach/pte/ParisProvider.java | 4 +- enabler/src/de/schildbach/pte/PlProvider.java | 6 +- .../src/de/schildbach/pte/QuebecProvider.java | 4 +- enabler/src/de/schildbach/pte/RtProvider.java | 4 +- .../de/schildbach/pte/RtaChicagoProvider.java | 6 +- .../src/de/schildbach/pte/SbbProvider.java | 4 +- enabler/src/de/schildbach/pte/SeProvider.java | 6 +- .../src/de/schildbach/pte/SeptaProvider.java | 27 +- enabler/src/de/schildbach/pte/ShProvider.java | 5 +- .../src/de/schildbach/pte/SncbProvider.java | 17 +- .../src/de/schildbach/pte/StvProvider.java | 4 +- .../src/de/schildbach/pte/SvvProvider.java | 4 +- .../src/de/schildbach/pte/SydneyProvider.java | 33 +- .../src/de/schildbach/pte/TfiProvider.java | 4 +- .../src/de/schildbach/pte/TlemProvider.java | 5 +- .../src/de/schildbach/pte/VagfrProvider.java | 4 +- .../src/de/schildbach/pte/VaoProvider.java | 4 +- .../src/de/schildbach/pte/VbbProvider.java | 6 +- .../src/de/schildbach/pte/VblProvider.java | 4 +- .../src/de/schildbach/pte/VbnProvider.java | 4 +- .../src/de/schildbach/pte/VgnProvider.java | 18 +- .../src/de/schildbach/pte/VgsProvider.java | 16 +- .../src/de/schildbach/pte/VmobilProvider.java | 4 +- .../src/de/schildbach/pte/VmsProvider.java | 32 +- .../src/de/schildbach/pte/VmvProvider.java | 4 +- .../src/de/schildbach/pte/VorProvider.java | 4 +- .../src/de/schildbach/pte/VrnProvider.java | 4 +- .../src/de/schildbach/pte/VrrProvider.java | 25 +- .../src/de/schildbach/pte/VrsProvider.java | 100 ++--- .../src/de/schildbach/pte/VvmProvider.java | 4 +- .../src/de/schildbach/pte/VvoProvider.java | 6 +- .../src/de/schildbach/pte/VvsProvider.java | 6 +- .../src/de/schildbach/pte/VvtProvider.java | 4 +- .../src/de/schildbach/pte/VvvProvider.java | 4 +- .../src/de/schildbach/pte/WienProvider.java | 22 +- .../src/de/schildbach/pte/ZvvProvider.java | 6 +- .../de/schildbach/pte/util/ParserUtils.java | 8 - .../pte/live/VgnProviderLiveTest.java | 4 +- 79 files changed, 977 insertions(+), 916 deletions(-) diff --git a/enabler/src/de/schildbach/pte/AbstractEfaProvider.java b/enabler/src/de/schildbach/pte/AbstractEfaProvider.java index 98c7315b..e57043d5 100644 --- a/enabler/src/de/schildbach/pte/AbstractEfaProvider.java +++ b/enabler/src/de/schildbach/pte/AbstractEfaProvider.java @@ -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("®ionID_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 result = new AtomicReference(); 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 result = new AtomicReference(); 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 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 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 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 result = new AtomicReference(); 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 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 result = new AtomicReference(); 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 result = new AtomicReference(); 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 result = new AtomicReference(); 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 result = new AtomicReference(); 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 products, - final @Nullable Optimize optimize, final @Nullable WalkSpeed walkSpeed, - final @Nullable Accessibility accessibility, final @Nullable Set