Skip to content

Commit 41d4675

Browse files
authored
snapping closures (#1232)
1 parent ee9a113 commit 41d4675

6 files changed

Lines changed: 320 additions & 5 deletions

File tree

services-directions-models/src/main/java/com/mapbox/api/directions/v5/models/RouteOptions.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,36 @@ public List<Point> waypointTargetsList() {
493493
@Nullable
494494
public abstract WalkingOptions walkingOptions();
495495

496+
/**
497+
* A semicolon-separated list of booleans affecting snapping of waypoint locations to road
498+
* segments.
499+
* If true, road segments closed due to live-traffic closures will be considered for snapping.
500+
* If false, they will not be considered for snapping.
501+
* If provided, the number of snappingClosures must be the same as the number of
502+
* coordinates.
503+
* Must be used with {@link DirectionsCriteria#PROFILE_DRIVING_TRAFFIC}
504+
*
505+
* @return a String representing a list of booleans
506+
*/
507+
@SerializedName("snapping_closures")
508+
@Nullable
509+
public abstract String snappingClosures();
510+
511+
/**
512+
* A list of booleans affecting snapping of waypoint locations to road segments.
513+
* If true, road segments closed due to live-traffic closures will be considered for snapping.
514+
* If false, they will not be considered for snapping.
515+
* If provided, the number of snappingClosures must be the same as the number of
516+
* coordinates.
517+
* Must be used with {@link DirectionsCriteria#PROFILE_DRIVING_TRAFFIC}
518+
*
519+
* @return a list of booleans
520+
*/
521+
@Nullable
522+
public List<Boolean> snappingClosuresList() {
523+
return ParseUtils.parseToBooleans(snappingClosures());
524+
}
525+
496526
/**
497527
* Gson type adapter for parsing Gson to this class.
498528
*
@@ -1029,6 +1059,45 @@ public Builder waypointTargetsList(@NonNull List<Point> waypointTargets) {
10291059
*/
10301060
public abstract Builder walkingOptions(@NonNull WalkingOptions walkingOptions);
10311061

1062+
/**
1063+
* A semicolon-separated list of booleans affecting snapping of waypoint locations to road
1064+
* segments.
1065+
* If true, road segments closed due to live-traffic closures will be considered for snapping.
1066+
* If false, they will not be considered for snapping.
1067+
* If provided, the number of snappingClosures must be the same as the number of
1068+
* coordinates.
1069+
* You can skip a coordinate and show its position in the list with the ; separator.
1070+
* If unspecified, this parameter defaults to false.
1071+
* Must be used with {@link DirectionsCriteria#PROFILE_DRIVING_TRAFFIC}
1072+
*
1073+
* @param snappingClosures a semicolon-separated list of booleans
1074+
* @return this builder for chaining options together
1075+
*/
1076+
public abstract Builder snappingClosures(@NonNull String snappingClosures);
1077+
1078+
/**
1079+
* A list of booleans affecting snapping of waypoint locations to road segments.
1080+
* If true, road segments closed due to live-traffic closures will be considered for snapping.
1081+
* If false, they will not be considered for snapping.
1082+
* If provided, the number of snappingClosures must be the same as the number of
1083+
* coordinates.
1084+
* You can skip a coordinate and show its position in the list with null value.
1085+
* If unspecified, this parameter defaults to false.
1086+
* Must be used with {@link DirectionsCriteria#PROFILE_DRIVING_TRAFFIC}
1087+
*
1088+
* @param snappingClosures a list of booleans
1089+
* @return this builder for chaining options together
1090+
*/
1091+
public Builder snappingClosures(@NonNull List<Boolean> snappingClosures) {
1092+
String result = FormatUtils.join(";", snappingClosures);
1093+
if (result != null) {
1094+
snappingClosures(result);
1095+
} else {
1096+
snappingClosures("");
1097+
}
1098+
return this;
1099+
}
1100+
10321101
/**
10331102
* Builds a new instance of the {@link RouteOptions} object.
10341103
*

services-directions-models/src/main/java/com/mapbox/api/directions/v5/utils/ParseUtils.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ public class ParseUtils {
1414
private static final String SEMICOLON = ";";
1515
private static final String COMMA = ",";
1616
private static final String UNLIMITED = "unlimited";
17+
private static final String TRUE = "true";
18+
private static final String FALSE = "false";
1719

1820
/**
1921
* Parse a String to a list of Integers.
@@ -165,4 +167,39 @@ public static List<List<Double>> parseToListOfListOfDoubles(@Nullable String ori
165167

166168
return result;
167169
}
170+
171+
/**
172+
* Parse a String to a list of Boolean.
173+
*
174+
* @param original an original String.
175+
* @return List of Booleans
176+
*/
177+
@Nullable
178+
public static List<Boolean> parseToBooleans(@Nullable String original) {
179+
if (original == null) {
180+
return null;
181+
}
182+
183+
List<Boolean> booleans = new ArrayList<>();
184+
if (original.isEmpty()) {
185+
return booleans;
186+
}
187+
188+
String[] strings = original.split(SEMICOLON, -1);
189+
for (String str : strings) {
190+
if (str != null) {
191+
if (str.isEmpty()) {
192+
booleans.add(null);
193+
} else if (str.equalsIgnoreCase(TRUE)) {
194+
booleans.add(true);
195+
} else if (str.equalsIgnoreCase(FALSE)) {
196+
booleans.add(false);
197+
} else {
198+
booleans.add(null);
199+
}
200+
}
201+
}
202+
203+
return booleans;
204+
}
168205
}

services-directions-models/src/test/java/com/mapbox/api/directions/v5/models/RouteOptionsTest.java

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.mapbox.geojson.Point;
44
import java.util.ArrayList;
55
import java.util.List;
6+
import static org.junit.Assert.assertTrue;
67
import org.junit.Test;
78

89
import static com.mapbox.api.directions.v5.DirectionsCriteria.ANNOTATION_CONGESTION;
@@ -17,7 +18,7 @@
1718
public class RouteOptionsTest {
1819

1920
private static final String ROUTE_OPTIONS_JSON =
20-
"{\"baseUrl\":\"https://api.mapbox.com\",\"user\":\"mapbox\",\"profile\":\"driving-traffic\",\"coordinates\":[[-122.4003312,37.7736941],[-122.4187529,37.7689715],[-122.4255172,37.7775835]],\"alternatives\":false,\"language\":\"ru\",\"radiuses\":\";unlimited;100\",\"bearings\":\"0,90;90,0;\",\"continue_straight\":false,\"roundabout_exits\":false,\"geometries\":\"polyline6\",\"overview\":\"full\",\"steps\":true,\"annotations\":\"congestion,distance,duration\",\"exclude\":\"toll\",\"voice_instructions\":true,\"banner_instructions\":true,\"voice_units\":\"metric\",\"access_token\":\"token\",\"uuid\":\"12345543221\",\"approaches\":\";curb;\",\"waypoints\":\"0;1;2\",\"waypoint_names\":\";two;\",\"waypoint_targets\":\";12.2,21.2;\"}";
21+
"{\"baseUrl\":\"https://api.mapbox.com\",\"user\":\"mapbox\",\"profile\":\"driving-traffic\",\"coordinates\":[[-122.4003312,37.7736941],[-122.4187529,37.7689715],[-122.4255172,37.7775835]],\"alternatives\":false,\"language\":\"ru\",\"radiuses\":\";unlimited;100\",\"bearings\":\"0,90;90,0;\",\"continue_straight\":false,\"roundabout_exits\":false,\"geometries\":\"polyline6\",\"overview\":\"full\",\"steps\":true,\"annotations\":\"congestion,distance,duration\",\"exclude\":\"toll\",\"voice_instructions\":true,\"banner_instructions\":true,\"voice_units\":\"metric\",\"access_token\":\"token\",\"uuid\":\"12345543221\",\"approaches\":\";curb;\",\"waypoints\":\"0;1;2\",\"waypoint_names\":\";two;\",\"waypoint_targets\":\";12.2,21.2;\",\"snapping_closures\":\";false;true\"}";
2122

2223
@Test
2324
public void toBuilder() {
@@ -328,6 +329,79 @@ public void annotationsList() {
328329
assertEquals("congestion,distance,maxspeed,speed", routeOptions.annotations());
329330
}
330331

332+
@Test
333+
public void snappingClosuresString() {
334+
String snappingClosuresString = "true;;;false;false;true;;;;" ;
335+
336+
RouteOptions routeOptions = routeOptions()
337+
.toBuilder()
338+
.snappingClosures(snappingClosuresString)
339+
.build();
340+
341+
assertEquals(snappingClosuresString, routeOptions.snappingClosures());
342+
343+
List<Boolean> snappingClosures = routeOptions.snappingClosuresList();
344+
assertEquals(10, snappingClosures.size());
345+
assertEquals(true, snappingClosures.get(0));
346+
assertEquals(null, snappingClosures.get(1));
347+
assertEquals(null, snappingClosures.get(2));
348+
assertEquals(false, snappingClosures.get(3));
349+
assertEquals(false, snappingClosures.get(4));
350+
assertEquals(true, snappingClosures.get(5));
351+
assertEquals(null, snappingClosures.get(6));
352+
assertEquals(null, snappingClosures.get(7));
353+
assertEquals(null, snappingClosures.get(8));
354+
assertEquals(null, snappingClosures.get(9));
355+
}
356+
357+
@Test
358+
public void snappingClosuresEmptyString() {
359+
String snappingClosuresString = "" ;
360+
361+
RouteOptions routeOptions = routeOptions()
362+
.toBuilder()
363+
.snappingClosures(snappingClosuresString)
364+
.build();
365+
366+
assertEquals(snappingClosuresString, routeOptions.snappingClosures());
367+
368+
List<Boolean> snappingClosures = routeOptions.snappingClosuresList();
369+
assertTrue(snappingClosures.isEmpty());
370+
}
371+
372+
@Test
373+
public void snappingClosuresList() {
374+
List<Boolean> snappingClosures = new ArrayList<>();
375+
snappingClosures.add(false);
376+
snappingClosures.add(false);
377+
snappingClosures.add(null);
378+
snappingClosures.add(true);
379+
snappingClosures.add(false);
380+
snappingClosures.add(null);
381+
snappingClosures.add(null);
382+
383+
RouteOptions routeOptions = routeOptions()
384+
.toBuilder()
385+
.snappingClosures(snappingClosures)
386+
.build();
387+
388+
assertEquals(snappingClosures, routeOptions.snappingClosuresList());
389+
assertEquals("false;false;;true;false;;", routeOptions.snappingClosures());
390+
}
391+
392+
@Test
393+
public void snappingClosuresEmptyList() {
394+
List<Boolean> snappingClosures = new ArrayList<>();
395+
396+
RouteOptions routeOptions = routeOptions()
397+
.toBuilder()
398+
.snappingClosures(snappingClosures)
399+
.build();
400+
401+
assertEquals(snappingClosures, routeOptions.snappingClosuresList());
402+
assertTrue(routeOptions.snappingClosures().isEmpty());
403+
}
404+
331405
@Test
332406
public void baseUrlIsValid_fromJson() {
333407
RouteOptions routeOptions = RouteOptions.fromJson(ROUTE_OPTIONS_JSON);
@@ -571,6 +645,24 @@ public void waypointTargetsListIsValid_fromJson() {
571645
assertEquals(null, options.waypointTargetsList().get(2));
572646
}
573647

648+
@Test
649+
public void snappingIncludeClosuresStringIsValid_fromJson() {
650+
RouteOptions options = RouteOptions.fromJson(ROUTE_OPTIONS_JSON);
651+
652+
assertEquals(";false;true", options.snappingClosures());
653+
}
654+
655+
@Test
656+
public void snappingIncludeClosuresListIsValid_fromJson() {
657+
RouteOptions options = RouteOptions.fromJson(ROUTE_OPTIONS_JSON);
658+
659+
List list = options.snappingClosuresList();
660+
assertEquals(3, list.size());
661+
assertEquals(null, list.get(0));
662+
assertEquals(false, list.get(1));
663+
assertEquals(true, list.get(2));
664+
}
665+
574666
@Test
575667
public void routeOptions_toJson() {
576668
RouteOptions options = routeOptions();
@@ -742,6 +834,7 @@ private RouteOptions routeOptions() {
742834
.waypointIndices("0;1;2")
743835
.waypointNames(";two;")
744836
.waypointTargets(";12.2,21.2;")
837+
.snappingClosures(";false;true")
745838
.build();
746839
}
747840
}

services-directions/src/main/java/com/mapbox/api/directions/v5/DirectionsService.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ public interface DirectionsService {
5959
* @param walkwayBias a factor that modifies the cost when encountering roads or paths
6060
* that do not allow vehicles and are set aside for pedestrian use
6161
* @param alleyBias a factor that modifies the cost when alleys are encountered
62+
* @param snappingClosures a list of booleans affecting snapping of waypoint locations to road
63+
* segments
6264
* @return the {@link DirectionsResponse} in a Call wrapper
6365
* @since 1.0.0
6466
*/
@@ -90,7 +92,8 @@ Call<DirectionsResponse> getCall(
9092
@Query("enable_refresh") Boolean enableRefresh,
9193
@Query("walking_speed") Double walkingSpeed,
9294
@Query("walkway_bias") Double walkwayBias,
93-
@Query("alley_bias") Double alleyBias
95+
@Query("alley_bias") Double alleyBias,
96+
@Query("snapping_include_closures") String snappingClosures
9497
);
9598

9699
/**
@@ -134,6 +137,8 @@ Call<DirectionsResponse> getCall(
134137
* @param walkwayBias a factor that modifies the cost when encountering roads or paths
135138
* that do not allow vehicles and are set aside for pedestrian use
136139
* @param alleyBias a factor that modifies the cost when alleys are encountered
140+
* @param snappingClosures a list of booleans affecting snapping of waypoint locations to road
141+
* segments
137142
* @return the {@link DirectionsResponse} in a Call wrapper
138143
* @since 4.6.0
139144
*/
@@ -166,6 +171,7 @@ Call<DirectionsResponse> postCall(
166171
@Field("enable_refresh") Boolean enableRefresh,
167172
@Field("walking_speed") Double walkingSpeed,
168173
@Field("walkway_bias") Double walkwayBias,
169-
@Field("alley_bias") Double alleyBias
174+
@Field("alley_bias") Double alleyBias,
175+
@Field("snapping_include_closures") String snappingClosures
170176
);
171177
}

services-directions/src/main/java/com/mapbox/api/directions/v5/MapboxDirections.java

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ private Call<DirectionsResponse> get() {
111111
enableRefresh(),
112112
walkingSpeed(),
113113
walkwayBias(),
114-
alleyBias()
114+
alleyBias(),
115+
snappingClosures()
115116
);
116117
}
117118

@@ -143,7 +144,8 @@ private Call<DirectionsResponse> post() {
143144
enableRefresh(),
144145
walkingSpeed(),
145146
walkwayBias(),
146-
alleyBias()
147+
alleyBias(),
148+
snappingClosures()
147149
);
148150
}
149151

@@ -338,6 +340,9 @@ Double alleyBias() {
338340
return walkingOptions().alleyBias();
339341
}
340342

343+
@Nullable
344+
abstract String snappingClosures();
345+
341346
private boolean hasWalkingOptions() {
342347
return walkingOptions() != null;
343348
}
@@ -393,6 +398,7 @@ public abstract static class Builder {
393398
private List<Integer> waypointIndices = new ArrayList<>();
394399
private List<String> waypointNames = new ArrayList<>();
395400
private List<Point> waypointTargets = new ArrayList<>();
401+
private List<Boolean> snappingClosures = new ArrayList<>();
396402

397403
/**
398404
* The username for the account that the directions engine runs on. In most cases, this should
@@ -1040,6 +1046,25 @@ public Builder waypointTargets(@NonNull List<Point> waypointTargets) {
10401046

10411047
abstract Builder waypointTargets(@Nullable String waypointTargets);
10421048

1049+
/**
1050+
* A list of booleans affecting snapping of waypoint locations to road segments.
1051+
* If true, road segments closed due to live-traffic closures will be considered for snapping.
1052+
* If false, they will not be considered for snapping.
1053+
* If provided, the number of snappingClosures must be the same as the number of
1054+
* coordinates.
1055+
* You can skip a coordinate and show its position in the list with null value.
1056+
* Must be used with {@link DirectionsCriteria#PROFILE_DRIVING_TRAFFIC}
1057+
*
1058+
* @param snappingClosures a list of booleans
1059+
* @return this builder for chaining options together
1060+
*/
1061+
public Builder snappingClosures(@NonNull List<Boolean> snappingClosures) {
1062+
this.snappingClosures = snappingClosures;
1063+
return this;
1064+
}
1065+
1066+
abstract Builder snappingClosures(@Nullable String snappingClosures);
1067+
10431068
/**
10441069
* A point to specify drop-off locations that are distinct from the locations specified in
10451070
* coordinates.
@@ -1169,6 +1194,14 @@ public MapboxDirections build() {
11691194
approaches(formattedApproaches);
11701195
}
11711196

1197+
if (!snappingClosures.isEmpty()) {
1198+
if (snappingClosures.size() != coordinates.size()) {
1199+
throw new ServicesException("Number of snapping closures elements must match "
1200+
+ "number of coordinates provided.");
1201+
}
1202+
snappingClosures(FormatUtils.join(";", snappingClosures));
1203+
}
1204+
11721205
coordinates(coordinates);
11731206
bearing(FormatUtils.formatBearings(bearings));
11741207
annotation(FormatUtils.join(",", annotations));

0 commit comments

Comments
 (0)