[GIS] Merging shapefiles with GeoTools

geotoolsjavamergeshapefile

I am trying to merge some shapefiles with different schemas in GeoTools. I'm aware of ogr2ogr, but for now I would like to figure out this problem with GeoTools.

The steps I'm taking are:

  1. Create a new Merged shapefile with the schema from the first shapefile in a list
  2. Update the schema of the Merged shapefile file with the subsequent shapefiles in the list of shapefiles
  3. Add features to the merged shapefile
  4. Write the shapefile

The problem is, I can't add features from shapefiles that contain different schemas. OK, that seems straight forward enough.

But when I try to get the schema from a subsequent shapefile and update the Merged shapefile schema, GeoTools throws an exception:

"Schema modification not supported"

Why won't GeoTools let me update the schema? Is there something more than just simply calling

mergedData.updateSchema(shapefileData.getSchema())

public static void init(ArrayList<String> shpArray, String sessionName)
{
    Config config = new Config();

    String sessionData = config.getProperty("pathTo_fade_servlets_data") + "sessions/" + sessionName;
    String newUrl = sessionData + "/tempShp.shp";

    init(newUrl, shpArray.get(0));

    for(int k = 1; k < shpArray.size(); k++)
    {
        mergeShapefile(shpArray.get(k));
    }

    saveShapefile();
}

@SuppressWarnings("rawtypes")
public static void init(String newURL, String copyURL)
{
    try 
    {

        File newFile = new File(newURL);

        Map<String, Serializable> newFileParams = new HashMap<String, Serializable>();
        newFileParams.put("url", newFile.toURI().toURL());

        ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();

        mergedData = (ShapefileDataStore) dataStoreFactory.createNewDataStore(newFileParams);

        //

        File copyFile = new File(copyURL);

        Map<String, Serializable> copyFileParams = new HashMap<String, Serializable>();
        copyFileParams.put("url", copyFile.toURI().toURL());

        ShapefileDataStore shapefileData = (ShapefileDataStore) dataStoreFactory.createNewDataStore(copyFileParams);

        mergedData.createSchema(shapefileData.getSchema());

        mergedFeatureStore = (FeatureStore)mergedData.getFeatureSource(shapefileData.getTypeNames()[0]);

        mergedTransaction = mergedFeatureStore.getTransaction();

    } 
    catch (MalformedURLException e) 
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 
    catch (IOException e) 
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }        
}

@SuppressWarnings({ "rawtypes", "unchecked" })
private synchronized static void mergeShapefile(String url) 
{
    if (url == null) return;

    try 
    {
        File file = new File(url);

        Map<String, Serializable> fileParams = new HashMap<String, Serializable>();
        fileParams.put("url", file.toURI().toURL());

        ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();

        //

        ShapefileDataStore shapefileData = (ShapefileDataStore) dataStoreFactory.createNewDataStore(fileParams);

        FeatureCollection features = shapefileData.getFeatureSource().getFeatures();
        //error occurs here:
        mergedData.updateSchema(shapefileData.getSchema());

        mergedFeatureStore.addFeatures(features);

    } 
    catch (Exception e) 
    {
        e.printStackTrace();
    }
}

 private static void saveShapefile() 
 {
        if (mergedTransaction == null) return;

        try 
        { 

            mergedTransaction.commit();

            mergedTransaction.close();

        } 
        catch (Exception e) 
        {
            e.printStackTrace();
        }
    }

Best Answer

Shapefiles in GeoTools are not mutable - the only way to change the schema of the shapefile is to read it in and write it back out to a new file with the modified schema.

To merge heterogeneous shapefiles you will need to read the schema of each file you want to import and then create a new schema that contains each attribute in those schemas. Then for each file read in the features and convert them to the new schema and write it back out to the new file.

Related Question