[GIS] How to create a new shapefile from JTS geometries

dbfgeotoolsjts-topology-suiteshapefile

What I use:
Java 1.7, JTS 1.13, geotools.api 14

What I have finished:
Creating correct JTS geometries from OSM relations, ways and nodes.

What I want to achieve:
Create a CSV file which contains the following data:
the_geom, name, postal_code, country, osm_id

"the_geom" should be a JTS polygon geometry or a null geometry.(Complains ESRI Specification)

The CSV file makes it possible to easy fill up data.

After those CSV file is completely created I want to read that file and create a shapefile from it. Those attributes like name, postal_code and so on, should be written into a dbf file related to new shapefile.

Following this I want to import the new shape and dbf file into PostgreSQL.

Next step to accomplish requirements written above:
How can I create a new shape and dbf file from any collection containing JTS polygon geometries? There are many classes involved but none of them is explained clearly in geotools.org like creating file headers and so on.

Something like:

public class Shapefile
{
  public Shapefile(String filename)
  {
      //..creates necessary stuff
  }

  public void loadFromCSV(String filename, String delimiter)
  {
     //use addGeometry for each row in csv ...
  }

  public void addGeometry(Geometry g, int esriType, Map<String, String> attributes)
  {
     //esriType = 5 for polygons and so on....
     //attributes = attributes for dbf file. Like name, postal_code ...
  }

  public void write() throws IOException
  {
     //Writes output to shapefile and dbf file ...
  }
 }

I hope someone can explain it.

Best Answer

This is a very hard and long winded way of doing it, you really should use GeoTools' datastores (which abstract all this work away)

So assuming that what you actually want is to write some geometries and attributes to PostGIS you can do this:

Decide what is in your dataset and convert your objects to Features (usually SimpleFeatures):

SimpleFeatureType schema = null;
try {
    schema = DataUtilities.createType("", "Location",
        "locations:LineString:srid=4326," + // <- the geometry
                        // attribute:
            "id:Integer" // a number attribute
         //add more attributes here to match your dataset
    );
} catch (SchemaException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    return;
}
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(schema);
//for each feature you have do:
featureBuilder.add(geom);
featureBuilder.add(name);
featureBuilder.add(number);
//+ all the other attributes (probably use a loop)
SimpleFeature feature = featureBuilder.buildFeature(null);
//put them into a collection feats and then convert it to a FeatureCollection
SimpleFeatureCollection collection = new ListFeatureCollection(shpType,
                    feats);

Now you need a PostGIS datastore (or a CSV or ShapeFile if you prefer):

Map<String,Object> params = new HashMap<String,Object>();
params.put( "dbtype", "postgis");
params.put( "host", "localhost");
params.put( "port", 5432);
params.put( "schema", "public");
params.put( "database", "database");
params.put( "user", "postgres");
params.put( "passwd", "postgres");

DataStore dataStore=DataStoreFinder.getDataStore(params);
Transaction transaction = new DefaultTransaction("create");

String typeName = dataStore.getTypeNames()[0];
SimpleFeatureSource featureSource = dataStore
                .getFeatureSource(typeName);
if (featureSource instanceof SimpleFeatureStore) {
            SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;


            featureStore.setTransaction(transaction);
            try {
                List<FeatureId> ids = featureStore.addFeatures(collection);
                transaction.commit();
            } catch (Exception problem) {
                problem.printStackTrace();
                transaction.rollback();
            } finally {
                transaction.close();
            }
            dataStore.dispose();
            return true;
        }