/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2015, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.data.geobuf; import com.vividsolutions.jts.geom.*; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.AttributeDescriptor; import org.opengis.feature.type.GeometryDescriptor; import java.io.*; /** * GeobufFeatureType encodes and decodes SimpleFeatureTypes * @author Jared Erickson */ public class GeobufFeatureType { private int precision; private int dimension; public GeobufFeatureType() { this(6, 2); } public GeobufFeatureType(int precision, int dimension) { this.precision = precision; this.dimension = dimension; } public void encode(SimpleFeatureType featureType, OutputStream out) throws IOException { Geobuf.Data.Builder dataBuilder = Geobuf.Data.newBuilder(); encode(featureType, dataBuilder); Geobuf.Data data = dataBuilder.build(); data.writeTo(out); } public SimpleFeatureType decode(String name, InputStream inputStream) throws IOException { Geobuf.Data data = Geobuf.Data.parseFrom(inputStream); return getFeatureType(name, data); } protected void encode(SimpleFeatureType featureType, Geobuf.Data.Builder dataBuilder) { // Keys for (AttributeDescriptor descriptor : featureType.getAttributeDescriptors()) { if (!(descriptor instanceof GeometryDescriptor)) { dataBuilder.addKeys(descriptor.getLocalName()); } } // Max Coordinate Dimension dataBuilder.setDimensions(dimension); // Number of digits after decimal point dataBuilder.setPrecision(precision); // Set Feature Collection dataBuilder.setFeatureCollection(Geobuf.Data.FeatureCollection.newBuilder().build()); } protected SimpleFeatureType getFeatureType(String name, Geobuf.Data data) throws IOException { SimpleFeatureTypeBuilder featureTypeBuilder = new SimpleFeatureTypeBuilder(); featureTypeBuilder.setName(name); if (data.getDataTypeCase() == Geobuf.Data.DataTypeCase.GEOMETRY) { featureTypeBuilder.setDefaultGeometry("geom"); featureTypeBuilder.add("geom", getGeometryType(data.getGeometry())); } else if (data.getDataTypeCase() == Geobuf.Data.DataTypeCase.FEATURE) { featureTypeBuilder.setDefaultGeometry("geom"); featureTypeBuilder.add("geom", getGeometryType(data.getFeature().getGeometry())); int keyCount = data.getKeysCount(); for (int i = 0; i < keyCount; i++) { String key = data.getKeys(i); Class type = getType(data.getFeature().getValues(i).getValueTypeCase()); featureTypeBuilder.add(key, type); } } else if (data.getDataTypeCase() == Geobuf.Data.DataTypeCase.FEATURE_COLLECTION) { featureTypeBuilder.setDefaultGeometry("geom"); if (data.getFeatureCollection().getFeaturesCount() == 0) { featureTypeBuilder.add("geom", Geometry.class); } else { featureTypeBuilder.add("geom", getGeometryType(data.getFeatureCollection().getFeatures(0).getGeometry())); } int keyCount = data.getKeysCount(); for (int i = 0; i < keyCount; i++) { String key = data.getKeys(i); Class type = String.class; if (data.getFeatureCollection().getFeaturesCount() > 0 && i < data.getFeatureCollection().getFeatures(0).getValuesCount()) { type = getType(data.getFeatureCollection().getFeatures(0).getValues(i).getValueTypeCase()); } featureTypeBuilder.add(key, type); } } else { throw new IOException("Unknown Data Type!"); } return featureTypeBuilder.buildFeatureType(); } protected Class<?> getType(Geobuf.Data.Value.ValueTypeCase vtc) { if (vtc == Geobuf.Data.Value.ValueTypeCase.STRING_VALUE) { return String.class; } else if (vtc == Geobuf.Data.Value.ValueTypeCase.POS_INT_VALUE || vtc == Geobuf.Data.Value.ValueTypeCase.NEG_INT_VALUE) { return Integer.class; } else if (vtc == Geobuf.Data.Value.ValueTypeCase.BOOL_VALUE) { return Boolean.class; } else if (vtc == Geobuf.Data.Value.ValueTypeCase.DOUBLE_VALUE) { return Boolean.class; } else if (vtc == Geobuf.Data.Value.ValueTypeCase.JSON_VALUE) { return String.class; } else { return Object.class; } } protected Class<? extends Geometry> getGeometryType(Geobuf.Data.Geometry g) { if (g.getType() == Geobuf.Data.Geometry.Type.POINT) { return Point.class; } else if (g.getType() == Geobuf.Data.Geometry.Type.LINESTRING) { return LineString.class; } else if (g.getType() == Geobuf.Data.Geometry.Type.POLYGON) { return Polygon.class; } else if (g.getType() == Geobuf.Data.Geometry.Type.MULTIPOINT) { return MultiPoint.class; } else if (g.getType() == Geobuf.Data.Geometry.Type.MULTILINESTRING) { return MultiLineString.class; } else if (g.getType() == Geobuf.Data.Geometry.Type.MULTIPOLYGON) { return MultiPolygon.class; } else if (g.getType() == Geobuf.Data.Geometry.Type.GEOMETRYCOLLECTION) { return GeometryCollection.class; } else { return Geometry.class; } } }