// Path: core/src/main/java/com/github/filosganga/geogson/model/Geometry.java
// public interface Geometry<P extends Positions> {
// 
//     /**
//      * Define the type of the Geometry. As defined in the GeoJson specifications.
//      */
//     enum Type {
//         POINT("Point"),
//         MULTI_POINT("MultiPoint"),
//         LINE_STRING("LineString"),
//         LINEAR_RING("LineString"),
//         MULTI_LINE_STRING("MultiLineString"),
//         POLYGON("Polygon"),
//         MULTI_POLYGON("MultiPolygon"),
//         GEOMETRY_COLLECTION("GeometryCollection");
// 
//         private final String value;
// 
//         Type(String value) {
//             this.value = value;
//         }
// 
//         public String getValue() {
//             return value;
//         }
// 
//         public static Type forValue(String value) {
//             for (Type type : values()) {
//                 if (type.getValue().equalsIgnoreCase(value)) {
//                     return type;
//                 }
//             }
//             throw new IllegalArgumentException("Cannot build a geometry for type: " + value);
//         }
//     }
// 
//     /**
//      * Returns the Geometry type.
//      *
//      * @return Type
//      */
//     Type type();
// 
//     /**
//      * Returns the Position underlying instance.
//      *
//      * @return Position
//      */
//     P positions();
// 
//     /**
//      * Returns the size of this Geometry. Depending of the type of this Geometry, it may have different meaning.
//      * eg: For a LineString it is the number of points, for a MultiPolygon it is the number of polygons.
//      *
//      * @return Int
//      */
//     int size();
// }
// 
// Path: core/src/main/java/com/github/filosganga/geogson/model/GeometryCollection.java
// public class GeometryCollection implements Geometry<Positions>, Serializable {
// 
//     /**
//      * internal Version for Serialization starting with 1. <b>Increment by 1 at
//      * every change!</b>
//      */
//     private static final long serialVersionUID = 1L;
// 
//     /**
//      * Geometries of this {@link GeometryCollection}
//      */
//     private final List<Geometry<?>> geometries;
// 
//     /**
//      * Constructor creating a {@link GeometryCollection} out of
//      * {@link Iterable} {@link Geometry Geometries}.
//      *
//      * @param geometries Geometries of this {@link GeometryCollection}
//      */
//     private GeometryCollection(List<Geometry<?>> geometries) {
//         this.geometries = geometries;
//     }
// 
//     public static GeometryCollection of(Geometry<?>...geometries) {
//         return new GeometryCollection(Arrays.asList(geometries));
//     }
// 
//     public static GeometryCollection of(Iterable<Geometry<?>> geometries) {
//         if(geometries instanceof List) {
//             return new GeometryCollection((List<Geometry<?>>)geometries);
//         } else {
//             return of(StreamSupport.stream(geometries.spliterator(), false).collect(Collectors.toList()));
//         }
//     }
// 
//     public static GeometryCollection of(Stream<Geometry<?>> geometries) {
//         return new GeometryCollection(geometries.collect(Collectors.toList()));
//     }
// 
//     /**
//      * Get the {@link Iterable} {@link Geometry Geometries} of this
//      * {@link GeometryCollection}
//      *
//      * @return all {@link Geometry Geometries} of this {@link Iterable} (e.g.
//      * Collection)
//      */
//     public List<Geometry<?>> getGeometries() {
//         return Collections.unmodifiableList(this.geometries);
//     }
// 
//     @Override
//     public Type type() {
//         return Type.GEOMETRY_COLLECTION;
//     }
// 
//     @Override
//     public Positions positions() {
//         Positions positions = new SinglePosition(Double.NaN, Double.NaN, Double.NaN);
//         for (Geometry<?> geometry : this.geometries) {
//             positions.merge(geometry.positions());
//         }
//         return positions;
//     }
// 
//     @Override
//     public int size() {
//         return geometries.size();
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(getClass(), this.geometries);
//     }
// 
//     @Override
//     public boolean equals(Object obj) {
//         if (this == obj) {
//             return true;
//         }
//         if (obj == null || getClass() != obj.getClass()) {
//             return false;
//         }
//         final GeometryCollection other = (GeometryCollection) obj;
//         return Objects.equals(this.geometries, other.geometries);
//     }
// 
//     @Override
//     public String toString() {
//         return "GeometryCollection{geometries: " + Objects.toString(this.geometries) + "}";
//     }
// 
// }


import com.github.filosganga.geogson.model.Geometry;
import com.github.filosganga.geogson.model.GeometryCollection;
import org.locationtech.jts.geom.GeometryFactory;
import java.util.stream.StreamSupport;
package com.github.filosganga.geogson.jts;



/**
 * Codec for a {@link org.locationtech.jts.geom.GeometryCollection JTS
 * GeometryCollection}
 */
public class GeometryCollectionCodec extends AbstractJtsCodec<org.locationtech.jts.geom.GeometryCollection, GeometryCollection> {

    /**
     * Create a codec for a {@link org.locationtech.jts.geom.GeometryCollection JTS
     * GeometryCollection} with a given {@link GeometryFactory}
     *
     * @param geometryFactory a {@link GeometryFactory} defining a PrecisionModel and a SRID
     */
    public GeometryCollectionCodec(GeometryFactory geometryFactory) {
        super(geometryFactory);
    }

    @Override
    public GeometryCollection toGeometry(org.locationtech.jts.geom.GeometryCollection src) {
        return GeometryCollection.of(StreamSupport.stream(JtsGeometryCollectionIterable.of(src).spliterator(), false)
                .map(this::fromJtsGeometryCollection)
// Path: core/src/main/java/com/github/filosganga/geogson/model/Geometry.java
// public interface Geometry<P extends Positions> {
// 
//     /**
//      * Define the type of the Geometry. As defined in the GeoJson specifications.
//      */
//     enum Type {
//         POINT("Point"),
//         MULTI_POINT("MultiPoint"),
//         LINE_STRING("LineString"),
//         LINEAR_RING("LineString"),
//         MULTI_LINE_STRING("MultiLineString"),
//         POLYGON("Polygon"),
//         MULTI_POLYGON("MultiPolygon"),
//         GEOMETRY_COLLECTION("GeometryCollection");
// 
//         private final String value;
// 
//         Type(String value) {
//             this.value = value;
//         }
// 
//         public String getValue() {
//             return value;
//         }
// 
//         public static Type forValue(String value) {
//             for (Type type : values()) {
//                 if (type.getValue().equalsIgnoreCase(value)) {
//                     return type;
//                 }
//             }
//             throw new IllegalArgumentException("Cannot build a geometry for type: " + value);
//         }
//     }
// 
//     /**
//      * Returns the Geometry type.
//      *
//      * @return Type
//      */
//     Type type();
// 
//     /**
//      * Returns the Position underlying instance.
//      *
//      * @return Position
//      */
//     P positions();
// 
//     /**
//      * Returns the size of this Geometry. Depending of the type of this Geometry, it may have different meaning.
//      * eg: For a LineString it is the number of points, for a MultiPolygon it is the number of polygons.
//      *
//      * @return Int
//      */
//     int size();
// }
// 
// Path: core/src/main/java/com/github/filosganga/geogson/model/GeometryCollection.java
// public class GeometryCollection implements Geometry<Positions>, Serializable {
// 
//     /**
//      * internal Version for Serialization starting with 1. <b>Increment by 1 at
//      * every change!</b>
//      */
//     private static final long serialVersionUID = 1L;
// 
//     /**
//      * Geometries of this {@link GeometryCollection}
//      */
//     private final List<Geometry<?>> geometries;
// 
//     /**
//      * Constructor creating a {@link GeometryCollection} out of
//      * {@link Iterable} {@link Geometry Geometries}.
//      *
//      * @param geometries Geometries of this {@link GeometryCollection}
//      */
//     private GeometryCollection(List<Geometry<?>> geometries) {
//         this.geometries = geometries;
//     }
// 
//     public static GeometryCollection of(Geometry<?>...geometries) {
//         return new GeometryCollection(Arrays.asList(geometries));
//     }
// 
//     public static GeometryCollection of(Iterable<Geometry<?>> geometries) {
//         if(geometries instanceof List) {
//             return new GeometryCollection((List<Geometry<?>>)geometries);
//         } else {
//             return of(StreamSupport.stream(geometries.spliterator(), false).collect(Collectors.toList()));
//         }
//     }
// 
//     public static GeometryCollection of(Stream<Geometry<?>> geometries) {
//         return new GeometryCollection(geometries.collect(Collectors.toList()));
//     }
// 
//     /**
//      * Get the {@link Iterable} {@link Geometry Geometries} of this
//      * {@link GeometryCollection}
//      *
//      * @return all {@link Geometry Geometries} of this {@link Iterable} (e.g.
//      * Collection)
//      */
//     public List<Geometry<?>> getGeometries() {
//         return Collections.unmodifiableList(this.geometries);
//     }
// 
//     @Override
//     public Type type() {
//         return Type.GEOMETRY_COLLECTION;
//     }
// 
//     @Override
//     public Positions positions() {
//         Positions positions = new SinglePosition(Double.NaN, Double.NaN, Double.NaN);
//         for (Geometry<?> geometry : this.geometries) {
//             positions.merge(geometry.positions());
//         }
//         return positions;
//     }
// 
//     @Override
//     public int size() {
//         return geometries.size();
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(getClass(), this.geometries);
//     }
// 
//     @Override
//     public boolean equals(Object obj) {
//         if (this == obj) {
//             return true;
//         }
//         if (obj == null || getClass() != obj.getClass()) {
//             return false;
//         }
//         final GeometryCollection other = (GeometryCollection) obj;
//         return Objects.equals(this.geometries, other.geometries);
//     }
// 
//     @Override
//     public String toString() {
//         return "GeometryCollection{geometries: " + Objects.toString(this.geometries) + "}";
//     }
// 
// }


// Path: jts/src/main/java/com/github/filosganga/geogson/jts/GeometryCollectionCodec.java
import com.github.filosganga.geogson.model.Geometry;
import com.github.filosganga.geogson.model.GeometryCollection;
import org.locationtech.jts.geom.GeometryFactory;
import java.util.stream.StreamSupport;

package com.github.filosganga.geogson.jts;



/**
 * Codec for a {@link org.locationtech.jts.geom.GeometryCollection JTS
 * GeometryCollection}
 */
public class GeometryCollectionCodec extends AbstractJtsCodec<org.locationtech.jts.geom.GeometryCollection, GeometryCollection> {

    /**
     * Create a codec for a {@link org.locationtech.jts.geom.GeometryCollection JTS
     * GeometryCollection} with a given {@link GeometryFactory}
     *
     * @param geometryFactory a {@link GeometryFactory} defining a PrecisionModel and a SRID
     */
    public GeometryCollectionCodec(GeometryFactory geometryFactory) {
        super(geometryFactory);
    }

    @Override
    public GeometryCollection toGeometry(org.locationtech.jts.geom.GeometryCollection src) {
        return GeometryCollection.of(StreamSupport.stream(JtsGeometryCollectionIterable.of(src).spliterator(), false)
                .map(this::fromJtsGeometryCollection)
                .toArray(Geometry<?>[]::new)