// Path: placesautocomplete/src/main/java/com/seatgeek/placesautocomplete/model/Place.java
// public final class Place {
// 
//     /**
//      * Human readable description of the place returned from the api. e.g. "235 Park Ave South, New York, NY, USA"
//      */
//     public final String description;
// 
//     /**
//      * A unique place id used in the maps apu. this can be used to query for further information about
//      * the location from the places api. See https://developers.google.com/places/documentation/place-id
//      * for more information about place_id
//      */
//     public final String place_id;
// 
//     /**
//      * The lengths and offsets of the substrings the query matched in the description
//      */
//     public final List<MatchedSubstring> matched_substrings;
// 
//     /**
//      * The strings and offsets of the components that make up the description.
//      */
//     public final List<DescriptionTerm> terms;
// 
//     /**
//      * The types of place that this corresponds to in the places api. See individual PlaceType's for
//      * thier descriptions
//      */
//     public final List<PlaceType> types;
// 
//     public Place(final String description, final String place_id, final List<MatchedSubstring> matched_substrings, final List<DescriptionTerm> terms, final List<PlaceType> types) {
//         this.description = description;
//         this.place_id = place_id;
//         this.matched_substrings = matched_substrings;
//         this.terms = terms;
//         this.types = types;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (!(o instanceof Place)) return false;
// 
//         Place place = (Place) o;
// 
//         if (description != null ? !description.equals(place.description) : place.description != null) return false;
//         if (matched_substrings != null ? !matched_substrings.equals(place.matched_substrings) : place.matched_substrings != null)
//             return false;
//         if (place_id != null ? !place_id.equals(place.place_id) : place.place_id != null) return false;
//         if (terms != null ? !terms.equals(place.terms) : place.terms != null) return false;
//         if (types != null ? !types.equals(place.types) : place.types != null) return false;
// 
//         return true;
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = description != null ? description.hashCode() : 0;
//         result = 31 * result + (place_id != null ? place_id.hashCode() : 0);
//         result = 31 * result + (matched_substrings != null ? matched_substrings.hashCode() : 0);
//         result = 31 * result + (terms != null ? terms.hashCode() : 0);
//         result = 31 * result + (types != null ? types.hashCode() : 0);
//         return result;
//     }
// }
// 
// Path: placesautocomplete/src/main/java/com/seatgeek/placesautocomplete/model/PlacesAutocompleteResponse.java
// public final class PlacesAutocompleteResponse extends PlacesApiResponse {
// 
//     /**
//      * A list of predicted places from the api based on the given input
//      */
//     public final List<Place> predictions;
// 
//     public PlacesAutocompleteResponse(final Status status, final String error_message, final List<Place> predictions) {
//         super(status, error_message);
//         this.predictions = predictions;
//     }
// }
// 
// Path: placesautocomplete/src/main/java/com/seatgeek/placesautocomplete/model/PlacesDetailsResponse.java
// public final class PlacesDetailsResponse extends PlacesApiResponse {
// 
//     public final PlaceDetails result;
// 
//     public PlacesDetailsResponse(final Status status, final String error_message, final PlaceDetails result) {
//         super(status, error_message);
//         this.result = result;
//     }
// }


import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.seatgeek.placesautocomplete.model.Place;
import com.seatgeek.placesautocomplete.model.PlacesAutocompleteResponse;
import com.seatgeek.placesautocomplete.model.PlacesDetailsResponse;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
package com.seatgeek.placesautocomplete.json;



class GsonPlacesApiJsonParser implements PlacesApiJsonParser {
    private final Gson gson;

    public GsonPlacesApiJsonParser() {
        gson = new GsonBuilder()
            .create();
    }

    @Override
    public PlacesAutocompleteResponse autocompleteFromStream(final InputStream is)  throws JsonParsingException {
        try {
            final BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            return gson.fromJson(reader, PlacesAutocompleteResponse.class);
        } catch (Exception e) {
            throw new JsonParsingException(e);
        }
    }

    @Override
// Path: placesautocomplete/src/main/java/com/seatgeek/placesautocomplete/model/Place.java
// public final class Place {
// 
//     /**
//      * Human readable description of the place returned from the api. e.g. "235 Park Ave South, New York, NY, USA"
//      */
//     public final String description;
// 
//     /**
//      * A unique place id used in the maps apu. this can be used to query for further information about
//      * the location from the places api. See https://developers.google.com/places/documentation/place-id
//      * for more information about place_id
//      */
//     public final String place_id;
// 
//     /**
//      * The lengths and offsets of the substrings the query matched in the description
//      */
//     public final List<MatchedSubstring> matched_substrings;
// 
//     /**
//      * The strings and offsets of the components that make up the description.
//      */
//     public final List<DescriptionTerm> terms;
// 
//     /**
//      * The types of place that this corresponds to in the places api. See individual PlaceType's for
//      * thier descriptions
//      */
//     public final List<PlaceType> types;
// 
//     public Place(final String description, final String place_id, final List<MatchedSubstring> matched_substrings, final List<DescriptionTerm> terms, final List<PlaceType> types) {
//         this.description = description;
//         this.place_id = place_id;
//         this.matched_substrings = matched_substrings;
//         this.terms = terms;
//         this.types = types;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (!(o instanceof Place)) return false;
// 
//         Place place = (Place) o;
// 
//         if (description != null ? !description.equals(place.description) : place.description != null) return false;
//         if (matched_substrings != null ? !matched_substrings.equals(place.matched_substrings) : place.matched_substrings != null)
//             return false;
//         if (place_id != null ? !place_id.equals(place.place_id) : place.place_id != null) return false;
//         if (terms != null ? !terms.equals(place.terms) : place.terms != null) return false;
//         if (types != null ? !types.equals(place.types) : place.types != null) return false;
// 
//         return true;
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = description != null ? description.hashCode() : 0;
//         result = 31 * result + (place_id != null ? place_id.hashCode() : 0);
//         result = 31 * result + (matched_substrings != null ? matched_substrings.hashCode() : 0);
//         result = 31 * result + (terms != null ? terms.hashCode() : 0);
//         result = 31 * result + (types != null ? types.hashCode() : 0);
//         return result;
//     }
// }
// 
// Path: placesautocomplete/src/main/java/com/seatgeek/placesautocomplete/model/PlacesAutocompleteResponse.java
// public final class PlacesAutocompleteResponse extends PlacesApiResponse {
// 
//     /**
//      * A list of predicted places from the api based on the given input
//      */
//     public final List<Place> predictions;
// 
//     public PlacesAutocompleteResponse(final Status status, final String error_message, final List<Place> predictions) {
//         super(status, error_message);
//         this.predictions = predictions;
//     }
// }
// 
// Path: placesautocomplete/src/main/java/com/seatgeek/placesautocomplete/model/PlacesDetailsResponse.java
// public final class PlacesDetailsResponse extends PlacesApiResponse {
// 
//     public final PlaceDetails result;
// 
//     public PlacesDetailsResponse(final Status status, final String error_message, final PlaceDetails result) {
//         super(status, error_message);
//         this.result = result;
//     }
// }


// Path: placesautocomplete/src/main/java/com/seatgeek/placesautocomplete/json/GsonPlacesApiJsonParser.java
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.seatgeek.placesautocomplete.model.Place;
import com.seatgeek.placesautocomplete.model.PlacesAutocompleteResponse;
import com.seatgeek.placesautocomplete.model.PlacesDetailsResponse;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;

package com.seatgeek.placesautocomplete.json;



class GsonPlacesApiJsonParser implements PlacesApiJsonParser {
    private final Gson gson;

    public GsonPlacesApiJsonParser() {
        gson = new GsonBuilder()
            .create();
    }

    @Override
    public PlacesAutocompleteResponse autocompleteFromStream(final InputStream is)  throws JsonParsingException {
        try {
            final BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            return gson.fromJson(reader, PlacesAutocompleteResponse.class);
        } catch (Exception e) {
            throw new JsonParsingException(e);
        }
    }

    @Override
    public PlacesDetailsResponse detailsFromStream(final InputStream is) throws JsonParsingException {