The GeoAPI Feature class is used to represents "something that can be drawn on a map".
We are not doing anything creative here in terms of information modelling. GeoAPI provides a normal Data Model, Query Model, Metadata separation.
References:
- GeoAPI javadocs
- ISO19107
- OGC General Feature Model
- Geographic Markup Language
Feature Model
Data Model
We store information in a data structure composed of Feature, Attributes, and Associations.

To create a feature we make use of a SimpleFeatureFactory
Query Model
Use Expression to access information stored in the data model. Use Filter to select features that are of interest.
final FilterFactory ff = CommonFactoryFinder.getFilterFactory( GeoTools.getDefaultHints ); Filter filter = ff.propertyLessThan( ff.property( "AGE"), ff.literal( 12 ) ); FeatureCollection<SimpleFeature> features = featureSource.getFeatures( filter ); features.accepts( new FeatureVisitor<SimpleFeature>() ){ public void visit( SimpleFeature feature ){ Expression query = ff.property( "NAME" ); String name = query.evaulate( feature, String.class ); System.out.println( feature.getID() + " is named: "+ name ); } }, null );
Metadata Model
Describe the represented information. You can review this description in order to figure out the attribute names when making a request. If you are creating new content you should check the feature type to ensure your content is valid.

Descriptors
A SimpleFeatureType is defined in terms of a List of AttributeDescriptors. Each AttributeDescriptor has a Name and a AttributeType; you can use the same AttributeType for several AttributeDescriptors.
Simple Feature
We have created an extension of Feature and FeatureType to provide a few helper methods when the following conditions are met.
- a feature's properties are limited to mandatory GeometryAttribute and Attribute (no complex attributes or multiplicity allowed).
- attributes values may be null; but each attribute must be represented
These restrictions match the abilities of a simple shapefile or database table.
Discussion
Comparison to Java
It may help you to compare the ideas presented here to something you are already familiar with ...
- The data structure Feature is used to hold information. Each feature "belongs to" a FeatureType which is used to describe valid contents. This is a dynamic type system because FeatureType is a data structure we can define at runtime.
- The data structure Object is used to hold information. Each Object "belongs to" a Class which is used to describe valid contents. This is a static type system because Class is a data structure we need to compile before the application is started.
(This table is a quick comparison please forgive and correct any mistakes)
| Java | Feature Model | |
|---|---|---|
| static type system | dynamic type system | |
| (data model) | ||
| Object | SimpleFeature | |
| (reflection) | Attribute | |
| (reflection) | GeometryAttribute | |
| (metadata) | ||
| Class | SimpleFeatureType | |
| Field | AttributeDescriptor | |
| GeometryAttributeDescriptor | ||
| Method | OperationType | |
| Filed.getType() | AttributeDescriptor.getType().getBinding() | |
| Field.getName() | AttributeDescriptor.getName().getLocalName() | |
| (query model) | ||
| Field.get( obj ) | expression.evaulate( feature, Class ) |
|
Class definition: class Flag {
Point location;
String name;
int classification;
double height;
}
|
SimpleFeatureType definition: SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder(); b.setName( "Flag" ); b.setCRS( DefaultGeographicCRS.WSG84 ); b.add( "location", Point.class ); b.add( "name", String.class ); b.add( "classification", Integer.class ); b.add( "height", Double.class ); |
Comparison to Java Beans
| Beans | Feature Model | |
|---|---|---|
| dynamic type system | dynamic type system | |
| (data model) | ||
| Object | SimpleFeature | |
| (reflection) | Attribute | |
| (reflection) | GeometryAttribute | |
| (metadata) | ||
| BeanInfo | SimpleFeatureType | |
| PropertyDescriptor | AttributeDescriptor | |
| GeometryAttributeDescriptor | ||
| MethodDescriptor | OperationType | |
| PropertyDescriptor.getPropertyType() | AttributeDescriptor.getType().getBinding() | |
| PropertyDescriptor.getName() | AttributeDescriptor.getName().getLocalName() | |
| (query model) | ||
| PropertyDescriptor.getReadMethod().invoke( obj ) | expression.evaulate( feature, Class ) |