View Javadoc
1   package au.gov.amsa.gt;
2   
3   import java.io.File;
4   import java.io.IOException;
5   import java.io.Serializable;
6   import java.util.ArrayList;
7   import java.util.HashMap;
8   import java.util.List;
9   import java.util.Map;
10  
11  import org.geotools.data.DataUtilities;
12  import org.geotools.data.DefaultTransaction;
13  import org.geotools.data.Transaction;
14  import org.geotools.data.collection.ListFeatureCollection;
15  import org.geotools.data.shapefile.ShapefileDataStore;
16  import org.geotools.data.shapefile.ShapefileDataStoreFactory;
17  import org.geotools.data.simple.SimpleFeatureCollection;
18  import org.geotools.data.simple.SimpleFeatureSource;
19  import org.geotools.data.simple.SimpleFeatureStore;
20  import org.geotools.feature.SchemaException;
21  import org.geotools.feature.simple.SimpleFeatureBuilder;
22  import org.geotools.geometry.jts.JTSFactoryFinder;
23  import org.opengis.feature.simple.SimpleFeature;
24  import org.opengis.feature.simple.SimpleFeatureType;
25  
26  import com.vividsolutions.jts.geom.Coordinate;
27  import com.vividsolutions.jts.geom.GeometryFactory;
28  
29  final class ShapefileCreator {
30  
31      public static void createPolygon(List<Coordinate> coords, File output) {
32          List<SimpleFeature> features = new ArrayList<>();
33  
34          final SimpleFeatureType type = createFeatureType();
35          // final SimpleFeatureType type = BasicFeatureTypes.POLYGON;
36          GeometryFactory gf = JTSFactoryFinder.getGeometryFactory();
37          SimpleFeatureBuilder f = new SimpleFeatureBuilder(type);
38  
39          f.add(gf.createPolygon(coords.toArray(new Coordinate[] {})));
40          SimpleFeature feature = f.buildFeature(null);
41          features.add(feature);
42          saveFeaturesToShapefile(features, type, output);
43      }
44  
45      private static SimpleFeatureType createFeatureType() {
46          try {
47              final SimpleFeatureType type = DataUtilities.createType("Region",
48                      "the_geom:Polygon:srid=4326");
49              return type;
50          } catch (SchemaException e) {
51              throw new RuntimeException(e);
52          }
53      }
54  
55      private static void saveFeaturesToShapefile(List<SimpleFeature> features,
56              final SimpleFeatureType type, File output) {
57          try {
58              ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
59  
60              Map<String, Serializable> params = new HashMap<String, Serializable>();
61              params.put("url", output.toURI().toURL());
62              params.put("create spatial index", Boolean.TRUE);
63  
64              ShapefileDataStore newDataStore = (ShapefileDataStore) dataStoreFactory
65                      .createNewDataStore(params);
66  
67              // type is used as a template to describe the file contents
68              newDataStore.createSchema(type);
69  
70              // Write the features to the shapefile
71              Transaction transaction = new DefaultTransaction("create");
72  
73              String typeName = newDataStore.getTypeNames()[0];
74              SimpleFeatureSource featureSource = newDataStore.getFeatureSource(typeName);
75              // SimpleFeatureType shapeType = featureSource.getSchema();
76              /*
77               * The Shapefile format has a couple limitations: - "the_geom" is
78               * always first, and used for the geometry attribute name -
79               * "the_geom" must be of type Point, MultiPoint, MuiltiLineString,
80               * MultiPolygon - Attribute names are limited in length - Not all
81               * data types are supported (example Timestamp represented as Date)
82               * 
83               * Each data store has different limitations so check the resulting
84               * SimpleFeatureType.
85               */
86              // System.out.println("SHAPE:" + shapeType);
87  
88              if (featureSource instanceof SimpleFeatureStore) {
89                  SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
90                  /*
91                   * SimpleFeatureStore has a method to add features from a
92                   * SimpleFeatureCollection object, so we use the
93                   * ListFeatureCollection class to wrap our list of features.
94                   */
95                  SimpleFeatureCollection collection = new ListFeatureCollection(type, features);
96                  featureStore.setTransaction(transaction);
97                  try {
98                      featureStore.addFeatures(collection);
99                      transaction.commit();
100                 } catch (IOException | RuntimeException e) {
101                     e.printStackTrace();
102                     transaction.rollback();
103                 } finally {
104                     transaction.close();
105                 }
106             } else {
107                 throw new RuntimeException(typeName + " does not support read/write access");
108             }
109         } catch (IOException e) {
110             throw new RuntimeException(e);
111         }
112     }
113 }