1919import com .mapbox .geojson .Point ;
2020import java .io .UnsupportedEncodingException ;
2121import java .net .MalformedURLException ;
22- import java .net .URI ;
23- import java .net .URISyntaxException ;
2422import java .net .URL ;
2523import java .net .URLDecoder ;
24+ import java .net .URLEncoder ;
2625import java .util .LinkedHashMap ;
2726import java .util .List ;
2827import java .util .Map ;
@@ -232,8 +231,9 @@ public List<Bearing> bearingsList() {
232231 * to differentiate them.
233232 * <p>
234233 * If provided, the list of layers must be the same length as the list of coordinates.
234+ *
235235 * @return a string representing the layers with the ; separator. Each value may be negative
236- or absent.
236+ * or absent.
237237 */
238238 @ Nullable
239239 public abstract String layers ();
@@ -871,7 +871,7 @@ public static RouteOptions fromUrl(@NonNull URL url) {
871871 String baseUrl = url .getProtocol () + "://" + url .getHost ();
872872 int port = url .getPort ();
873873 if (port != -1 ) {
874- baseUrl += ":" + port ;
874+ baseUrl += ":" + port ;
875875 }
876876 optionsJson .addProperty ("baseUrl" , baseUrl );
877877
@@ -921,101 +921,43 @@ public URL toUrl(@NonNull String accessToken) {
921921 .append (String .format ("?%s=%s" , ACCESS_TOKEN_URL_PARAM_NAME , accessToken ))
922922 .append (String .format ("&geometries=%s" , geometries ()));
923923
924- if (alternatives () != null ) {
925- sb .append (String .format ("&alternatives=%s" , alternatives ()));
926- }
927- if (overview () != null ) {
928- sb .append (String .format ("&overview=%s" , overview ()));
929- }
930- if (radiuses () != null ) {
931- sb .append (String .format ("&radiuses=%s" , radiuses ()));
932- }
933- if (steps () != null ) {
934- sb .append (String .format ("&steps=%s" , steps ()));
935- }
936- if (avoidManeuverRadius () != null ) {
937- sb .append (String .format ("&avoid_maneuver_radius=%s" , avoidManeuverRadius ()));
938- }
939- if (bearings () != null ) {
940- sb .append (String .format ("&bearings=%s" , bearings ()));
941- }
942- if (layers () != null ) {
943- sb .append (String .format ("&layers=%s" , layers ()));
944- }
945- if (continueStraight () != null ) {
946- sb .append (String .format ("&continue_straight=%s" , continueStraight ()));
947- }
948- if (annotations () != null ) {
949- sb .append (String .format ("&annotations=%s" , annotations ()));
950- }
951- if (language () != null ) {
952- sb .append (String .format ("&language=%s" , language ()));
953- }
954- if (roundaboutExits () != null ) {
955- sb .append (String .format ("&roundabout_exits=%s" , roundaboutExits ()));
956- }
957- if (voiceInstructions () != null ) {
958- sb .append (String .format ("&voice_instructions=%s" , voiceInstructions ()));
959- }
960- if (bannerInstructions () != null ) {
961- sb .append (String .format ("&banner_instructions=%s" , bannerInstructions ()));
962- }
963- if (voiceUnits () != null ) {
964- sb .append (String .format ("&voice_units=%s" , voiceUnits ()));
965- }
966- if (exclude () != null ) {
967- sb .append (String .format ("&exclude=%s" , exclude ()));
968- }
969- if (include () != null ) {
970- sb .append (String .format ("&include=%s" , include ()));
971- }
972- if (approaches () != null ) {
973- sb .append (String .format ("&approaches=%s" , approaches ()));
974- }
975- if (waypointIndices () != null ) {
976- sb .append (String .format ("&waypoints=%s" , waypointIndices ()));
977- }
978- if (waypointNames () != null ) {
979- sb .append (String .format ("&waypoint_names=%s" , waypointNames ()));
980- }
981- if (waypointTargets () != null ) {
982- sb .append (String .format ("&waypoint_targets=%s" , waypointTargets ()));
983- }
984- if (enableRefresh () != null ) {
985- sb .append (String .format ("&enable_refresh=%s" , enableRefresh ()));
986- }
987- if (walkingSpeed () != null ) {
988- sb .append (String .format ("&walking_speed=%s" , walkingSpeed ()));
989- }
990- if (walkwayBias () != null ) {
991- sb .append (String .format ("&walkway_bias=%s" , walkwayBias ()));
992- }
993- if (alleyBias () != null ) {
994- sb .append (String .format ("&alley_bias=%s" , alleyBias ()));
995- }
996- if (snappingIncludeClosures () != null ) {
997- sb .append (String .format ("&snapping_include_closures=%s" , snappingIncludeClosures ()));
998- }
999- if (arriveBy () != null ) {
1000- sb .append (String .format ("&arrive_by=%s" , arriveBy ()));
1001- }
1002- if (departAt () != null ) {
1003- sb .append (String .format ("&depart_at=%s" , departAt ()));
1004- }
1005- if (maxHeight () != null ) {
1006- sb .append (String .format ("&max_height=%s" , maxHeight ()));
1007- }
1008- if (maxWidth () != null ) {
1009- sb .append (String .format ("&max_width=%s" , maxWidth ()));
1010- }
1011- if (metadata () != null ) {
1012- sb .append (String .format ("&metadata=%s" , metadata ()));
1013- }
1014- if (unrecognized () != null ) {
1015- for (Map .Entry <String , SerializableJsonElement > entry : unrecognized ().entrySet ()) {
924+ appendQueryParameter (sb , "alternatives" , alternatives ());
925+ appendQueryParameter (sb , "overview" , overview ());
926+ appendQueryParameter (sb , "radiuses" , radiuses ());
927+ appendQueryParameter (sb , "steps" , steps ());
928+ appendQueryParameter (sb , "avoid_maneuver_radius" , avoidManeuverRadius ());
929+ appendQueryParameter (sb , "bearings" , bearings ());
930+ appendQueryParameter (sb , "layers" , layers ());
931+ appendQueryParameter (sb , "continue_straight" , continueStraight ());
932+ appendQueryParameter (sb , "annotations" , annotations ());
933+ appendQueryParameter (sb , "language" , language ());
934+ appendQueryParameter (sb , "roundabout_exits" , roundaboutExits ());
935+ appendQueryParameter (sb , "voice_instructions" , voiceInstructions ());
936+ appendQueryParameter (sb , "banner_instructions" , bannerInstructions ());
937+ appendQueryParameter (sb , "voice_units" , voiceUnits ());
938+ appendQueryParameter (sb , "exclude" , exclude ());
939+ appendQueryParameter (sb , "include" , include ());
940+ appendQueryParameter (sb , "approaches" , approaches ());
941+ appendQueryParameter (sb , "waypoints" , waypointIndices ());
942+ appendQueryParameter (sb , "waypoint_names" , waypointNames ());
943+ appendQueryParameter (sb , "waypoint_targets" , waypointTargets ());
944+ appendQueryParameter (sb , "enable_refresh" , enableRefresh ());
945+ appendQueryParameter (sb , "walking_speed" , walkingSpeed ());
946+ appendQueryParameter (sb , "walkway_bias" , walkwayBias ());
947+ appendQueryParameter (sb , "alley_bias" , alleyBias ());
948+ appendQueryParameter (sb , "snapping_include_closures" , snappingIncludeClosures ());
949+ appendQueryParameter (sb , "arrive_by" , arriveBy ());
950+ appendQueryParameter (sb , "depart_at" , departAt ());
951+ appendQueryParameter (sb , "max_height" , maxHeight ());
952+ appendQueryParameter (sb , "max_width" , maxWidth ());
953+ appendQueryParameter (sb , "metadata" , metadata ());
954+
955+ Map <String , SerializableJsonElement > unrecognized = unrecognized ();
956+ if (unrecognized != null ) {
957+ for (Map .Entry <String , SerializableJsonElement > entry : unrecognized .entrySet ()) {
1016958 JsonElement element = entry .getValue ().getElement ();
1017959 if (element .isJsonPrimitive ()) {
1018- sb . append ( String . format ( "&%s=%s" , entry .getKey (), element .getAsString () ));
960+ appendQueryParameter ( sb , entry .getKey (), element .getAsString ());
1019961 } else {
1020962 throw new IllegalStateException (
1021963 String .format (
@@ -1029,20 +971,47 @@ public URL toUrl(@NonNull String accessToken) {
1029971 }
1030972
1031973 try {
1032- URL decodedUrl = new URL (sb .toString ());
1033- URI encodedUri = new URI (
1034- decodedUrl .getProtocol (),
1035- decodedUrl .getUserInfo (),
1036- decodedUrl .getHost (),
1037- decodedUrl .getPort (),
1038- decodedUrl .getPath (),
1039- decodedUrl .getQuery (),
1040- decodedUrl .getRef ()
1041- );
1042- // workaround to encode `&` chars in Strings like "me & you".
1043- // need a better solution to fix encoding in general.
1044- return new URL (encodedUri .toASCIIString ().replace ("%20&%20" , "%20%26%20" ));
1045- } catch (MalformedURLException | URISyntaxException ex ) {
974+ return new URL (sb .toString ());
975+ } catch (MalformedURLException ex ) {
976+ throw new RuntimeException (ex );
977+ }
978+ }
979+
980+ private static void appendQueryParameter (
981+ @ NonNull StringBuilder builder ,
982+ @ NonNull String name ,
983+ @ Nullable Number value ) {
984+ if (value != null ) {
985+ appendQueryParameter (builder , name , String .valueOf (value ));
986+ }
987+ }
988+
989+ private static void appendQueryParameter (
990+ @ NonNull StringBuilder builder ,
991+ @ NonNull String name ,
992+ @ Nullable Boolean value ) {
993+ if (value != null ) {
994+ appendQueryParameter (builder , name , String .valueOf (value ));
995+ }
996+ }
997+
998+ private static void appendQueryParameter (
999+ @ NonNull StringBuilder builder ,
1000+ @ NonNull String name ,
1001+ @ Nullable String value ) {
1002+ if (value != null ) {
1003+ builder
1004+ .append ("&" )
1005+ .append (name )
1006+ .append ("=" )
1007+ .append (escape (value ));
1008+ }
1009+ }
1010+
1011+ private static String escape (@ NonNull String value ) {
1012+ try {
1013+ return URLEncoder .encode (value , UTF_8 );
1014+ } catch (UnsupportedEncodingException ex ) {
10461015 throw new RuntimeException (ex );
10471016 }
10481017 }
@@ -1945,6 +1914,7 @@ public Builder snappingIncludeClosuresList(@Nullable List<Boolean> snappingClosu
19451914 * which are not present in the model yet but are supported on the Directions API,
19461915 * to a URL generated by `RouteOptions#toUrl`.
19471916 * Use it for experimental parameters.
1917+ *
19481918 * @param unrecognizedProperties parameters to add to request
19491919 */
19501920 @ NonNull
0 commit comments