From e42752f7af776ae33b74640975535d7abce52850 Mon Sep 17 00:00:00 2001 From: Andrew Janke Date: Sat, 7 Jul 2018 03:00:45 -0400 Subject: [PATCH] Add non-stopover Waypoint support. --- .../com/google/maps/DirectionsApiRequest.java | 122 +++++++++++++++--- .../com/google/maps/DirectionsApiTest.java | 49 +++++++ 2 files changed, 151 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/google/maps/DirectionsApiRequest.java b/src/main/java/com/google/maps/DirectionsApiRequest.java index a94a858ef..7ce4bf294 100644 --- a/src/main/java/com/google/maps/DirectionsApiRequest.java +++ b/src/main/java/com/google/maps/DirectionsApiRequest.java @@ -16,6 +16,7 @@ package com.google.maps; import static com.google.maps.internal.StringJoin.join; +import static java.util.Objects.requireNonNull; import com.google.maps.model.DirectionsResult; import com.google.maps.model.LatLng; @@ -35,7 +36,7 @@ public DirectionsApiRequest(GeoApiContext context) { } protected boolean optimizeWaypoints; - protected String[] waypoints; + protected Waypoint[] waypoints; @Override protected void validateRequest() { @@ -58,8 +59,8 @@ protected void validateRequest() { /** * The address or textual latitude/longitude value from which you wish to calculate directions. If - * you pass an address as a string, the Directions service will geocode the string and convert it - * to a latitude/longitude coordinate to calculate directions. If you pass coordinates, ensure + * you pass an address as a location, the Directions service will geocode the location and convert + * it to a latitude/longitude coordinate to calculate directions. If you pass coordinates, ensure * that no space exists between the latitude and longitude values. * * @param origin The starting location for the Directions request. @@ -71,8 +72,8 @@ public DirectionsApiRequest origin(String origin) { /** * The address or textual latitude/longitude value from which you wish to calculate directions. If - * you pass an address as a string, the Directions service will geocode the string and convert it - * to a latitude/longitude coordinate to calculate directions. If you pass coordinates, ensure + * you pass an address as a location, the Directions service will geocode the location and convert + * it to a latitude/longitude coordinate to calculate directions. If you pass coordinates, ensure * that no space exists between the latitude and longitude values. * * @param destination The ending location for the Directions request. @@ -166,9 +167,9 @@ public DirectionsApiRequest departureTime(ReadableInstant time) { } /** - * Specifies a list of waypoints. Waypoints alter a route by routing it through the specified + * Specifies a list of waypoints. Waypoints alter a route by routing it through the specified * * location(s). A waypoint is specified as either a latitude/longitude coordinate or as an address - * which will be geocoded. Waypoints are only supported for driving, walking and bicycling + * * which will be geocoded. Waypoints are only supported for driving, walking and bicycling * * directions. * *

For more information on waypoints, see See {@link #waypoints(Waypoint...)}. + * + * @param waypoints The waypoints to add to this directions request. + * @return Returns this {@code DirectionsApiRequest} for call chaining. + */ + public DirectionsApiRequest waypoints(String... waypoints) { + Waypoint[] objWaypoints = new Waypoint[waypoints.length]; + for (int i = 0; i < waypoints.length; i++) { + objWaypoints[i] = new Waypoint(waypoints[i]); } + return waypoints(objWaypoints); } /** * The list of waypoints as latitude/longitude locations. * + *

See {@link #waypoints(Waypoint...)}. + * * @param waypoints The waypoints to add to this directions request. * @return Returns this {@code DirectionsApiRequest} for call chaining. */ public DirectionsApiRequest waypoints(LatLng... waypoints) { - if (waypoints == null) { - return this; + Waypoint[] objWaypoints = new Waypoint[waypoints.length]; + for (int i = 0; i < waypoints.length; i++) { + objWaypoints[i] = new Waypoint(waypoints[i]); } - int length = waypoints.length; - String[] waypointStrings = new String[length]; - for (int i = 0; i < length; i++) { - waypointStrings[i] = waypoints[i].toString(); - } - return waypoints(waypointStrings); + return waypoints(objWaypoints); } /** @@ -271,4 +291,66 @@ public DirectionsApiRequest transitRoutingPreference(TransitRoutingPreference pr public DirectionsApiRequest trafficModel(TrafficModel trafficModel) { return param("traffic_model", trafficModel); } + + public static class Waypoint { + /** The location of this waypoint, expressed as an API-recognized location. */ + private String location; + /** Whether this waypoint is a stopover waypoint. */ + private boolean isStopover; + + /** + * Constructs a stopover Waypoint using a String address. + * + * @param location Any address or location recognized by the Google Maps API. + */ + public Waypoint(String location) { + this(location, true); + } + + /** + * Constructs a Waypoint using a String address. + * + * @param location Any address or location recognized by the Google Maps API. + * @param isStopover Whether this waypoint is a stopover waypoint. + */ + public Waypoint(String location, boolean isStopover) { + requireNonNull(location, "address may not be null"); + this.location = location; + this.isStopover = isStopover; + } + + /** + * Constructs a stopover Waypoint using a Latlng location. + * + * @param location The LatLng coordinates of this waypoint. + */ + public Waypoint(LatLng location) { + this(location, true); + } + + /** + * Constructs a Waypoint using a LatLng location. + * + * @param location The LatLng coordinates of this waypoint. + * @param isStopover Whether this waypoint is a stopover waypoint. + */ + public Waypoint(LatLng location, boolean isStopover) { + requireNonNull(location, "location may not be null"); + this.location = location.toString(); + this.isStopover = isStopover; + } + + /** + * Gets the String representation of this Waypoint, as an API request parameter fragment. + * + * @return The HTTP parameter fragment representing this waypoint. + */ + public String toString() { + if (isStopover) { + return location; + } else { + return "via:" + location; + } + } + } } diff --git a/src/test/java/com/google/maps/DirectionsApiTest.java b/src/test/java/com/google/maps/DirectionsApiTest.java index e2c2a658a..1c3078d22 100644 --- a/src/test/java/com/google/maps/DirectionsApiTest.java +++ b/src/test/java/com/google/maps/DirectionsApiTest.java @@ -226,6 +226,30 @@ public void testBostonToConcordViaCharlestownAndLexington() throws Exception { } } + /** + * Boston to Concord, via Charlestown and Lexington, using non-stopover waypoints. + * + *

{@code + * http://maps.googleapis.com/maps/api/directions/json?origin=Boston,MA&destination=Concord,MA&waypoints=via:Charlestown,MA|via:Lexington,MA} + */ + @Test + public void testBostonToConcordViaCharlestownAndLexingtonNonStopover() throws Exception { + try (LocalTestServerContext sc = + new LocalTestServerContext("{\"routes\": [{}],\"status\": \"OK\"}")) { + DirectionsApi.newRequest(sc.context) + .origin("Boston,MA") + .destination("Concord,MA") + .waypoints( + new DirectionsApiRequest.Waypoint("Charlestown,MA", false), + new DirectionsApiRequest.Waypoint("Lexington,MA", false)) + .await(); + + sc.assertParamValue("Boston,MA", "origin"); + sc.assertParamValue("Concord,MA", "destination"); + sc.assertParamValue("via:Charlestown,MA|via:Lexington,MA", "waypoints"); + } + } + /** * Boston to Concord, via Charlestown and Lexington, but using exact latitude and longitude * coordinates for the waypoints. @@ -249,6 +273,31 @@ public void testBostonToConcordViaCharlestownAndLexingtonLatLng() throws Excepti } } + /** + * Boston to Concord, via Charlestown and Lexington, but using exact latitude and longitude + * coordinates for the waypoints, using non-stopover waypoints. + * + *

{@code + * http://maps.googleapis.com/maps/api/directions/json?origin=Boston,MA&destination=Concord,MA&waypoints=via:42.379322,-71.063384|via:42.444303,-71.229087} + */ + @Test + public void testBostonToConcordViaCharlestownAndLexingtonLatLngNonStopoever() throws Exception { + try (LocalTestServerContext sc = + new LocalTestServerContext("{\"routes\": [{}],\"status\": \"OK\"}")) { + DirectionsApi.newRequest(sc.context) + .origin("Boston,MA") + .destination("Concord,MA") + .waypoints( + new DirectionsApiRequest.Waypoint(new LatLng(42.379322, -71.063384), false), + new DirectionsApiRequest.Waypoint(new LatLng(42.444303, -71.229087), false)) + .await(); + + sc.assertParamValue("Boston,MA", "origin"); + sc.assertParamValue("Concord,MA", "destination"); + sc.assertParamValue("via:42.37932200,-71.06338400|via:42.44430300,-71.22908700", "waypoints"); + } + } + /** * Toledo to Madrid, in Spain. This showcases region biasing results. *