GeoTools

OSGeo

Table Of Contents

Previous topic

AbstractDataStore Tutorial

Next topic

Library

This Page

ContentDataStore Tutorial

Writing a new DataStore for GeoTools is one of the best ways to get involved in the project, as writing it will make clear many of the core concepts of the API.

The modular nature of GeoTools allows new DataStores to quickly become part of the next release (we have an “unsupported” directory just for this purpose), so that new formats are can quickly be distributed to to all GeoTools users.

Note

AbstractDataStore is the original GeoTools 2.0 class; since that time we have learned a number of tricks and have a much easier starting point for you in the form of ContentDataStore.

While ContentDataStore is a lot less work to use; it is not yet as fully featured as AbstractDataStore. You may wish to try both tutorials before deciding on a course of action.

Terminology

The DataStore interface borrows most of its concepts and some of its syntax from the OpenGIS Consortium (OGC) Web Feature Server Specification:

  • Feature - atomic unit of geographic information
  • FeatureType - keeps track of what attributes each Feature can hold
  • FeatureID - a unique id associated with each Feature (must start with a non-numeric character)

Introduction

An earlier tutorial produced a bit of code to read in a comma seperated value file; and produce a feature collection (which we could save out using the shapefile datastore class).

This time out we are going to make a DataStore.

Here was the sample file we used:

  1. Create a text file location.csv and copy and paste the following locations into it:

    LAT, LON, CITY, NUMBER
    46.066667, 11.116667, Trento, 140
    44.9441, -93.0852, St Paul, 125
    13.752222, 100.493889, Bangkok, 150
    45.420833, -75.69, Ottawa, 200
    44.9801, -93.251867, Minneapolis, 350
    46.519833, 6.6335, Lausanne, 560
    48.428611, -123.365556, Victoria, 721
    -33.925278, 18.423889, Cape Town, 550
    -33.859972, 151.211111, Sydney, 436
    
  2. Or download locations.csv.

Approach

Here is our strategy for representing GeoTools concepts with a CSV file.

  • FeatureID or FID - uniquely defines a Feature.

    We will use the row number in our CSV file.

  • FeatureType

    Same as the name of the .csv file (ie. “locations” for locations.csv)

  • DataStore

    We will create a CSVDataStore to access all the FeatureTypes (.csv files) in a directory

  • FeatureType or Schema

    We will represent the names of the columns in our CSV (and if possible their types).

  • Geometry

    We will try and recognise several columns and map them into Point x and y ordinates.

JavaCSV Reader

To read csv files this time out we are going to make use of the Java CSV Reader project.

Time to create a new project making use of this library:

  1. Create a csv project using maven

  2. Use the following maven dependencies:

      <dependencies>
        <dependency>
          <groupId>org.geotools</groupId>
          <artifactId>gt-api</artifactId>
          <version>${project.version}</version>
        </dependency>
        <dependency>
          <groupId>org.geotools</groupId>
          <artifactId>gt-data</artifactId>
          <version>${project.version}</version>
        </dependency>
        <dependency>
          <groupId>org.geotools</groupId>
          <artifactId>gt-epsg-hsql</artifactId>
          <version>${geotools.version}</version>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.javacsv</groupId>
            <artifactId>javacsv</artifactId>
            <version>2.0</version>
        </dependency>
      </dependencies>
    
  3. Or download pom.xml

Creating CSVDataStore

The first step is to create a basic DataStore that only supports feature extraction. We will read data from a csv file into the GeoTools feature model.

To implement a DataStore we will subclass ContentDataStore. This is a helpful base class for making new kinds of content available to GeoTools. The GeoTools library works with an interaction model very similar to a database - with transactions and locks. ContentDataStore is going to handle all of this for us - as long as we can teach it how to access our content.

ContentDataStore requires us to implement the following two methods:

  • createTypeNames() - name of all the different kinds of content (tables or types). In a CSV file we will only have one kind of content
  • createFeatureSource(ContentEntry entry)

The class ContentEntry is a bit of a scratch pad used to keep track of things for each type.

Initially we are going to make a read-only datastore accessing CSV content:

  1. To begin create the file CSVDataStore extending ContentDataStore

    package org.geotools.tutorial.datastore;
    
    import java.io.File;
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.Reader;
    import java.util.Collections;
    import java.util.List;
    
    import org.geotools.data.Query;
    import org.geotools.data.store.ContentDataStore;
    import org.geotools.data.store.ContentEntry;
    import org.geotools.data.store.ContentFeatureSource;
    import org.geotools.feature.NameImpl;
    import org.opengis.feature.type.Name;
    
    import com.csvreader.CsvReader;
    
    public class CSVDataStore extends ContentDataStore {
    
  2. We are going to be working with a single CSV file

        File file;
        
        public CSVDataStore( File file ){
            this.file = file;
        }
    

Listing TypeNames

A DataStore may provide access to several different types of information. The method createTypeNames provides a list of the available types. This is called once; and then the same list is returned by ContentDataStore.getTypeNames() each time. (This allows you to do some real work; such as connecting to a web service or parsing a large file, without worrying about doing it many times).

For our purposes this list will be the name of the csv file.

  1. We can now implement createTypeNames() returning a filename

        protected List<Name> createTypeNames() throws IOException {
            String name = file.getName();
            name = name.substring(0, name.lastIndexOf('.'));
            
            Name typeName = new NameImpl( name );
            return Collections.singletonList(typeName);
        }
    

To be continued

I have not been able to complete writing this tutorial ... to volunteer to test please ask for Jody Garnett on the geotools user list.

Here are the working downloads: