From db6d3d18dd4ee5981a1aac6a7371f184fa1cd30a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cosana=E2=80=9D?= Date: Tue, 20 Mar 2018 22:51:47 -0400 Subject: [PATCH 1/2] Adding MapMatchingError --- .../api/matching/v5/MapboxMapMatching.java | 76 +++++++++++ .../matching/v5/models/MapMatchingError.java | 118 ++++++++++++++++++ .../v5/models/MapMatchingMatching.java | 40 ++++++ .../v5/models/MapMatchingResponse.java | 58 +++++++++ 4 files changed, 292 insertions(+) create mode 100644 services-matching/src/main/java/com/mapbox/api/matching/v5/models/MapMatchingError.java diff --git a/services-matching/src/main/java/com/mapbox/api/matching/v5/MapboxMapMatching.java b/services-matching/src/main/java/com/mapbox/api/matching/v5/MapboxMapMatching.java index 7459907a9..606f5a328 100644 --- a/services-matching/src/main/java/com/mapbox/api/matching/v5/MapboxMapMatching.java +++ b/services-matching/src/main/java/com/mapbox/api/matching/v5/MapboxMapMatching.java @@ -14,6 +14,7 @@ import com.mapbox.api.directions.v5.DirectionsCriteria.OverviewCriteria; import com.mapbox.api.directions.v5.DirectionsCriteria.ProfileCriteria; import com.mapbox.api.matching.v5.models.MapMatchingAdapterFactory; +import com.mapbox.api.matching.v5.models.MapMatchingError; import com.mapbox.api.matching.v5.models.MapMatchingResponse; import com.mapbox.core.MapboxService; import com.mapbox.core.constants.Constants; @@ -23,12 +24,24 @@ import com.mapbox.core.utils.TextUtils; import com.mapbox.geojson.Point; +import okhttp3.ResponseBody; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Converter; +import retrofit2.Response; + +import java.io.IOException; +import java.lang.annotation.Annotation; + import java.util.ArrayList; import java.util.List; import java.util.Locale; +import java.util.logging.Level; import retrofit2.Call; +import static com.sun.xml.internal.ws.spi.db.BindingContextFactory.LOGGER; + /** * The Mapbox map matching interface (v5) *

@@ -44,6 +57,7 @@ public abstract class MapboxMapMatching extends MapboxService { + protected MapboxMapMatching() { super(MapMatchingService.class); } @@ -77,6 +91,68 @@ protected Call initializeCall() { waypoints()); } + /** + * Wrapper method for Retrofits {@link Call#execute()} call returning a response specific to the + * Map Matching API. + * + * @return the Map Matching v5 response once the call completes successfully + * @throws IOException Signals that an I/O exception of some sort has occurred + * @since 1.0.0 + */ + @Override + public Response executeCall() throws IOException { + + Response response = getCall().execute(); + if (!response.isSuccessful()) { + errorDidOccur(null, response); + } + return response; + } + + /** + * Wrapper method for Retrofits {@link Call#enqueue(Callback)} call returning a response specific + * to the Map Matching API. Use this method to make a directions request on the Main Thread. + * + * @param callback a {@link Callback} which is used once the {@link MapMatchingResponse} is + * created. + * @since 1.0.0 + */ + @Override + public void enqueueCall(final Callback callback) { + getCall().enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (!response.isSuccessful()) { + errorDidOccur(callback, response); + return; + } + callback.onResponse(call, response); + } + + @Override + public void onFailure(Call call, Throwable throwable) { + callback.onFailure(call, throwable); + } + }); + } + + + private void errorDidOccur(@Nullable Callback callback, + @NonNull Response response) { + // Response gave an error, we try to LOGGER any messages into the LOGGER here. + Converter errorConverter = + getRetrofit().responseBodyConverter(MapMatchingError.class, new Annotation[0]); + if (callback == null) { + return; + } + try { + callback.onFailure(getCall(), + new Throwable(errorConverter.convert(response.errorBody()).message())); + } catch (IOException ioException) { + LOGGER.log(Level.WARNING, "Failed to complete your request. ", ioException); + } + } + @Nullable abstract String clientAppName(); diff --git a/services-matching/src/main/java/com/mapbox/api/matching/v5/models/MapMatchingError.java b/services-matching/src/main/java/com/mapbox/api/matching/v5/models/MapMatchingError.java new file mode 100644 index 000000000..f38e379c7 --- /dev/null +++ b/services-matching/src/main/java/com/mapbox/api/matching/v5/models/MapMatchingError.java @@ -0,0 +1,118 @@ +package com.mapbox.api.matching.v5.models; + +import android.support.annotation.Nullable; + +import com.google.auto.value.AutoValue; +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; + +import java.io.Serializable; + +/** + * If an InvalidInput error is thrown, this class can be used to get both the code and the message + * which holds an explanation of the invalid input. + * + * On error, the server responds with different HTTP status codes. + * For responses with HTTP status codes lower than 500, the JSON response body includes the code property, + * which may be used by client programs to manage control flow. The response body may also include a message property, + * with a human-readable explaination of the error. If a server error occurs, + * the HTTP status code will be 500 or higher and the response will not include a code property. + * + * @since 3.0.0 + */ +@AutoValue +public abstract class MapMatchingError implements Serializable { + + /** + * Create a new instance of this class by using the {@link Builder} class. + * + * @return this classes {@link Builder} for creating a new instance + * @since 3.0.0 + */ + public static Builder builder() { + return new AutoValue_MapMatchingError.Builder(); + } + + /** + * String indicating the state of the response. This is a separate code than the HTTP status code. + * On normal valid responses, the value will be Ok. The possible responses are listed below: + *

+ * + * @return a string with one of the given values described in the list above + * @since 3.0.0 + */ + @Nullable + public abstract String code(); + + /** + * Provides a short message with the explanation of the invalid input. + * + * @return a string containing the message API MapMatching response + * @since 3.0.0 + */ + @Nullable + public abstract String message(); + + /** + * Gson type adapter for parsing Gson to this class. + * + * @param gson the built {@link Gson} object + * @return the type adapter for this class + * @since 3.0.0 + */ + public static TypeAdapter typeAdapter(Gson gson) { + return new AutoValue_MapMatchingError.GsonTypeAdapter(gson); + } + + /** + * This builder can be used to set the values describing the {@link MapMatchingError}. + * + * @since 3.0.0 + */ + @AutoValue.Builder + public abstract static class Builder { + + /** + * String indicating the state of the response. This is a separate code than the HTTP status + * code. On normal valid responses, the value will be Ok. The possible responses are listed + * below: + * + * + * @param code a string with one of the given values described in the list above + * @return this builder for chaining options together + * @since 3.0.0 + */ + public abstract Builder code(String code); + + /** + * Provides a short message with the explanation of the invalid input. + * + * @param message a string containing the message API Directions response + * @return this builder for chaining options together + * @since 3.0.0 + */ + public abstract Builder message(String message); + + /** + * Build a new {@link MapMatchingError} object. + * + * @return a new {@link MapMatchingError} using the provided values in this builder + * @since 3.0.0 + */ + public abstract MapMatchingError build(); + } +} diff --git a/services-matching/src/main/java/com/mapbox/api/matching/v5/models/MapMatchingMatching.java b/services-matching/src/main/java/com/mapbox/api/matching/v5/models/MapMatchingMatching.java index 58ca3f7a9..3040d11df 100644 --- a/services-matching/src/main/java/com/mapbox/api/matching/v5/models/MapMatchingMatching.java +++ b/services-matching/src/main/java/com/mapbox/api/matching/v5/models/MapMatchingMatching.java @@ -3,10 +3,21 @@ import android.support.annotation.Nullable; import com.google.auto.value.AutoValue; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.google.gson.TypeAdapter; import com.google.gson.annotations.SerializedName; +import com.mapbox.api.directions.v5.DirectionsAdapterFactory; import com.mapbox.api.directions.v5.models.RouteLeg; import com.mapbox.api.directions.v5.models.DirectionsRoute; +import com.mapbox.api.directions.v5.models.RouteOptions; +import com.mapbox.api.matching.v5.MapboxMapMatching; +import com.mapbox.geojson.BoundingBox; +import com.mapbox.geojson.Geometry; +import com.mapbox.geojson.Point; +import com.mapbox.geojson.gson.BoundingBoxDeserializer; +import com.mapbox.geojson.gson.GeoJsonAdapterFactory; +import com.mapbox.geojson.gson.GeometryDeserializer; +import com.mapbox.geojson.gson.PointDeserializer; import java.io.Serializable; import java.util.List; @@ -30,6 +41,24 @@ public static Builder builder() { return new AutoValue_MapMatchingMatching.Builder(); } + /** + * Create a new instance of this class by passing in a formatted valid JSON String. + * + * @param json a formatted valid JSON string defining a GeoJson MapboxMapMatching + * @return a new instance of this class defined by the values passed inside this static factory + * method + * @since 3.0.0 + */ + public static MapMatchingMatching fromJson(String json) { + GsonBuilder gson = new GsonBuilder(); + gson.registerTypeAdapter(Point.class, new PointDeserializer()); + gson.registerTypeAdapter(Geometry.class, new GeometryDeserializer()); + gson.registerTypeAdapter(BoundingBox.class, new BoundingBoxDeserializer()); + gson.registerTypeAdapterFactory(GeoJsonAdapterFactory.create()); + gson.registerTypeAdapterFactory(MapMatchingAdapterFactory.create()); + return gson.create().fromJson(json, MapMatchingMatching.class); + } + /** * The distance traveled from origin to destination. * @@ -90,6 +119,17 @@ public static Builder builder() { */ public abstract double confidence(); + /** + * Convert the current {@link MapMatchingMatching} to its builder holding the currently assigned + * values. This allows you to modify a single variable and then rebuild the project resulting in + * an updated and modifier {@link MapMatchingMatching}. + * + * @return a {@link MapMatchingMatching.Builder} with the same values set to match the ones defined + * in this {@link MapMatchingMatching} + * @since 3.0.0 + */ + public abstract MapMatchingMatching.Builder toBuilder(); + /** * Gson type adapter for parsing Gson to this class. * diff --git a/services-matching/src/main/java/com/mapbox/api/matching/v5/models/MapMatchingResponse.java b/services-matching/src/main/java/com/mapbox/api/matching/v5/models/MapMatchingResponse.java index 52f125cd6..cf3092c1d 100644 --- a/services-matching/src/main/java/com/mapbox/api/matching/v5/models/MapMatchingResponse.java +++ b/services-matching/src/main/java/com/mapbox/api/matching/v5/models/MapMatchingResponse.java @@ -4,7 +4,16 @@ import android.support.annotation.Nullable; import com.google.auto.value.AutoValue; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.google.gson.TypeAdapter; +import com.mapbox.api.directions.v5.models.DirectionsRoute; +import com.mapbox.geojson.BoundingBox; +import com.mapbox.geojson.Geometry; +import com.mapbox.geojson.Point; +import com.mapbox.geojson.gson.BoundingBoxDeserializer; +import com.mapbox.geojson.gson.GeoJsonAdapterFactory; +import com.mapbox.geojson.gson.GeometryDeserializer; +import com.mapbox.geojson.gson.PointDeserializer; import java.io.Serializable; import java.util.List; @@ -28,6 +37,24 @@ public static Builder builder() { return new AutoValue_MapMatchingResponse.Builder(); } + /** + * Create a new instance of this class by passing in a formatted valid JSON String. + * + * @param json a formatted valid JSON string defining a GeoJson MapMatching Response + * @return a new instance of this class defined by the values passed inside this static factory + * method + * @since 3.0.0 + */ + public static MapMatchingResponse fromJson(String json) { + GsonBuilder gson = new GsonBuilder(); + gson.registerTypeAdapter(Point.class, new PointDeserializer()); + gson.registerTypeAdapter(Geometry.class, new GeometryDeserializer()); + gson.registerTypeAdapter(BoundingBox.class, new BoundingBoxDeserializer()); + gson.registerTypeAdapterFactory(GeoJsonAdapterFactory.create()); + gson.registerTypeAdapterFactory(MapMatchingAdapterFactory.create()); + return gson.create().fromJson(json, MapMatchingResponse.class); + } + /** * A string depicting the state of the response. *