Feature API Overview (from 2.2M0)
On the next chapter, we're going to refer to some core GeoTools classes, so lets make a general overview of what those classes are and how they inter-relate.
This overview will be quick, since this document intended audience will be pretty familiar with the GeoTools architecture.
Feature related architectural layers
GeoTools is a library. A good one. As such, it has a layered architecture, from which we're focusing on its feature layer.
So this is the Feature API.
FeatureTypeBuilder allows to programatically build a
FeatureType, and obtaining its (immutable) instance once ready. An
AttributeTypeFactory may be used in the process of building a
FeatureType, to create
AttributeType instances and pass them to
FeatureType instances represents an actual feature class schema, consisting of a name, a namespace, and a set of (potentially complex) properties, where zero or more of them can be geospatially related (Geometry + Coordinate Reference System). As the attributes of a
FeatureType, may be nested in many ways, the fetching of an attribute type from a FeatureType instance was conceived to be XPath aware from the initial API design. Today, this design is being questioned. XPath type access to feature and featuretype members was actually never implemented, and it could be good to leave the API cleaner (i.e. first depth level access only) and provide XPath like expression evaluation from outside, where it makes more sense, avoiding the burden of forcing implementors to deal with a rather complex expression language.
DefaultFeatureType is the general purpose
FeatureType properties, are indeed
AttributeType s have a name and a type, they may or may not allow null values, and may impose lower and upper bounds for the number of value occurrences, both of them defaulting to one occurrence.
AttributeType s may have facets, which are a statement of the restrictions of the value space that attribute values must comply with in order to be acceptable, and provides the mechanisms to parse a value instance from an acceptable input object and to validate that such a value instance adheres to the type facets.
Finally, we need a placeholder for these attribute values.
Feature instances provides such a place, and are uniquely identifiable inside the namespace of its
FeatureCollection is a
Feature by itself, may have a
FeatureType independently of the different schemas of the Features it holds, and provides for traversal and modification of its content by adhering to the
java.util.Collection method contracts.
The notion of a
SimpleFeature is drawn from the OGC's Simple Features for SQL specification - where a simple feature represents a single row in a database table. This extends beyond databases though, to flat files, for example.
SimpleFeatureType have born to allow the development of the complex attribute types support without breaking the pre-complex code, allowing all previous DataStore implementations and related code to continue making with the assumption that a Feature attribute has
1 cardinality and all its attributes are of a simple type.
You may be wondering what's going on with FeatureFactory: why it doesn't implements Factory and where is a FeatureFactory implementation? The point is that FeatureType used to implement FeatureFactory, but it no longer does, which is a good thing after all, since they're so different things. In the mean time, our core developers are thinking hard to find a way of not breaking existing code and still being able of getting rid of FeatureType::create and force using a FeatureFactory instead.
AttributeType class diagram
The AttributeType class hierarchy is perhaps the most important piece of study for this survey, since it shall hold most of the expressive power of the whole Feature API.
We already mentioned what the intent of AttributeType is.
PrimativeAttributeType was introduced to denote that an AttributeType realization is about a simple data type and to add the ability to have restrictions on a particular data primitive in a declarative manner, through the
getRestriction():Filter method. Then,
getRestriction() seems to have been promoted to the AttributeType superinterface. As it will be shown bellow, restrictions on complex data types refers to limiting the order and type of their child properties, and are modeled separatelly, so it would make sense to eliminate
getRestriction from AttributeType since the concept only applies to atomic data types.
GeometryAttributeType adds CRS knowledge for geometric attributes.
GeometricAttributeType, NumericAttributeType, TemporalAttributeType and TextualAttributeType specialize in parsing and validating geometric, numeric, temporal and textual literals respectivelly, relying on DefaultAttributeType for all the common behavior.
That's the "simple features" arm of the API. The complex one is represented by a set of AttributeType realizations each of on serves a specific complex construct, or XML Schema order indicator: choice, sequence, all.
All of them can contain a series of other AttributeTypes, either simple or complex, and gives different meaning as to how these contained types can be used.
ChoiceAttributeType maps to the choice construct in XML Schema, and is meant to represent a complex attribute type where the attribute value can be of one and only one of the types it holds.
ListAttributeType maps to the sequence construct in XML Schema, and is meant to represent a complex attribute type that holds value instances of the attribute types it holds, in the declared order.
SetAttributeType maps to the all construct in XML Schema, and is meant to represent a complex attribute type that holds value instances of the attribute types it holds, in any order, and where the multiplicity of its attributes is limited to
FeatureAttributeType does not maps to a XML Schema construct, but to a GML feature Association property. It is conceptually different from a ListAttributeType in that it have to expose, among its own name, the name of the child FeatureType, to follow the GML Association rule.