Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ directions-fixtures:
curl "https://api.mapbox.com/directions/v5/mapbox/driving/13.4301,52.5109;13.432507621760521,52.501725088556014?approaches=unrestricted;curb&access_token=$(MAPBOX_ACCESS_TOKEN)" \
-o services-directions/src/test/resources/directions_v5_approaches.json

# Directions: includes waypoint_names
curl "https://api.mapbox.com/directions/v5/mapbox/cycling/-122.42,37.78;-77.03,38.91?steps=true&voice_instructions=true&banner_instructions=true&voice_units=imperial&waypoint_names=Home;Work&access_token=$(MAPBOX_ACCESS_TOKEN)" \
-o services-directions/src/test/resources/directions_v5_waypoint_names.json

mapmatching-fixtures:
curl "https://api.mapbox.com/matching/v5/mapbox/driving/$(MAP_MATCHING_COORDINATES)?geometries=polyline&language=sv&steps=true&access_token=$(MAPBOX_ACCESS_TOKEN)" \
-o services-matching/src/test/resources/map_matching_v5_polyline.json
Expand All @@ -142,6 +146,9 @@ mapmatching-fixtures:
curl "https://api.mapbox.com/matching/v5/mapbox/driving/-117.1728265285492,32.71204416018209;-117.17334151268004,32.71254065549407?approaches=unrestricted;curb&access_token=$(MAPBOX_ACCESS_TOKEN)" \
-o services-matching/src/test/resources/mapmatching_v5_approaches.json

# MapMatching request with waypoint_names:
curl "https://api.mapbox.com/matching/v5/mapbox/driving/2.344003915786743,48.85805170891599;2.346750497817993,48.85727523615161;2.348681688308716,48.85936462637049;2.349550724029541,48.86084691113991;2.349550724029541,48.8608892614883;2.349625825881958,48.86102337068847;2.34982967376709,48.86125629633996?steps=true&tidy=true&waypoints=0;6&waypoint_names=Home;Work&banner_instructions=true&access_token=$(MAPBOX_ACCESS_TOKEN)" \
-o services-matching/src/test/resources/mapmatching_v5_waypoint_names.json

optimization-fixtures:
# request an optimized car trip with no additional options
Expand Down
17 changes: 17 additions & 0 deletions services-core/src/main/java/com/mapbox/core/utils/TextUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,21 @@ public static String formatApproaches(String[] approaches) {
}
return TextUtils.join(";", approaches);
}

/**
* Converts String array with waypoint_names values
* to a string ready for API consumption.
*
* @param waypointNames a string representing approaches to each coordinate.
* @return a formatted string.
* @since 3.3.0
*/
public static String formatWaypointNames(String[] waypointNames) {
for (int i = 0; i < waypointNames.length; i++) {
if (waypointNames[i] == null) {
waypointNames[i] = "";
}
}
return TextUtils.join(";", waypointNames);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ public interface DirectionsService {
* useful for navigation
* @param voiceUnits voice units
* @param exclude exclude tolls, motorways or more along your route
* @param approaches which side of the road to approach a waypoint.
* @param approaches which side of the road to approach a waypoint
* @param waypointNames custom names for waypoints used for the arrival instruction.
* @return the {@link DirectionsResponse} in a Call wrapper
* @since 1.0.0
*/
Expand All @@ -70,6 +71,7 @@ Call<DirectionsResponse> getCall(
@Query("banner_instructions") Boolean bannerInstructions,
@Query("voice_units") String voiceUnits,
@Query("exclude") String exclude,
@Query("approaches") String approaches
@Query("approaches") String approaches,
@Query("waypoint_names") String waypointNames
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ protected Call<DirectionsResponse> initializeCall() {
bannerInstructions(),
voiceUnits(),
exclude(),
approaches());
approaches(),
waypointNames());
}

@Override
Expand Down Expand Up @@ -204,6 +205,7 @@ private List<DirectionsRoute> generateRouteOptions(Response<DirectionsResponse>
RouteOptions.builder()
.profile(profile())
.coordinates(coordinates())
.waypointNames(waypointNames())
.continueStraight(continueStraight())
.annotations(annotation())
.approaches(approaches())
Expand Down Expand Up @@ -304,6 +306,9 @@ private static String formatCoordinates(List<Point> coordinates) {
@Nullable
abstract String approaches();

@Nullable
abstract String waypointNames();

/**
* Build a new {@link MapboxDirections} object with the initial values set for
* {@link #baseUrl()}, {@link #profile()}, {@link #user()}, and {@link #geometries()}.
Expand Down Expand Up @@ -352,6 +357,7 @@ public abstract static class Builder {
private Point destination;
private Point origin;
private String[] approaches;
private String[] waypointNames;

/**
* The username for the account that the directions engine runs on. In most cases, this should
Expand Down Expand Up @@ -707,6 +713,22 @@ public Builder addApproaches(String... approaches) {

abstract Builder approaches(@Nullable String approaches);

/**
* Custom names for waypoints used for the arrival instruction,
* each separated by ; . Values can be any string and total number of all characters cannot
* exceed 500. If provided, the list of waypointNames must be the same length as the list of
* coordinates, but you can skip a coordinate and show its position with the ; separator.
* @param waypointNames Custom names for waypoints used for the arrival instruction.
* @return this builder for chaining options together
* @since 3.3.0
*/
public Builder addWaypointNames(@Nullable String... waypointNames) {
this.waypointNames = waypointNames;
return this;
}

abstract Builder waypointNames(@Nullable String waypointNames);

abstract MapboxDirections autoBuild();

/**
Expand All @@ -730,6 +752,18 @@ public MapboxDirections build() {
+ " directions API request.");
}

if (waypointNames != null) {
if (waypointNames.length != coordinates.size()) {
throw new ServicesException("Number of waypoint names must match "
+ " the number of waypoints provided.");
}
final String waypointNamesStr = TextUtils.formatWaypointNames(waypointNames);
if (!waypointNamesStr.isEmpty() && waypointNamesStr.length() > 500) {
throw new ServicesException("Waypoint names exceed 500 character limit.");
}
waypointNames(waypointNamesStr);
}

if (approaches != null) {
if (approaches.length != coordinates.size()) {
throw new ServicesException("Number of approach elements must match "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,18 @@ public static Builder builder() {
@Nullable
public abstract String approaches();

/**
* Custom names for waypoints used for the arrival instruction in banners and voice instructions,
* each separated by ; . Values can be any string and total number of all characters cannot
* exceed 500. If provided, the list of waypoint_names must be the same length as the list of
* coordinates, but you can skip a coordinate and show its position with the ; separator.
* @return a string representing names for each waypoint
* @since 3.3.0
*/
@Nullable
public abstract String waypointNames();


/**
* Gson type adapter for parsing Gson to this class.
*
Expand Down Expand Up @@ -486,6 +498,17 @@ public abstract Builder overview(
@Nullable
public abstract Builder approaches(String approaches);

/**
* The same approaches the user originally made when the request was made.
*
* @param waypointNames unrestricted, curb or omitted (;)
* @return this builder for chaining options together
* @since 3.3.0
*/

@Nullable
public abstract Builder waypointNames(@Nullable String waypointNames);

/**
* Builds a new instance of the {@link RouteOptions} object.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import static com.mapbox.api.directions.v5.DirectionsCriteria.APPROACH_CURB;
import static com.mapbox.api.directions.v5.DirectionsCriteria.APPROACH_UNRESTRICTED;
import static com.mapbox.api.directions.v5.DirectionsCriteria.GEOMETRY_POLYLINE;
import static com.mapbox.api.directions.v5.DirectionsCriteria.PROFILE_CYCLING;
import static com.mapbox.api.directions.v5.DirectionsCriteria.PROFILE_DRIVING;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.Matchers.startsWith;
Expand All @@ -52,6 +53,7 @@ public class MapboxDirectionsTest extends TestUtils {
private static final String DIRECTIONS_V5_MAX_SPEED_ANNOTATION = "directions_v5_max_speed_annotation.json";
private static final String DIRECTIONS_V5_BANNER_INSTRUCTIONS = "directions_v5_banner_instructions.json";
private static final String DIRECTIONS_V5_APPROACHES_REQUEST = "directions_v5_approaches.json";
private static final String DIRECTIONS_V5_WAYPOINT_NAMES_FIXTURE = "directions_v5_waypoint_names.json";

private MockWebServer server;
private HttpUrl mockUrl;
Expand All @@ -70,7 +72,9 @@ public MockResponse dispatch(RecordedRequest request) throws InterruptedExceptio
resource = DIRECTIONS_ROTARY_FIXTURE;
} else if (request.getPath().contains("annotations")) {
resource = DIRECTIONS_V5_ANNOTATIONS_FIXTURE;
} else if (request.getPath().contains("approaches")) {
} else if (request.getPath().contains("waypoint_names")) {
resource = DIRECTIONS_V5_WAYPOINT_NAMES_FIXTURE;
}else if (request.getPath().contains("approaches")) {
resource = DIRECTIONS_V5_APPROACHES_REQUEST;
} else if (request.getPath().contains("-151.2302")) {
resource = DIRECTIONS_V5_NO_ROUTE;
Expand Down Expand Up @@ -575,6 +579,7 @@ public void sanityApproachesInstructions() throws Exception {
assertTrue(mapboxDirections.cloneCall().request().url().toString()
.contains("approaches=unrestricted;;;curb"));
}

@Test
public void build_exceptionThrownWhenNumApproachesDoesNotMatchCoordinates() throws Exception {
thrown.expect(ServicesException.class);
Expand Down Expand Up @@ -637,4 +642,88 @@ public void testRouteOptionsApproaches() throws Exception {

assertEquals("unrestricted;curb", routeOptions.approaches());
}

@Test
public void sanityWaypointNamesInstructions() throws Exception {
MapboxDirections mapboxDirections = MapboxDirections.builder()
.origin(Point.fromLngLat(1.0, 1.0))
.addWaypoint(Point.fromLngLat(2.0, 2.0))
.destination(Point.fromLngLat(4.0, 4.0))
.addWaypointNames("Home", "Store", "Work")
.baseUrl("https://foobar.com")
.accessToken(ACCESS_TOKEN)
.build();
assertNotNull(mapboxDirections);
assertTrue(mapboxDirections.cloneCall().request().url().toString()
.contains("waypoint_names=Home;Store;Work"));
}

@Test
public void build_exceptionThrownWhenWaypointNamesDoNotMatchCoordinates() throws Exception {
thrown.expect(ServicesException.class);
thrown.expectMessage(
startsWith("Number of waypoint names must match"));
MapboxDirections mapboxDirections = MapboxDirections.builder()
.origin(Point.fromLngLat(2.0, 2.0))
.addWaypoint(Point.fromLngLat(2.0, 2.0))
.addWaypoint(Point.fromLngLat(3.0, 3.0))
.destination(Point.fromLngLat(4.0, 4.0))
.addWaypointNames("Home", "Work")
.baseUrl("https://foobar.com")
.accessToken(ACCESS_TOKEN)
.build();
}

@Test
public void build_exceptionThrownWhenWaypointNamesExceedLimit() throws Exception {
thrown.expect(ServicesException.class);
thrown.expectMessage(
startsWith("Waypoint names exceed 500 character limit"));

StringBuffer longWpName = new StringBuffer();
for (int i = 0; i < 124; i++) {
longWpName.append("Home");
}
MapboxDirections mapboxDirections = MapboxDirections.builder()
.origin(Point.fromLngLat(2.0, 2.0))
.destination(Point.fromLngLat(4.0, 4.0))
.addWaypointNames(longWpName.toString(), "Work")
.baseUrl("https://foobar.com")
.accessToken(ACCESS_TOKEN)
.build();

assertTrue(mapboxDirections.cloneCall().request().url().toString()
.contains("waypoint_names=Home"));

// one more char results in exception
mapboxDirections = MapboxDirections.builder()
.origin(Point.fromLngLat(2.0, 2.0))
.destination(Point.fromLngLat(4.0, 4.0))
.addWaypointNames(longWpName.toString(), "Work1")
.baseUrl("https://foobar.com")
.accessToken(ACCESS_TOKEN)
.build();
}

@Test
public void testWithWaypointNames() throws Exception {

MapboxDirections mapboxDirections = MapboxDirections.builder()
.profile(PROFILE_CYCLING)
.origin(Point.fromLngLat(-122.42,37.78))
.destination(Point.fromLngLat(-77.03,38.91))
.steps(true)
.voiceInstructions(true)
.voiceUnits(DirectionsCriteria.IMPERIAL)
.addWaypointNames("Home", "Work")
.accessToken(ACCESS_TOKEN)
.baseUrl(mockUrl.toString())
.build();

mapboxDirections.setCallFactory(null);
Response<DirectionsResponse> response = mapboxDirections.executeCall();
assertEquals(200, response.code());
assertEquals("Ok", response.body().code());
}

}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public interface MapMatchingService {
* marked-up text for voice guidance along the route.
* @param voiceUnits voice units
* @param waypoints Which input coordinates should be treated as waypoints.
* @param waypointNames wustom names for waypoints used for the arrival instruction.
* @param approaches which side of the road to approach a waypoint.
* @return the MapMatchingResponse in a Call wrapper
* @since 2.0.0
Expand All @@ -81,5 +82,6 @@ Call<MapMatchingResponse> getCall(
@Query("voice_instructions") Boolean voiceInstructions,
@Query("voice_units") String voiceUnits,
@Query("waypoints") String waypoints,
@Query("waypoint_names") String waypointNames,
@Query("approaches") String approaches);
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ protected Call<MapMatchingResponse> initializeCall() {
voiceInstructions(),
voiceUnits(),
waypoints(),
waypointNames(),
approaches());
}

Expand Down Expand Up @@ -222,6 +223,7 @@ private List<MapMatchingMatching> generateRouteOptions(Response<MapMatchingRespo
.requestUuid(PLACEHOLDER_UUID)
.accessToken(accessToken())
.approaches(approaches())
.waypointNames(waypointNames())
.baseUrl(baseUrl())
.build()
).build());
Expand Down Expand Up @@ -296,6 +298,9 @@ private static List<Point> formatCoordinates(String coordinates) {
@Nullable
abstract String waypoints();

@Nullable
abstract String waypointNames();

@Nullable
abstract String approaches();

Expand Down Expand Up @@ -331,6 +336,7 @@ public abstract static class Builder {
private String[] timestamps;
private Double[] radiuses;
private Integer[] waypoints;
private String[] waypointNames;
private String[] approaches;

/**
Expand Down Expand Up @@ -648,6 +654,23 @@ public Builder addApproaches(@Nullable String... approaches) {

abstract Builder approaches(@Nullable String approaches);

/**
* Custom names for waypoints used for the arrival instruction,
* each separated by ; . Values can be any string and total number of all characters cannot
* exceed 500. If provided, the list of waypointNames must be the same length as the list of
* waypoints, but you can skip a coordinate and show its position with the ; separator.
*
* @param waypointNames Custom names for waypoints used for the arrival instruction.
* @returnthis builder for chaining options together
* @since 3.3.0
*/
public Builder addWaypointNames(@Nullable String... waypointNames) {
this.waypointNames = waypointNames;
return this;
}

abstract Builder waypointNames(@Nullable String waypointNames);

/**
* Optionally change the APIs base URL to something other then the default Mapbox one.
*
Expand Down Expand Up @@ -707,6 +730,17 @@ public MapboxMapMatching build() {
}
}

if (waypointNames != null) {
if (waypointNames.length != waypoints.length) {
throw new ServicesException("Number of waypoint names must match "
+ " the number of waypoints provided.");
}
final String waypointNamesStr = TextUtils.formatWaypointNames(waypointNames);
if (!waypointNamesStr.isEmpty() && waypointNamesStr.length() > 500) {
throw new ServicesException("Waypoint names exceed 500 character limit.");
}
waypointNames(waypointNamesStr);
}

if (approaches != null) {
if (approaches.length != coordinates.size()) {
Expand Down
Loading