// Path: core/src/main/java/com/github/filosganga/geogson/model/Feature.java
// public class Feature implements Serializable {
// 
//     private static final long serialVersionUID = 1L;
// 
//     private final Geometry<?> geometry;
// 
//     // Feature properties can contain generic json objects
//     private final Map<String, JsonElement> properties;
// 
//     private final String id;
// 
//     private transient Integer cachedHashCode = null;
// 
//     public static class Builder {
// 
//         private Geometry<?> geometry = null;
//         private Map<String, JsonElement> properties = new HashMap<>(240);
//         private Optional<String> id = Optional.empty();
// 
//         Builder(){
//         }
// 
//         public Builder withGeometry(Geometry<?> geometry) {
//             this.geometry = geometry;
//             return this;
//         }
// 
//         public Builder withProperties(Map<String, JsonElement> properties) {
//             this.properties.putAll(properties);
//             return this;
//         }
// 
//         public Builder withProperty(String name, JsonElement value) {
//             this.properties.put(name, value);
//             return this;
//         }
// 
//         public Builder withId(Optional<String> id) {
//             this.id = id;
//             return this;
//         }
// 
//         public Builder withId(String id) {
//             return withId(Optional.of(id));
//         }
// 
//         public Feature build() {
//             if(geometry == null) {
//                 throw new IllegalStateException("geometry is required to build a Feature");
//             }
//             return new Feature(geometry, properties, id);
//         }
// 
//     }
// 
//     private Feature(Geometry<?> geometry, Map<String, JsonElement> properties, Optional<String> id) {
//         this.geometry = geometry;
//         this.properties = properties;
//         this.id = id.orElse(null);
//     }
// 
//     public static Builder builder() {
//         return new Builder();
//     }
// 
//     public static Builder builder(Feature feature) {
//         return builder().withGeometry(feature.geometry).withProperties(feature.properties).withId(feature.id);
//     }
// 
//     /**
//      * Build a {@link Feature} with the given {@link Geometry}.
//      *
//      * @param geometry The Geometry to build Feature from
//      *
//      * @return An instance of Feature
//      */
//     public static Feature of(Geometry<?> geometry) {
//         return builder().withGeometry(geometry).build();
//     }
// 
//     /**
//      * The Geometry of this Feature.
//      *
//      * @return a Geometry instance.
//      */
//     public Geometry<?> geometry() {
//         return geometry;
//     }
// 
//     /**
//      * The properties of this Feature.
//      *
//      * @return an Map containing the properties. An empty map if not properties have been set.
//      */
//     public Map<String, JsonElement> properties() {
//         return Collections.unmodifiableMap(properties);
//     }
// 
//     /**
//      * The id of the Feature.
//      *
//      * @return Optional.absent if this Feature does not have any id. A valued Optional otherwise.
//      */
//     public Optional<String> id() {
//         return Optional.ofNullable(id);
//     }
// 
// 
//     @Override
//     public int hashCode() {
//         if(cachedHashCode == null) {
//             cachedHashCode = Objects.hash(getClass(), this.id, this.geometry, this.properties);
//         }
// 
//         return cachedHashCode;
//     }
// 
//     @Override
//     public boolean equals(Object obj) {
//         if (this == obj) {
//             return true;
//         }
//         if (obj == null || getClass() != obj.getClass()) {
//             return false;
//         }
//         final Feature other = (Feature) obj;
//         return Objects.equals(this.id, other.id)
//                 && Objects.equals(this.properties, other.properties)
//                 && Objects.equals(this.geometry, other.geometry);
//     }
// 
//     @Override
//     public String toString() {
//         return "Feature{" +
//                 "geometry=" + geometry +
//                 ", properties=" + properties +
//                 ", id=" + id +
//                 '}';
//     }
// }
// 
// Path: core/src/main/java/com/github/filosganga/geogson/model/FeatureCollection.java
// public class FeatureCollection implements Serializable {
// 
//     private static final long serialVersionUID = 1L;
// 
//     private final List<Feature> features;
// 
//     public FeatureCollection(List<Feature> features) {
//         this.features = features;
//     }
// 
//     public static FeatureCollection of(Feature...features) {
//         return new FeatureCollection(Arrays.asList(features));
//     }
// 
//     public List<Feature> features() {
//         return Collections.unmodifiableList(features);
//     }
// 
//     public int size() {
//         return features.size();
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(getClass(), this.features);
//     }
// 
//     @Override
//     public boolean equals(Object obj) {
//         if (this == obj) {
//             return true;
//         }
//         if (obj == null || getClass() != obj.getClass()) {
//             return false;
//         }
//         final FeatureCollection other = (FeatureCollection) obj;
//         return Objects.equals(this.features, other.features);
//     }
// 
//     @Override
//     public String toString() {
//         return "FeatureCollection{" +
//                 "features=" + features +
//                 '}';
//     }
// }


import com.github.filosganga.geogson.model.Feature;
import com.github.filosganga.geogson.model.FeatureCollection;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.util.LinkedList;
package com.github.filosganga.geogson.gson;




/**
 * The Gson TypeAdapter to serialize/de-serialize {@link FeatureCollection} instances.
 */
public final class FeatureCollectionAdapter extends TypeAdapter<FeatureCollection> {

    private final Gson gson;
// Path: core/src/main/java/com/github/filosganga/geogson/model/Feature.java
// public class Feature implements Serializable {
// 
//     private static final long serialVersionUID = 1L;
// 
//     private final Geometry<?> geometry;
// 
//     // Feature properties can contain generic json objects
//     private final Map<String, JsonElement> properties;
// 
//     private final String id;
// 
//     private transient Integer cachedHashCode = null;
// 
//     public static class Builder {
// 
//         private Geometry<?> geometry = null;
//         private Map<String, JsonElement> properties = new HashMap<>(240);
//         private Optional<String> id = Optional.empty();
// 
//         Builder(){
//         }
// 
//         public Builder withGeometry(Geometry<?> geometry) {
//             this.geometry = geometry;
//             return this;
//         }
// 
//         public Builder withProperties(Map<String, JsonElement> properties) {
//             this.properties.putAll(properties);
//             return this;
//         }
// 
//         public Builder withProperty(String name, JsonElement value) {
//             this.properties.put(name, value);
//             return this;
//         }
// 
//         public Builder withId(Optional<String> id) {
//             this.id = id;
//             return this;
//         }
// 
//         public Builder withId(String id) {
//             return withId(Optional.of(id));
//         }
// 
//         public Feature build() {
//             if(geometry == null) {
//                 throw new IllegalStateException("geometry is required to build a Feature");
//             }
//             return new Feature(geometry, properties, id);
//         }
// 
//     }
// 
//     private Feature(Geometry<?> geometry, Map<String, JsonElement> properties, Optional<String> id) {
//         this.geometry = geometry;
//         this.properties = properties;
//         this.id = id.orElse(null);
//     }
// 
//     public static Builder builder() {
//         return new Builder();
//     }
// 
//     public static Builder builder(Feature feature) {
//         return builder().withGeometry(feature.geometry).withProperties(feature.properties).withId(feature.id);
//     }
// 
//     /**
//      * Build a {@link Feature} with the given {@link Geometry}.
//      *
//      * @param geometry The Geometry to build Feature from
//      *
//      * @return An instance of Feature
//      */
//     public static Feature of(Geometry<?> geometry) {
//         return builder().withGeometry(geometry).build();
//     }
// 
//     /**
//      * The Geometry of this Feature.
//      *
//      * @return a Geometry instance.
//      */
//     public Geometry<?> geometry() {
//         return geometry;
//     }
// 
//     /**
//      * The properties of this Feature.
//      *
//      * @return an Map containing the properties. An empty map if not properties have been set.
//      */
//     public Map<String, JsonElement> properties() {
//         return Collections.unmodifiableMap(properties);
//     }
// 
//     /**
//      * The id of the Feature.
//      *
//      * @return Optional.absent if this Feature does not have any id. A valued Optional otherwise.
//      */
//     public Optional<String> id() {
//         return Optional.ofNullable(id);
//     }
// 
// 
//     @Override
//     public int hashCode() {
//         if(cachedHashCode == null) {
//             cachedHashCode = Objects.hash(getClass(), this.id, this.geometry, this.properties);
//         }
// 
//         return cachedHashCode;
//     }
// 
//     @Override
//     public boolean equals(Object obj) {
//         if (this == obj) {
//             return true;
//         }
//         if (obj == null || getClass() != obj.getClass()) {
//             return false;
//         }
//         final Feature other = (Feature) obj;
//         return Objects.equals(this.id, other.id)
//                 && Objects.equals(this.properties, other.properties)
//                 && Objects.equals(this.geometry, other.geometry);
//     }
// 
//     @Override
//     public String toString() {
//         return "Feature{" +
//                 "geometry=" + geometry +
//                 ", properties=" + properties +
//                 ", id=" + id +
//                 '}';
//     }
// }
// 
// Path: core/src/main/java/com/github/filosganga/geogson/model/FeatureCollection.java
// public class FeatureCollection implements Serializable {
// 
//     private static final long serialVersionUID = 1L;
// 
//     private final List<Feature> features;
// 
//     public FeatureCollection(List<Feature> features) {
//         this.features = features;
//     }
// 
//     public static FeatureCollection of(Feature...features) {
//         return new FeatureCollection(Arrays.asList(features));
//     }
// 
//     public List<Feature> features() {
//         return Collections.unmodifiableList(features);
//     }
// 
//     public int size() {
//         return features.size();
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(getClass(), this.features);
//     }
// 
//     @Override
//     public boolean equals(Object obj) {
//         if (this == obj) {
//             return true;
//         }
//         if (obj == null || getClass() != obj.getClass()) {
//             return false;
//         }
//         final FeatureCollection other = (FeatureCollection) obj;
//         return Objects.equals(this.features, other.features);
//     }
// 
//     @Override
//     public String toString() {
//         return "FeatureCollection{" +
//                 "features=" + features +
//                 '}';
//     }
// }


// Path: core/src/main/java/com/github/filosganga/geogson/gson/FeatureCollectionAdapter.java
import com.github.filosganga.geogson.model.Feature;
import com.github.filosganga.geogson.model.FeatureCollection;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.util.LinkedList;

package com.github.filosganga.geogson.gson;




/**
 * The Gson TypeAdapter to serialize/de-serialize {@link FeatureCollection} instances.
 */
public final class FeatureCollectionAdapter extends TypeAdapter<FeatureCollection> {

    private final Gson gson;
    private final TypeAdapter<Feature> featureAdapter;