FeatureType Survey - STEMLab/geotools GitHub Wiki
The GeoTools FeatureType model has born with the concept of being mappeable to GML schemas, in the hope of being directly usable by a Web Feature Service implementation. The concepts governing the FeatureType model was deeply inspired on the Simple Features for SQL implementation specification. That meant that for a while, this model served perfectly for the representation of simple, also called flat, feature types, which are those whose properties are all scalar.
But the notion of complex feature types, which includes multiple instances of a given property type, nested features, etc, was always there, mostly because of the need of a deeper support of GML. This lack of support for complex constructs forced Rob A. and his partners to develop the complex_sco GeoServer branch to bypass this limitation through a customized mechanism for querying and encoding scienticif data such as water quality and geochemistry datasets.
Then, Chris Holmes and David Zwiers joint together and had a try at extending the GeoTools feature type model for a wider synchronization of both schema models. As a result, we have now a potentially way more useful type hierarchy to model complex schemas and an outdated GeoServer branch with functionality needed in the core product.
In this document we will open up a discussion of the 2.1.0 status of the FeatureType model to identify the key aspects that still need to be enhanced, and hopefully outline a strategy for the achievement of the level of expressiveness needed to take a FeatureType instance and construct a to more meaningful GML schema.
- To evaluate the current coverage level of the FeatureType API regarding GML Schemas
- To propose the enhancements needed for a better, if not optimal, coverage of the GML Schema constructs
The current FeatureType capabilities includes only the representation of flat schemas. A flat schema, or simple feature type, maps to a complex xml type whose attributes are only a sequence of scalar attributes:
<xs:element name="road">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="centerline" type="gml:LineStringPropertyType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
Simple attributes may also have restrictions (aka, facets):
<xs:element name="road">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="code">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="[A-Z][A-Z][A-Z]"/>
</xs:restriction>
</xs:simpleType
</xs:element>
<xs:element name="centerline" type="gml:LineStringPropertyType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
The GeoTools AttributeType interface, which is the superinterface for all the different possible types of attributes, has an initial attempt of supporting restrictions, or facets, by using a Filter to express the restriction, and convenient methods for expressing multiplicity and nillability:
AttributeType.java
public interface AttributeType{
...
Filter getRestriction();
boolean isNillable();
int getMinOccurs();
int getMaxOccurs();
...
}
The drawback is that still no DataStore implementation is able of meaningfully using this abilities.
It is not the goal of the GeoTools FeatureType API to be able of reflecting each and every
possible XML schema, but only those valid for GML. Better said, GML schemas.
GML schemas express the properties of a Feature as elements, never as attributes. This is, though,
a GML recommendation, since nothing can prevent one from declaring a set of element attributes in a
GML/XML schema.
The point is that we're not going to worry, through this document, that the FeatureType API should
be able to reflect if a given feature property maps to a XML attribute or to a XML element. We'll
assume that feature properties always maps to a Feature property in the GML sense, following the
Object/property pattern.
In the case that, for reasons of Application Schema design, a GeoTools AttributeType may need to be
mapped to a XML attribute for Application Schema conformance, other mechanisms should exist to
perform such a mapping, that have nothing to do with the way the GeoTools FeatureType API is or will
be modeled.
There are, though, a few attributes that most GML instances use: gml:id
, xlink:href
and
srsName
. They're already being handled at Feature to GML serialization time.
Thus, the GeoTools FeatureType API does not needs to worry about any specific issue related to XML
attributes, or to XML at all, beyond ensuring that it provides a straightforward mechanism of
modeling a GML schema.
GML supports relationships between features via a simple "association" property that allows inline containment of related features, or use of xlink to reference them. The latter is perhaps the critical one to implement, since duplication of contained features with identical gml:ids is not legal.
We also need to expose the types of related features through the API because it is necessary to formulate requests - e.g. find roads that join junction B33454
To support the mapping of a GML schema, the FeatureType API needs at least to support the basic XML
Schema types.
XML Schema types can be simple or complex:
-
Simple data types: simple types defines XML elements that have no attributes. They can be:
-
Atomic: The - lexical space- of an - atomic- data type is a set of literals whose
internal structure is specific to the datatype in question. For instance, they can be:
- Primitive datatypes are those that are not defined in terms of other datatypes; they exist ab initio.
- Derived datatypes are those that are defined in terms of other datatypes.
- List datatypes are those having values each of which consists of a finite-length (possibly empty) sequence of values of an - atomic- datatype.
- Union datatypes are those whose - value space- s and - lexical space- s are the union of the - value space- s and - lexical space- s of one or more other datatypes. Much like a union in C.
-
Atomic: The - lexical space- of an - atomic- data type is a set of literals whose
internal structure is specific to the datatype in question. For instance, they can be:
-
Complex data types provides for:
- Constraining element information item [children] to be empty, or to conform to a specified element-only or mixed content model,
- Using the mechanisms of Type Definition Hierarchy to derive a complex type from another simple or complex type.
- Controlling the permission to substitute, in an instance, elements of a derived type for elements declared in a content model to be of a given complex type.
Simple types may have restrictions, also called facets, which are a limitation of its value space.
F.2.1.2.11 Predefined basic types (page 527)
The simple types from the XML Schema and GML namespace listed in the left hand column of Table 22 may be used in the GML application schema. All other simple types from these namespaces shall not be used in a GML application schema.
This sections contains a review of the relevant XML Schema types that the API should support in order to allow a bidirectional mapping of an XML Schema and a FeatureType instance.
This diagram shows primitive and derived built in data type of XML Schema that needs to be supported by the AttributeType model for strongly mapping a GML schema.
List data types are simple types that are defined as an aggregation or collection of a given atomic data type. Thus, they're always derived from the concrete atomic type.
Example:
<xs:element name="byteList">
<xs:simpleType>
<xs:list itemType="xs:byte"/>
</xs:simpleType>
</xs:element>
This XML Schema fragment defines an element named byteList
whose instances may hold only a space
separated list of byte
literals. If we had to represent it in Java, would do it simply with a
List<Byte>
.
An instance of this element may look like:
<byteList>1 2 3 127</byteList>
The following facets apply to list data types:
When evaluating a length type restriction, the unit of length is measured in number of list items.
The - value space- and - lexical space- of a - union- datatype are the union of the - value space- s and - lexical space- s of its - memberTypes- . - union- datatypes are always - derived- . The member types of a union data type may be any combination of one or more atomic or list data types.
Example:
<xs:simpleType name="aUniontType">
<xs:union>
<xs:simpleType>
<xs:restriction base="gml:booleanOrNull" />
</xs:simpleType>
<xs:simpleType>
<xs:restriction base="gml:doubleOrNull" />
</xs:simpleType>
<xs:simpleType>
<xs:restriction base="xs:token" />
</xs:simpleType>
</xs:union>
</xs:simpleType>
This XML Schema fragment defines an type whose instances may hold either a gml:booleanOrNull
,
gml:doubleOrNull
, or xs:token
Instances of this element may look like:
<unionInstance xsi:type="aUnionType">Null</unionInstance>
<unionInstance xsi:type="aUnionType">1.0</unionInstance>
<unionInstance xsi:type="aUnionType">JUST_A_TOKEN</unionInstance>
<unionInstance xsi:type="aUnionType">1</unionInstance>
âšī¸ There are no facets defined for union data types. Instead, value instances may validate against one of the member data types of the union.
A string that represents the ID attribute in XML.The BNF for an ID attribute is as follows:
NCName ::= (Letter |'_') (NCNameChar)* /* An XML Name, minus the ":" */
NCNameChar ::= Letter |Digit |'.' |'-' |'_'
|CombiningChar |
Extender
Restrictions:
A string that does not contain line feeds, carriage returns, or tabs
Restrictions: none
A string
Restrictions: none
Restrictions: token
A string that does not contain line feeds, carriage returns, tabs, leading or trailing spaces, or multiple spaces
Restrictions: none
Defines a date value
Restrictions:
Defines a date and time value
Defines a time interval
Defines a part of a date - the day (DD)
Defines a part of a date - the month (MM)
Defines a part of a date - the month and day (MM-DD)
Defines a part of a date - the year (YYYY)
Defines a part of a date - the year and month (YYYY-MM)
Defines a time value
A signed 8-bit integer
Restrictions:
- enumeration
- fractionDigits
- maxExclusive
- maxInclusive
- minExclusive
- minInclusive
- pattern
- totalDigits
- whiteSpace
IEEE single-precision 32-bit floating point type
IEEE double-precision 64-bit floating point type
A decimal value
A signed 32-bit integer
An integer value whose value space is the infinite set
A signed 64-bit integer. long is derived from integer by setting the value of maxInclusive to be 9223372036854775807 and minInclusive to be -9223372036854775808.
An integer <= -1
An integer >= 0
An integer <= 0
An integer <= 1
A signed 16-bit integer
An unsigned 64-bit integer
An unsigned 32-bit integer
An unsigned 16-bit integer
An unsigned 8-bit integer
boolean has the - value space- required to support the mathematical concept of binary-valued logic: {true, false, 1, 0}.
Restrictions:
represents Base64-encoded arbitrary binary data
Restrictions:
- length (measured in octets (8 bits) of binary data)
- minLength
- maxLength
- pattern
- enumeration
- whiteSpace
represents arbitrary hex-encoded binary data
represents a Uniform Resource Identifier Reference (URI)
Restrictions:
I think the following types needs not to have direct mappings at the AttributeType level, though I
may be wrong with some of them:
QName, NOTATION, language, Name, NCName, NMTOKEN, NMTOKENS, IDREF, IDREFS, ENTITY, ENTITIES.
One of the main goals of the "complex schema" support project is that the GeoTools FeatureType API
becomes expressive enough as to seamlessly represent a GML3 schema. That is, one with complex
features.
Complex features are those that have complex properties.
Complex properties may be as complex as any XML Schema complex type
definition
A complex property may be complex by its own, or
because it is a Feature association.
The following are the requirements that our API must support in order to be capable of modeling complex features:
Jody's feedback
âšī¸
In particular ensuring that the modeling power of FeatureType / AttributeType are capable of describing both FeatureCollections and Features. One way I have approached the problem is to ensure that the correct XPath expression can be generated based on the information available in the FeatureType/AttributeType, and that the Feature / FeatureCollection data structure is complete enough that the expression can be used successfully to process an XPath expression.
This leads me to the following simple QA tests:
- Can I make an SLD document based on FeatureType / AttributeType description?
- Using FeatureCollection.getFeatureType() can I figure out what the child features are?
Is FeatureType an AttributeType?
âšī¸
Jody Garnett
The relationship between FeatureType (not present in your diagram), ListAttributeType and
FeatureAttributeType leads me to think that FeatureType may better be served extending
AttributeType.
Chris Holmes
We've actually talked about doing that every single time we've even thought about redoing the
Feature stuff, and always decided against it.
IanS has many good arguments on why this is a bad thing, in the archives. It comes down to putting
too much responsibility on the FeatureType if it extends AttributeType, it starts to do two things
when it should just do one. I can dig up the arguments again if needed, as I always forget, but
every time I read them I'm convinced again.
A complex FeatureType may have zero to N geometric attributes.
Geometric attributes are those whose values are a Geometry primitive or a Geometry aggregation. For
instance, Point, LineString, MultiPoint, etc.
They're always represented in GML as an association, where the property name is the place holder
for the actual geometry element. For example:
<Road>
<code>66</code>
<the_geom>
<gml:LineString><gml:coordinates>...</gml:coordinates></gml:LineString>
</the_geom>
</Road>
is an instance of a Road feature type, with a geometric property named the_geom
.
That a feature type supports multiple geometric attributes means that more than one of its properties are of a geometry type. Like in:
<Road>
<code>66</code>
<from_point>
<gml:location>....</gml:location>
</from_point>
<to_point>
<gml:location>....</gml:location>
</to_point>
<the_geom>
<gml:LineString><gml:coordinates>...</gml:coordinates></gml:LineString>
</the_geom>
</Road>
In this case, the Road feature type has three geometric attributes, from_point
, to_point
, and
the_geom
.
The following considerations apply to features with multiple geometric properties:
- the bounds of a Feature instance is the union of the bounds of all its geometric attributes.
- one of the geometric attributes must be the default geometry.
âšī¸ fortunately this issues are already well covered by the GeoTools Feature API:
- a FeatureType may have as many GeometryAttributes as it wants
- the bounds are calculated
- the default geometry must be explicitly set by the data provider, is obtained by
Feature::getDefaultGeometry():Geometry
, and which attribute type is the default geometric one is obtained throughFeatureType::getDefaultGeometry():GeometryAttributeType
A complex property is one that contains other complex or scalar properties.
There are three different kinds of complex properties, mandated by the XML Schema order indicators:
choice, sequence, and all.
Theese are order indicators, that group properties affecting how they may appear.
Thus, these order indicators specifies a content model or schema for the property they
belongs to, independently of the type of values of the properties they allow as children.
Following is a brief explanation of how these three different content models for complex properties act:
A choice is like a union in C. It contains another properties but a value instance of this type has to of one of the types in the choice:
choice
<xs:element name="the_geom">
<xs:complexType>
<xs:choice>
<xs:element ref="gml:Point"/>
<xs:element ref="gml:Polygon"/>
</xs:choice>
</xs:complexType>
</xs:element>
In this case, an instance of this property may consist of either a gml:Point
or a gml:Polygon
element, but not both.
A sequence indicator specifies that the nested attributes must appear in the specified order
sequence
<xs:element name="the_geom">
<xs:complexType>
<xs:sequence>
<xs:element ref="gml:Point" minoccurs="0" maxoccurs="unbounded"/>
<xs:element ref="gml:Polygon"/>
</xs:sequence>
</xs:complexType>
</xs:element>
In this case, an instance of this property may consist of any number of gml:Point
elemets (see
minoccurs and maxoccurs), followed by one gml:Polygon
element, in that order.
The all indicator specifies that the child elements can appear in any order and that each child
element must occur once and only once
When using the all indicator you can set minOccurs to 0 or 1 and maxOccurs can only be set to
1
all
<xs:element name="the_geom">
<xs:complexType>
<xs:all>
<xs:element ref="gml:Point" minoccurs="0"/>
<xs:element ref="gml:Polygon"/>
</xs:all>
</xs:complexType>
</xs:element>
In this case, an instance of this property may consist of zero or one gml:Point
elemets and one
gml:Polygon
element, in any order.
In GML, a Feature property value may be indeed another Feature instance. We'll call them nested
Features.
Nested Features is a special case of complex properties, governed by a GML convention: the schema
of a nested feature is mandated to be of GML FeaturePropertyType
, following the
gml:AssociationType pattern.
schema
sample insance
<xs:complexType name="RoadType">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureType">
<xs:sequence>
<xs:element name="roadName" type="xs:string"/>
<xs:element name="centerLine" type="gml:LineStringPropertyType"/>
<xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="RoadPropertyType">
<xs:annotation>
<xs:documentation>Container for a Road -
follow gml:AssociationType pattern.</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:restriction base="gml:FeaturePropertyType">
<xs:sequence>
<xs:element ref="Road" />
</xs:sequence>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="CityType">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureType">
<xs:sequence>
<xs:element name="cityName" type="xs:string"/>
<xs:element name="roadProperty" maxOccurs="unbounded" type="RoadPropertyType"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name='Road' type='RoadType' substitutionGroup="gml:_Feature" />
<xs:element name='City' type='CityType' substitutionGroup="gml:_Feature" />
<City gml:id="city.1">
<cityName>Bilbao</cityName>
<roadProperty>
<Road gml:id="road.1">
<roadName>Kastrexana</roadName>
<centerLine>
<gml:LineString>....</gml:LineString>
</centerLine>
</Road>
</roadProperty>
<roadProperty>
<Road gml:id="road.2">
<roadName>A8</roadName>
<centerLine>
<gml:LineString>....</gml:LineString>
</centerLine>
</Road>
</roadProperty>
</City>
A feature association instance can be encoded by value or by
reference. By value means that in the XML document
instance, the feature property definition is inlined on the corresponding xml element body, and by
reference means that it exists somewhere else in the document, and thus it is remotely referenced
by its unique identifier by using a xlink:href
element attribute.
There is a restriction, though, on the way that nested features can be encoded in a GML document:
- Features has a FID
- FIDs are used to uniquely identify a feature instance through the
gml:id
attribute - IDs must be unique on a GML document
â ī¸ so you can't encode the same feature twice on the same GML document.
Mad Idea
âšī¸
This makes me think ahead on the concept of a LazyFeature, one that has only FID. Actually it may be proxied, so if client code doesn't know about the existence of LazyFeatures, the feature instance could go fetch its contents to the back end, but if the client code knows about LazyFeatures, it may choose not to consume it, since it knows the Feature contents were previously acquired.
GML encoding sketch
FeatureIterator features = ...
while(features.hasNext()){
Feature f = features.next();
encodeFeature(f);
}
features.close();
...
private void encodeFeature(Feature f){
FeatureType schema = f.getFeatureType();
if( f instanceof LazyFeature ){
//just writes <propertyName xlink:href="id"/>
encodeByReferenceFeature(schema, f.getID());
}else{
startFeature(schema, f.getID());
AttributeType []types = schema.getAttributeTypes();
encodeAttributes(f.getAttributes(), types);
endFeature(schema);
}
}
private void encodeAttributes(Object[] values, FeatureType schema){
for(int i = 0; i < values.length; i++){
if(schema.getAttribute(i) instanceof FeatureAttributeType){
encodeFeature((Feature)f);
}else{
//.... encode simple types, etc, etc
}
}
}
Output
<wfs:FeatureCollection>
<gml:boundedBy>...
<featureMember>
<City gml:id="city.1">
<name>Rosario</name>
<intersects>
<Road gml:id="road.1">
<name>Ruta 9</name>
</Road>
</intersects>
</City>
</featureMember>
<featureMember>
<City gml:id="city.2">
<name>Buenos Aires</name>
<intersects xlink:href="#road.1"/>
</City>
</featureMember>
<featureMember>
<City gml:id="city.3">
<name>Cordoba</name>
<intersects xlink:href="#road.1"/>
</City>
</featureMember>
</wfs:FeatureCollection>
Benefit: such an approach may easy the job of cross DataStore joins, by not having to do a full join at all, if you can guarantee or force that the "foreign key" on your master table is the FID of the features on the slave table.
As in XML Schema, namespaces are used in GML schemas to relate to externally defined types. This is
extremelly important for building community schemas, which aims for semantic interoperability
instead of just common protocols.
Suppose in your country's transportation organization has ellaborated a schema for defining
inter-agency interchange of transportation information. By the other hand, your province admin
urbanism department has a schema modeling the urban infrastructures, which includes information of
the roads from the transportation schema, for each city:
<urb:City>
<urb:cityName>Bilbao</urb:cityName>
<tr:roadProperty>
<tr:Road>
<tr:roadName>Kastrexana</tr:roadName>
<tr:centerLine>
<gml:LineString>....</gml:LineString>
</tr:centerLine>
</tr:Road>
</tr:roadProperty>
<tr:roadProperty>
<tr:Road>
<tr:roadName>A8</tr:roadName>
<tr:centerLine>
<gml:LineString>....</gml:LineString>
</tr:centerLine>
</tr:Road>
</tr:roadProperty>
</urb:City>
In this example, the
urb
namespace prefix belongs to the feature types defined in a hipotetical urbanism schema, andtr
namespace prefix to the ones defined in the hipotetical transportation schema.
The urbanism schema may look something like this:
hipotetical urbanism schema
<xs:schema targetNamespace="http://myprov.org/urbanism"
xmlns:urb="http://myprov.org/urbanism"
xmlns:tr="http://mycountry.org/transportation"
xmlns:gml="http://www.opengis.net/gml"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
version="1.0">
<xs:import namespace="http://www.opengis.net/gml" schemaLocation="../schemas.opengis.net/gml/3.1.1/base/feature.xsd" />
<xs:import namespace="http://mycountry.org/transportation" schemaLocation="transportation.xsd" />
<xs:complexType name="CityType">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureType">
<xs:sequence>
<xs:element name="cityName" type="xs:string"/>
<xs:element name="roadProperty" minOccurs="0" maxOccurs="unbounded" type="tr:RoadPropertyType"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name='City' type='urb:CityType' substitutionGroup="gml:_Feature" />
</xs:schema>
There is a problem, though, that arises from an attribute being able of belonging to a different
namespace:
For example:
<element name="nameAttribute">
<complexType>
<choice>
<element name="name" type="xs:string"/>
<element ref="gml:name"/>
</choice>
</complexType>
</element>
Despite its aparent unusefulness, it's a completely valid example.
An instance of this schema fragment can be either
<myNs:nameAttribute>
<myNs:name>theName</myNs:name>
<myNs:nameAttribute>
or
<myNs:nameAttribute>
<gml:name>theName</gml:name>
<myNs:nameAttribute>
now try to do feature.setAttribute("nameAttribute", "theName")
....
đĄ it may be the case that a single attribute name is not enough to set an attribute value, we might need QNames (qualified names). So it may worth taking a look at GeoAPI's GenericName
By the other hand, â what would be really consistent:
-
feature.setAttribute("nameAttribute", "theName")
-
feature.setAttribute("nameAttribute/gml:name", "theName")
-
feature.setAttribute("nameAttribute", Arrays.asList( new String[]{null, "theName"} )
-
AttributeType type = feature.getFeatureType().getAttributeType("nameAttribute").getAttributeType("http://www.opengis.org/gml", "name"); feature.setAttribute(type, "theName" )
Example #1 does not solves the problem, its ambiguous.
Example #2 may be enough, provided that at least relative location
paths are directly supported.
âšī¸ Example #3 exemplifies the current approach for
dealing with complex types: every complex type value is a java.util.List
. Note it has some
invonvenients, though: It partially addresses the ambiguity described above, since attribute
values are order dependant of the declaration of child types, BUT: this order dependence is
only applicable to the semantics of a sequence construct. For a choice, the value might be a
single Object (though it is managed as being always a singleton List?), and for an all construct
there is no way, since the semantics of all means its children can appear in any order; so how
do you assign a value to one of the name attributes in the example above?
Example #4 might be safer: it doesn't require intrinsic XPath support and is namespace aware, but
there is a strong dependence of the internal data structure.
Now lets try the inverse case: getting the attribute value:
-
Object value = feature.getAttribute("nameAttribute")
-
Object value1 = feature.getAttribute("nameAttribute/gml:name") Object value2 = feature.getAttribute("nameAttribute/myNs:name")
-
List values = (List) feature.getAttribute("nameAttribute")
-
AttributeType type1 = feature.getFeatureType().getAttributeType("nameAttribute").getAttributeType("http://www.opengis.org/gml", "name"); AttributeType type2 = feature.getFeatureType().getAttributeType("nameAttribute").getAttributeType("http://www.myNs.org", "name"); Object val1 = feature.getAttribute(type) Object val2 = feature.getAttribute(type)
To evaluate the usefulness of those constructs, lets suppose we have to encode a GML document based
on the previous reading examples:
Example #1: you got the value. Which one?
Example #2: ehem... I'm sure I would not use that API.
Example #3 (aka, how things work right now): again, ok for order dependant attributes, but what
for all? you got List[null, "theName"], what's null? gml:name or myNs:name?
Example #4: apart of looking a bit burdened, it may work, except that you need a deep
pre-knowledge of the whole structure, and it may make a lot more of sense to be able of just asking
for the value of "nameAttribute" and being able of knowing which of its sub elements the value
corresponds to.
It seems, like in the XML world, that a value has no sense outstide its context (i.e. its element name, on our case, its attribute).
What about....
âšī¸
//a tuple for handling attribute values
interface AttributeValue{
/** which attribute type the value belongs to */
AttributeType getType();
/**
* Returns the value of the attribute instance.
* The value of the attribute instance is defined to be:
* - a List of actual values if getType().getMaxOccurs() > 1
* - an actual value otherwhise.
* An actual value is defined to be:
* - an AttributeValue if the value's type is complex
* - a value literal if the value's type is simple
*/
Object getValue();
void setValue(Object value);
}
Feature.java
interface Feature{
...
/** value.getType() may address a leaf attribute (aka, a SimpleAttributeType),
* or a complex attribute, in which case value.getValue() will be another
* AttributeValue up to the nesting level desired.
*/
void setAttribute(AttributeValue value);
/** attName must address a leaf attribute */
void setAttribute(GenericName attName, Object value);
AttributeValue getAttribute(GenericName attName);
/** returns a literal if att is simple, or an AttributeValue
* if type is complex
*/
Object getAttribute(AttributeType att);
}
Though this example is far from being a complete model, its intention is to show that:
- A Feature instance, as a complex structure, actually holds a sequence of tree like attribute values
- Those attribute values have to be typed
- The
AttributeValue
tuple defines by itself a tree structure of typed values that:- uniquelly identifies a node in the hierarchy
- avoids ambiguity in the interpretation of the value's type
A FeatureCollection is defined in GML as a Feature of type FeatureCollectionType, which in turn extends AbstractFeatureType.
Said that, the notably thing is that a FeatureCollection does not differs from any other derived feature type that you may define in order to allow the holding of any number of other Feature instances.
But if you need such a thing, the recomendation is to use a FeatureCollection instead of reinventing the wheel, since that's why there are so many predefined elements and types in GML.
So, as FeatureCollection is already well defined, it has a well defined schema:\
abstract AbstractFeatureCollectionType extends AbstractFeatureType
featureMember (0..N)
featureMembers (0..1)
FeatureCollectionType extends AbstractFeatureCollectionType
where featureMember is the FeatureCollection's AttributeType (following the gml:AssociationType pattern) that allows it to hold any number of features of any FeatureType, and featureMember*s* may be used to hold any number of features without enclosing each one on a featureMember element (since it is an array of features).
The difference between this two ways of holding features on a feature collection is not just the saving of space in encoding (one featureMember element for each Feature vs just one featureMembers element for the whole document), but the ability to reference a remote feature using XLinking that featureMember has against the featureMembers array.
With all this small backgroung in mind, what worths being said is that you can use a FeatureCollection the same way as you use a Feature instance, that a FeatureCollection's member may indeed be another FeatureCollection, and so on.
đĄ The other notably thing is, as long as GML
is intended as a basis for defining specific application domain schemas, its obvious that you can
extend (actually restrict) the value space of a FeatureCollection so its schema decalres what
exactly are the allowable Feature types for the collection.
âšī¸ So keep in mind the previous statement for
further discussion, as it seems there is some confusion (it could be me, of cuorse):
- a FeatureCollection, as defined, allows for the containment of any type of Feature instances
- you can restrict which ones to allow, but this requires the definition of your own restricted FeatureCollectionType, deriving from the base FeatureCollection type
What about GeoTools FeatureCollections ?
Well, abviously it would be desirable to treat a GeoTools FeatureCollection instance as a single
Feature in a number of situations, though it is possible nowadays, the following is a list of
current situation:
- đ FeatureCollection properly requires that
its schema is of
gml:AbstractFeatureCollectionType
type - đ FeatureCollection is thought on the basis of
GML < 3.1.1, where
gml:AbstractFeatureCollectionType
descends fromgml:BoundedFeatureType
, makingboundedBy
property mandatory. This is no more the case as for GML 3.1.1, which we should target, as it is the first version that completely validates and the one that will drive future developments in the short term. - đ it may act as a derived FeatureCollection, due
to the ability of knowing the FeatureType of its contained Feature instances (note the
distinction between the #FeatureCollection schema
and the schema of its contained features). This ability is useful since most the time you will
make a query over a DataStore's FeatureType and obtain a FeatureCollection as result, all of
which are of the same type. âšī¸ So in this case
we're gracefuly extending gml:FeatureCollection adding this extra behavior: restricting its
value space. The way to notice the existence of this restriction is if
getSchema():FeatureType
does not returnsnull
. \(on) So a more usefull extention may be the ability to restrict the allowable features to more than oneFeatureType
, by replacing
getSchema():FeatureType
by
getAllowedMemberTypes():Set<FeatureType>
- đ The current Feature API implementation for
FeatureCollection does not respects the association type pattern:
- It acts like a
gml:FeatureArrayPropertyType
itself, by allowing to query a member asgetAttribute("typeName")
, where "typeName" is the ame of a child FeatureType. - In order to complain with the
FeatureCollectionType
definition, it should be:getAttribute("featureMember")
, which may return ajava.util.List<Feature>
, since thefeatureMember
association multiplicity is (0..N). â ī¸ BUT a derived FeatureCollection is not mandated to havefeatureMember(s)
properties. The point of being able to derive them is, apart of being able of restricting its members to a given type(s), to be able of calling the member property as you like. For example, you can define a RiverCollection that derives from FeatureCollection, whose association attribute is calledriverMember
instead offetureMember
.
- It acts like a
- It is clear that for simplicity of use, programmers should be able of using a FeatureCollection
instance through a conventient interface, like
FeatureCollection.features():FeatureIterator
- But, if we're going to be able of using a FeatureCollection through its Feature API, we'll need:
- đĄ a FeatureCollectionType, as well as we have a FeatureType
- đĄ a convenient way of restricting its members to one or more Feature types
- đĄ a convenient way of redefining the name of its feature association attribute name (like for replacing featureMember by riverMember)
From GML 3.1.1 spec, page 23: (paragraph numbers are mine)
"(1) A GML object is an XML element of a type derived directly or indirectly
from AbstractGMLType. From this derivation, a GML object may have a gml:id
attribute.(2) A GML property may not be derived from AbstractGMLType, may not have a
gml:id attribute, or any other attribute of XML type ID.(3) An element is a GML property if and only if it is a child element of a GML
object.(4) No GML object may appear as the immediate child of a GML object.
(5) Consequently, no element may be both a GML object and a GML property.
(6) NOTE In this version of GML, the use of additional XML attributes
in a GML application schema is discouraged."
Implications:
(1) Identity: aparently our type system may be able of dealing with identity beyond Feature. Any complex type that you define may inherit from AbstractGMLType or not. If it does, it may have identity, as well as metadataProperty, description and name.
(2): that's what a simple Attribute and a Complex one means
(4): that's where the gml:AssociationType pattern comes from. Currently, when we encode a GeometryAttribute to GML, we respect that rule just because we already know how geometries should be encoded. đĄ Adding the ability to know if a complex attribute "is identified" makes it more explicit and allows for user defined types to derive from AbstractGMLType
(6) that's consistent with the Object/property rule.
(5) the following is a real world example:
<sco:wq_plus gml:id="_41010901">
<sco:sitename>BALRANALD WEIR</sco:sitename>
<sco:anzlic_no>ANZNS0359100023</sco:anzlic_no>
<sco:location>
<gml:Point srsName="http://www.opengis.net/gml/srs/epsg.xml#4283">
<gml:pos>22 143.53399658</gml:pos>
</gml:Point>
</sco:location>
<sco:measurement gml:id="_16JAN94002001002003000000">
<sco:determinand_description>16/JAN/94</sco:determinand_description>
<sco:result>Turbidity</sco:result>
</sco:measurement>
<sco:measurement gml:id="_24JAN94002001002003000000">
<sco:determinand_description>24/JAN/94</sco:determinand_description>
<sco:result>Turbidity</sco:result>
</sco:measurement>
<sco:project_no>RWWQ0004</sco:project_no>
</sco:wq_plus>
Given (5), <sco:measurement>
is apparently wrong, since it is both a property and a GML Object
(its type derives from AbstractGMLType, or its badly defined, because of (1) and (6)).
đĄ So that's the requirement, adding a identity capable complex attribute, since its clear that not only features may have id, there are plenty of them in the GML spec (for example, Geometry), and a user should be able of defining its own complex type with identity.
From the above points, we had learned that the gml:AssociationType
pattern is widely used. It is a
container property for a complex attribute that's generally defined externally to the FeatureType
itself, like a Feature, a Geometry, etc.
More than that, every time you have to refer to an extenally defined entity (those than in
GML sense derives from AbstractGMLType, and thus may have identity), you should use a
container (association) property to refer to such an externally defined entity.
By the way, we do have a small set of well known association types that we'ew already treating as
such: FeatureAttributeType
and GeometryAttributeType
.
Now we found that the concept is extensible to any entity defined externally to a given
FeatureType. Note this is different from having a FeatureType property that has a complex structure
by itself.
đĄ So there exists the need to be able of explicitly modeling a property which acts as a container of an entity whose type is defined externally to a given FeatureType, wether such an entity is or not a Feature, it could be any kind of complex type (like a topology type).
Reference: http://old.geotools.org/Current-requirements-support-report_30521.html
The goal of the following section is to expose if the current API is able of expressing the needed
simple types.
This evaluation does not takes in count if they check or not that the restrictions applied
through a Filter adheres to each type allowed restrictions, since for all the current AttributeTypes
there is not this kind of validation. Thus, adding this kind of validation will be the subject of
another chapter by itself.
What this table does exposes is if there are a current AttributeType mapping for each primitive
type.
Level of support legend:
- đ unsupported
- đ partially supported
- đ supported
đ
Not supported. Passing List.class
as type argument for DefaultAttributeType
will not be enough.
list data types nees to know the type of its elements, and the type may be a derived atomic one,
so it has to deal with the item type restrictions, etc.
đĄ list data types may need their own
AttributeType
đ
Not supported
đĄ union will definitely need its own
AttributeType.
đ
TextualAttributeType fully handles plain strings
đ
When a Boolean attribute is needed, we simply use DefaultAttributeType passing it Boolean.class as
its type. Since we're going stronger,
đĄ boolean may need its own AttributeType
implementation, at least to deal with allowed restrictions?
đ
it may be specified by passing BigDecimal.class as the type of a NumericAttributeType
đ
passing Float.class as the type of a NumericAttributeType
đ
passing Double.class as the type of a NumericAttributeType
đ
duration can be stored as an instance of java.util.Date, thus mapping to TemporalAttributeType.
đĄ But we need a way of distinguishing the
exact XML Schema type given an instance of TemporalAttributeType. Otherwise we'll not be able of
correctly encoding a GML schema from a FeatureType instance
đ
its the current exact match for TemporalAttributeType
đ
same as duration
đ
same as duration
đ
same as duration
đ
same as duration
đ
đ
same as duration
đ
same as duration
đ
has no current mapping
đ
has no current mapping
đ
has no current mapping, though it may be inferred by using a DefaultAttributeType with URI.class as its type
đ
may map to TextualAttributeType, but it has no way of enforcing or validating a normalizedString
đ
same as above
đ
same as above
đ
supported by passing BigInteger.class as the type of a NumericAttributeType
đ
NumericAttributeType has no way of validating the type value space, and in such a case, there is no
way of differentiating a positive from a negative type since there is no direct equivalences to Java
classes and NumericAttributeType relies on the Class passed as its constructor argument to set the
type.
đĄ We need to extend NumericAttributeType in a
way that all the XML Schema basic type derived from decimal could be mapped with no ambiguities
đ
same as above
đ
Exact match for NumericAttributeType with Long.class as type argument
đ
Exact match for NumericAttributeType with Integer.class as type argument
đ
Exact match for NumericAttributeType with Short.class as argument
đ
Exact match for NumericAttributeType with Byte.class as argument
đ
same as nonPositiveInteger
đ
same as nonPositiveInteger
đ
same as nonPositiveInteger
đ
same as nonPositiveInteger
đ
same as nonPositiveInteger
đ
same as nonPositiveInteger
As each simple type has its own set of allowed restrictions, the first step is to ensure that all
the possible restriction types can be represented. The current approach to define a restriction on
an AttributeType is indeed very smart, since there exists already a powerful API to represent
constraints on a data set: the Filter API, which is the GeoTools implementation of the Open
Geospatial Consortium Filter 1.0 implementation specification.
The following is a table of the XML Schema constraining
facets and how they could be represented by a GeoTools
Filter. The power of this is such that, even if there is no predefined filter expression types to
match a given facet, there is a huge chance that it still can be used by a Function expression.
enforces the length of value to be equal to the declared length. length is the number of units of length, where units of length varies depending on the type that is being - derived- from (#of chars for a string type, #of octets for a binary type, etc)
schema
<xs:simpleType name="att_name">
<xs:restriction base="xs:string">
<xs:length value="10"/>
</xs:restriction>
</xs:simpleType>
matching filter
<Filter>
<PropertyIsEqualTo>
<Function name="strLength">
<PropertyName>att_name</PropertyName>
</Function>
<Literal>10</Literal>
</PropertyIsEqualTo>
</Filter>
Comments: that works for string based types. đĄ A new function expression should have to be created to check the length of binary data types
enforces the length of attribute value to be lower than or equal to the non negative integer specified as the value of the restriction
schema
<xs:simpleType name="att_name">
<xs:restriction base="xs:string">
<xs:minLength value="10"/>
</xs:restriction>
</xs:simpleType>
matching filter
<Filter>
<PropertyIsGreaterThanOrEqualTo>
<Function name="strLength">
<PropertyName>att_name</PropertyName>
</Function>
<Literal>10</Literal>
</PropertyIsGreaterThanOrEqualTo>
</Filter>
Comments: same as above
enforces the length of attribute value to be greater than or equal to the non negative integer specified as the value of the restriction
schema
<xs:simpleType name="att_name">
<xs:restriction base="xs:string">
<xs:maxLength value="10"/>
</xs:restriction>
</xs:simpleType>
matching filter
<Filter>
<PropertyIsLessThanOrEqualTo>
<Function name="strLength">
<PropertyName>att_name</PropertyName>
</Function>
<Literal>10</Literal>
</PropertyIsLessThanOrEqualTo>
</Filter>
Comments: same as above
specifies a regular expression that the attribute value must match to. Note: It is a consequence of the schema representation constraint Multiple patterns and of the rules for - restriction- that - pattern- facets specified on the same step in a type derivation are OR ed together, while - pattern- facets specified on different steps of a type derivation are AND ed together.
schema
<xs:simpleType name="att_name">
<xs:restriction base="xs:string">
<xs:pattern value="[A-Z]*"/>
</xs:restriction>
</xs:simpleType>
matching filter
<Filter>
<PropertyIsEqualTo>
<Function name="strMatches">
<PropertyName>att_name</PropertyName>
<Literal>[A-Z]*</Literal>
</Function>
<Literal>true</Literal>
</PropertyIsEqualTo>
</Filter>
Comments: pattern applies to all basic types (temporal, string, boolean, numeric, binary and anyURI)
đĄ verify that the XML Schema regular
expressions are compatible with Java1.4 ones, or find a regular expression evaluation engine that
does
constrains the - value space- to a specified set of values.
schema
<xs:simpleType name="att_name">
<xs:restriction base="xs:string">
<xs:enumeration value="option 1"/>
<xs:enumeration value="option 2"/>
</xs:restriction>
</xs:simpleType>
matching filter
<Filter>
<Or>
<PropertyIsEqualTo>
<PropertyName>att_name</PropertyName>
<Literal>option 1</Literal>
</PropertyIsEqualTo>
<PropertyIsEqualTo>
<PropertyName>att_name</PropertyName>
<Literal>option 2</Literal>
</PropertyIsEqualTo>
</Or>
</Filter>
Comments: Thanks to Dave: According to OGC Filter implementation, <Functions> must have a pre-defined number of arguments. You can always implement "in" with a set of "<Or>...<PropertyIsEqualTo>..."s.
constrains the - value space- of types - derived- from string such that the various behaviors specified in Attribute Value Normalization in XML 1.0 (Second Edition) are realized. The value of whiteSpace must be one of {preserve, replace, collapse}
schema
<xs:simpleType name="att_name">
<xs:restriction base="xs:string">
<!-- one of collapse|preserve|replace -->
<xs:whiteSpace value="collapse"/>
</xs:restriction>
</xs:simpleType>
Comments:
is the - inclusive upper bound- of the - value space. for a datatype with the - ordered- property
schema
<xs:simpleType name="date_att">
<xs:restriction base="xs:date">
<xs:maxInclusive value="2005-08-09"/>
</xs:restriction>
</xs:simpleType>
matching filter
<Filter>
<PropertyIsLessThanOrEqualTo>
<PropertyName>date_att</PropertyName>
<Literal>2005-08-09</Literal>
</PropertyIsLessThanOrEqualTo>
</Filter>
Comment: applies to all numeric and temporal types. Fully supported for numeric types.
java.util.Calendar
and
knowledge of the concrete temporal type
is the - exclusive upper bound- of the - value space- for a datatype with the - ordered- property
schema
<xs:simpleType name="date_att">
<xs:restriction base="xs:date">
<xs:maxExclusive value="2005-08-09"/>
</xs:restriction>
</xs:simpleType>
matching filter
<Filter>
<PropertyIsLessThan>
<PropertyName>date_att</PropertyName>
<Literal>2005-08-09</Literal>
</PropertyIsLessThan>
</Filter>
Comments: same as above
is the - exclusive lower bound- of the - value space- for a datatype with the - ordered- property
schema
<xs:simpleType name="date_att">
<xs:restriction base="xs:date">
<xs:minExclusive value="2005-08-09"/>
</xs:restriction>
</xs:simpleType>
matching filter
<Filter>
<PropertyIsGreaterThan>
<PropertyName>date_att</PropertyName>
<Literal>2005-08-09</Literal>
</PropertyIsGreaterThan>
</Filter>
Comments: same as above
is the - inclusive lower bound- of the - value space- for a datatype with the - ordered- property
schema
<xs:simpleType name="date_att">
<xs:restriction base="xs:date">
<xs:minInclusive value="2005-08-09"/>
</xs:restriction>
</xs:simpleType>
matching filter
<Filter>
<PropertyIsGreaterThanOrEqualTo>
<PropertyName>date_att</PropertyName>
<Literal>2005-08-09</Literal>
</PropertyIsGreaterThanOrEqualTo>
</Filter>
Comments: same as above
controls the maximum number of values in the - value space- of datatypes - derived- from decimal, by
restricting it to numbers that are expressible as i à 10^``n
where i and n are integers such that
|i| < 10^totalDigits
and
0 <= n <= totalDigits
. The value of totalDigits -
must be a positiveInteger.
schema
<xs:simpleType name="decimal_att">
<xs:restriction base="xs:string">
<xs:totalDigits value="10"/>
</xs:restriction>
</xs:simpleType>
Comments:
controls the size of the minimum difference between values in the - value space- of datatypes -
derived- from decimal, by restricting the - value space- to numbers that are expressible as
i à 10^``n
where i
and n
are integers and 0 <= n <= fractionDigits
. The value of fractionDigits - must be a
nonNegativeInteger.
schema
<xs:simpleType name="decimal_att">
<xs:restriction base="xs:string">
<xs:fractionDigits value="10"/>
</xs:restriction>
</xs:simpleType>
Comments:
This section outlines the requirement, level of support and description for complex types.
đ
support for multiple geometric attributes was in there from the inseption of the GeoTools Feature
API
đĄ Though we should make sure that a complex
attribute (not a Feature association) that contains a GeometricAttribute shall be treated as well??
Foe example:
<xs:complexType name="MyFeatureType">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureType">
<xs:sequence>
<xs:element name="the_geom" type="gml:PointPropertyType"/>
<xs:element name="aComplexAtt">
<xs:complexType>
<xs:sequence>
<xs:element name="complexAttName" type="xs:string"/>
<xs:element name="comlexAttGeom" type="gml:LineStringPropertyType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
â have both MyFeatureType/the_geom
and
MyFeatureType/aComplexAtt/complexAttGeom
to be taken in count?
đ
Current API has initial support for the different content models defined in XML Schema. Of the
three, choice is the one that is more tested, though the following considerations should be noted
for all of them:
(!)The current AttributeType model is reaching its limit for modeling a complex feature class. The
property values of a complex feature instance are structured in a tree like fashion, where each
"node" should be addressable by a expression language (like an XPath's location path), and its
value, either simple or complex must not only respect the type's value space, but also must be
structured in a way that respects its content model.
đĄ We have found that explicitly separating
both concerns, type system and content model (or schema) may lead to a simpler and more
powerful API
đ
Currently, ListAttributeType is meant to represent a sequence content model and define the type of the allowed content, though the same considerations than for choice support applies.
đ
The current SetAttributeType is intended to reflect the all content model, though its implementation still has order dependant code that makes difficult to ensure the content model is respected by a value instance.
đ
There exists a FeatureAttributeType to denote a nested feature property, though the lack of DataStore implementations that can make use of it limits the ability to evaluate its appliance to real world use cases.
đ
currently there are no support for a Feature property belonging to a different namespace than the Feature's FeatureType one
đ
if we're going to be able of using a FeatureCollection through its Feature API, we'll need:
- đĄ FeatureCollectionType, as well as we have a FeatureType
- đĄ convenient way of restricting its members to one or more Feature types
- đĄ convenient way of redefining the name of its feature association attribute name (like for replacing featureMember by riverMember)
đ
The current API has no knowledge of object identity beyond Feature
đ
Currently there exist a NestedAttributeType
which is intended to reflect that it is refering to an
externally defined object type, but:
â ī¸ it has no knowledge of identityâ ī¸ it derives fromListAttributeType
, which limits its content model to the equivalence of a XML Schemasequence
- It seems it's not being used across the GeoTools code base
Supporting all the features mentioned above seems like a lot of work. We have, though, a driven specification that will help limit scope. Actually it's an OGC discussion paper, but is what the project stakeholders are interested in for the short time: Level 0 Profile of GML3 for WFS.
The intent of that document is to specify the encoding of application schemas sufficiently so that
WFS client implementations do not need to deal with the entire scope of XML-Schema and GML but only
need to understand a restricted subset of both specifications in order to be able interpret schema
document s
generated in response to a DescribeFeatureType request.
Among other things, it defines the essential geometry and simple types that a system must support to achieve a minimum level of interoperability.
From the mentioned discussion paper, table 4, page 21, the following are the allowed geometry types:
GML Geometric Property Type | Defined in GML Schema File | Restrictions |
---|---|---|
gml:PointPropertyType | geometryBasic0d1d.xsd | none |
gml:CurvePropertyType | geometryBasic0d1d.xsd | only LineString allowed as value |
gml:SurfacePropertyType | geometryBasic2d.xsd | only Polygon allowed as value |
gml:MultiCurvePropertyType | geometryAggregates.xsd | only MultiLineString allowed as value |
gml:MultiSurfacePropertyType | geometryAggregates.xsd | MultiPolygon and MultiSurface allowed as value; MultiSurface can use only linear (sub)geometries |
gml:LinearRingPropertyType | geometryBasic2d.xsd | This was missing in GML- 2 and has justifiably been added to GML- 3 |
gml:RingPropertyType | geometryPrimitives.xsd | only LinearRing or Ring with LineStrings can appear as value |
That's good, we already handle most of them.
As for simple types, section 7.5.2 Basic Data Types, page 26, limits the set of available basic types to a smaller subset. The rational being that a smaller common set of supported basic data types is likely to be more interoperable.
The list of supported basic data types is:
-
Integers, limited to integer data type with no limit on applyable facets
-
Reals, limited to decimal, float and double and totalDigits and fractionDigits facets
-
Character strings, to string type and maxLength facet
-
Date, limited to date and dateTime data types with no restriction on facets
-
boolean data type
-
Binary data, both base64Binary and hexBinary, with no restriction on facets, and the aggregate of the attributes url, mimeType, and role, as specified in the following fragment:
<xs:element name="propertyName" minOccurs="0|N" maxOccurs="0|N|unbounded"> <xs:complexType> <xs:simpleContent> <xs:extension base="xs:base64Binary|xs:hexBinary"> <xs:attribute name="url" type="xs:anyURI" use="optional"/> <!-- when referenced from an external URI --> <xs:attribute name="mimeType" type="xs:string" use="required"/> <!-- must be specified to indicate the type or format of binary data that is being referenced --> <xs:attribute name="role" type="xs:string" use="optional"/> <!-- can be used to assign a user-defined role to the data. The role attribute allows complex binary format s like HDF/EOS, which contains multiple independent binary component s, to be supported. --> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element>
đĄ so we may be able of coming back with a flexible design that addresses this essential requirements and leaves place for the wider implementation of the rest.
Be careful
âšī¸
GML Level 0 profile is about simple features, so the explanation above aplies only to the simple attributes support requirements. We still need to support multiple geometric attributes, related features, and complex attribute types.
It is not a requirement (at least for this phase of the project) to cover all the mappings
between simple types to the predefined XML Schema simple types.
It is enough to count with a well known set of java to xml bindings, like Integer->xs:int,
String->xs:string, Date->xs:date, etc.
There is no need of having mappings to XML Schema list
and union
simple types.
The majority of available data sources are producers of Simple Features. So the API shuold be kept simple enough that it adds no significant complexity for simple cases.
We have discovered that the current approach has difficulties to express, in a single type
hierarchy, what the valid structure of a type instance is, and what's the exact type of each of the
components of such an instance.
The new model must be able of:
- specify the type (name, value range, nillability) of a property
- state the content model of a type (multiplicity and tree structure)
- provide an unambiguous containment model
A type always belongs to a namespace. A nested object type may belong to a different namespace than its parent.
Not only Feature instances has identity (for Feature, it is its FID). It should be possible to
define a type hose values has a unique identifier inside its namespace. These are always complex
types.
A common case are Geometries. Two or more Features may share the same Geometry. In GML, Geometries
are allowed to have an id. So both Features may share the same geometry value, by reference.
A Feature property follows the association type pattern. A Geometry property too. In fact, all Feature attributes whose type is defined externally to the feature's type, or internally but may have identity, should be referenced by an association element. That's what will allow to reference a remote value instance.
All the types that can be defined are derived from another one. If it is a simple type, it derives
from a primitive type. It is a complex type, either it derives from gml:_Object
, or if it may have
identity, derives directly or indirectly from gml:AbstractGMLType
.
There are some well known abstract supertypes for well known type hierarchies, like for Geometries
and Features.
Type hineritance is limited to single hinherintance.
Setting a requirement for a type to return its super type (i.e. getParent():Type) may be overkill, since due to cross namespace hinheritance, it would be the task of a repository of types to obtain a type instance. But due to the use of qualified names to identify types, a given type may be able of returning the qualified name of its parent.
Do not stick the modeling power of the API to XPath. XPath is an expression language and there can
exist others.
We must provide an API that makes easy the implementation of an expression language against it.
FeatureCollection is a well known construct, with a well known type, as well as Geometry and its
derivatives are.
The same way you can define your own type to hold features, you could define your own type to hold
a geometry. Instead of having to do that, GML provides thes e predefined constructs to easy the job
of GIS users, so lets integrate FeatureCollection in the modeling system in a way that it is not
needed to have a special treatment to deal with them, but simply using its Feature API.
The restrictions on the value space of a simple type is given by its "facets".
The restrictions on the value space of a complex type is given by its "content model".
By the other hand, the idea of directly expressing these restrictions through the Filter API may or
may not satisfy the whole spectrum of needs. It it does, predefined function names should be defined
to treat facets, and the Filter API may need to be extended to deal with validation of the content
model for complex types. More than that, it would be desirable to validate a type instance without
having a complete Feature instance, which the current Filter API does not allows.
This may impose an unacceptable burden to the API making it very hard to implement.
Instead, the restrictions on a type's value space could be expressed by a simple API and give implementations the freedom to validate them as they like.
This is an API change proposal to address the previously stated needs.
Refer to the document, and specially to the Discussion section for an insight on the process the lead to this proposal.