Web Service Implementation
of OGC Web Feature Service
OGC Schemas
Implementing WFS (or any other
OGC service) requires producing OGC compible XML documents. Each service has a
set of XML Schemas defined for expressing services it offers and capabilities
it can demonsrate. We use these schemas for data binding -to create XML
documents with code- and to make sure that these documents are compatible with
the standards.
The interconnection between OGC schemas are as follows:

A WFS should be able to fulfill
following service requests (Definitions are from OGC WFS document):
| Request |
Definition |
| GetCapabilities |
WFS describes its capabilities through an XML document.
This document should be returned for this request. |
| DescribeFeatureType |
WFS should be able to generate a schema description of
feature types serviced.
|
| GetFeature |
Allows retrieval of features in XML format.
|
| GetFeatureWithLock |
Functionally similar to the GetFeature, except that it
indicates to a WFS to attempt to lock the features that are selected.
|
| LockFeature |
The purpose of this request is to expose a long term
feature locking mechanism to ensure consistency.
|
| Transaction |
Data transformation operations that are to be applied to
web accessible feature instances. |
Data binding frameworks such as Castor
(http://castor.exolab.org) or XMLBeans
(http://xml.apache.org/xmlbeans ) take
XML Schemas as input and produce java sources. But one major problem with these
frameworks is that sometimes it is not easy to find an object oriented
correspondence of the XML Schema constructs. In such cases either the source
codes can not be generated or generated source codes may not produce correct
XML instances.
Some of the XML Schema types
-such as substitutions and abstract types- used in OGC Schemas are currently
not supported by Castor. I had to make several changes to make these schemas
compatible with Castor Source Generator. Some of these changes are
summarized below.
Original OGC Schemas can be found
here:
http://schemas.opengis.net/
Modified schemas are here:
http://complexity.ucs.indiana.edu/~gaydin/ogc/modified/
In general OGC Schemas use
substitution to express a group of elements can be used interchangeably.
Substitution is defined by W3.org as follows
XML Schema provides a mechanism, called substitution groups, that
allows elements to be substituted for other elements. More specifically,
elements can be assigned to a special group of elements that are said to be
substitutable for a particular named element called the head element. (Note
that the head element must be declared as a global element.)
The existence of a substitution group does not require any of the
elements in that class to be used, nor does it preclude use of the head
element. It simply provides a mechanism for allowing elements to be used
interchangeably.
Since Castor does not support
substitution groups I had to find a way around this problem and it appears that
using choices is the answer.
Consider following example from
expr schema:
<expression> element
in this schema is a top level definition for general expressions. Any one of
the seven elements in ‘expression substitution group’ may be used while
constructing an expression in an XML instance.
|

|
<xsd:element name="expression" type="ogc:ExpressionType" abstract="true"/>
..
<xsd:complexType name="ExpressionType" abstract="true" mixed="true"/>
|
As it can be seen from the schema
fragment, <expression> element is ‘abstract’, meaning we don’t
expect to see any <expression> tags in the final XML instance.
Since one of the seven elements
can be used where an expression is to be defined, I simply replaced the
substitution group with a <choice> in <ExpressionType>.
|

|
<xsd:element name="expression" abstract="true">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="ogc:ExpressionType"/>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
…
<xsd:complexType name="ExpressionType" mixed="true">
<xsd:choice>
<xsd:element ref="ogc:Add"/>
<xsd:element ref="ogc:Div"/>
<xsd:element ref="ogc:Function"/>
<xsd:element ref="ogc:Literal"/>
<xsd:element ref="ogc:Mul"/>
<xsd:element ref="ogc:PropertyName"/>
<xsd:element ref="ogc:Sub"/>
</xsd:choice>
</xsd:complexType>
|
I made several changes of the
same kind, but some cases required different approaches to produce XML
instances that are compatible with the original schemas. For instance:
A Function element may have
multiple expressions at the same time.
|

|
<xsd:element name="Function" type="ogc:FunctionType" substitutionGroup="ogc:expression"/>
…
<xsd:complexType name="FunctionType">
<xsd:complexContent>
<xsd:extension base="ogc:ExpressionType">
<xsd:sequence>
<xsd:element ref="ogc:expression" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
|
To express this element with a <choice>
I changed the Function as follows:
|

|
<xsd:complexType name="FunctionType">
<xsd:sequence minOccurs="0">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="ogc:Add" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="ogc:Div" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="ogc:Function" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="ogc:Literal" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="ogc:Mul" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="ogc:PropertyName" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="ogc:Sub" minOccurs="0" maxOccurs="unbounded"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
|
Here the Function has a sequence of choices which
basically means a sequence of the seven elements.
OGC Filter Implementation
One of the challenges with implementing OGC WFS is to be
able to create and parse XML documents that contain Filters. Filters are used
to define constraints on a query.
GetFeature (and GetFeatureWithLock) requests contain <Query>
element which in turn may contain <Filter> element to
constraint the query. If no <Filter> element is contained
in <Query> than the query is unconstrained and all feature
instances should be retrieved Filters can be used to specify both spatial
and/or non-spatial constraints in a query. (WFS Spec p.26).
A Filter may include an operation element in one of the
following three operation types:
- Spatial Operations
- Comparison Operations
- Logic Operations
These operation types are defined as substitution groups in Filter
Schema as following picture shows:
|

|
<xsd:element name="Filter" type="ogc:FilterType"/>
..
<xsd:complexType name="FilterType">
<xsd:choice>
<xsd:element ref="ogc:spatialOps"/>
<xsd:element ref="ogc:comparisonOps"/>
<xsd:element ref="ogc:logicOps"/>
<xsd:element ref="ogc:FeatureId" maxOccurs="unbounded"/>
</xsd:choice>
</xsd:complexType>
|
The picture tells us that at any given time a Filter may
have one element from one of the three groups and any sub element under these
groups may substitute each other.
I removed the substitution groups and created choices to
replace them. Finally in this version of the schema the Filter has a choice
which in turn has three choices that correspond to three substitution groups in
the original schema.
|

|
<xsd:element name="Filter" type="ogc:FilterType"/>
..
<xsd:complexType name="FilterType">
<xsd:choice id="FilterTypeChoice">
<xsd:choice id="spatialOpsChoice">
<xsd:element ref="ogc:BBOX"/>
<xsd:element ref="ogc:Beyond"/>
<xsd:element ref="ogc:Contains"/>
<xsd:element ref="ogc:Crosses"/>
<xsd:element ref="ogc:DWithin"/>
<xsd:element ref="ogc:Disjoint"/>
<xsd:element ref="ogc:Equals"/>
<xsd:element ref="ogc:Intersects"/>
<xsd:element ref="ogc:Overlaps"/>
<xsd:element ref="ogc:Touches"/>
<xsd:element ref="ogc:Within"/>
</xsd:choice>
<xsd:choice id="comparisonOpsChoice">
<xsd:element ref="ogc:PropertyIsBetween"/>
<xsd:element ref="ogc:PropertyIsEqualTo"/>
<xsd:element ref="ogc:PropertyIsGreaterThan"/>
<xsd:element ref="ogc:PropertyIsGreaterThanOrEqualTo"/>
<xsd:element ref="ogc:PropertyIsLessThan"/>
<xsd:element ref="ogc:PropertyIsLessThanOrEqualTo"/>
<xsd:element ref="ogc:PropertyIsLike"/>
<xsd:element ref="ogc:PropertyIsNotEqualTo"/>
<xsd:element ref="ogc:PropertyIsNull"/>
</xsd:choice>
<xsd:choice id="LogicOpsChoice">
<xsd:element ref="ogc:And"/>
<xsd:element ref="ogc:Not"/>
<xsd:element ref="ogc:Or"/>
</xsd:choice>
<xsd:element ref="ogc:FeatureId" maxOccurs="unbounded"/>
</xsd:choice>
</xsd:complexType>
|
Similar changes were made in WFS and GML schemas as well.
The Demo
The OGC specifications do not have information on how to
build Web Services; instead the specified services are intended to be servlets
that can exchange information using HTTP GET and POST operations.
Since we wanted to make OGC Web Services I have created a wsdl
file for WFS which defines operations for required WFS request types.
The WFS-WS methods receive requests as XML strings and
return the results as strings. The request – response XML formats are fully
compatible with the OGC specifications.
To use WFS-WS user generates the client stubs from wfs.wsdl
which is available on WFS server. Then using this client stub code user
sends the requests in appropriate format and receives the results as XML
strings.
I used Apache Axis for creating and publishing the
Web Service. Axis takes care of the SOAP communication between server
and the client.
Currently this WFS-WS can process GetCapabilities and
a subset of GetFeature requests. I used capabilities document and the
data from the deegree’s sample WFS implementation.
deegree-WFS uses Microsoft Access database for two
sample geographic data sets, Europe and Cities. I used a tool called
access2mysql for
mapping these tables to our MySQL server in gridfarm8.
This version of WFS supports GetFeature requests with a BBOX
constraint. User needs to define Query which includes a BBOX filter. BBOX
constraint should include coordinates inside the scope of the sample Europe data.
A sample GetFeature request is provided in the demo page. By
changing the PropertyName elements user can retrieve different column values
from the database.
After user submits the GetFeature request the WFS parses
this XML document and extracts Property Names and coordinate information to
construct an SQL query. This query is then executed for MySQL database and the
results are returned as plain-text. GetFeature responses should be GML 2.1.2
compatible XML documents which contains Feature Collections. But for the demo
this property is not supported.
I am working on developing a more general data layer (which
might use Hibernate) that would make it easier to adopt new data stores.
This is not a complete WFS-WebService implementation; rather
it is a small demo to show current progress.
What has been done:
-
Modifying OGC schemas for data binding and source code generation.
-
OGC Filter Encoding implementation (This will improve as I implement a
new DataStore interface for the databases that have Geographic Features).
-
Parsing and creating WFS 1.1, Filter 1.0.0 and GML 2.1.2 OGC schemas.
-
WSDL interface for the WFS Web Service
-
GetCapabilities request
-
GetFeature request (This is a partial implementation)
What to do:
-
Complete GetFeature request. WFS returns an XML document as a response
to this request.Returning document has a collection of Features (FeatureCollection)
which satisfy the constraints in the GetFeature request. Features retrieved
from the database are defined in a GML compatible schema and I need to create
instances of this schema to include in the FeatureCollection. I think
using XSL will help us overcome this problem.
-
A general and flexible DataStore implementation: This would allow us to
integrate any number of databases that contain geographic features.
DescribeFeatureType request. This involves in returning the schema that defines
the data store in which the geographic feature resides. This should be
straightforward.
-
GetFeatureWithLock, LockFeature, Transaction requests. These are
advanced request types, not required initially to have a working WFS, so they
are not supposed to be implemented immediately. But we should have them to have
a complete WFS implementation.
-
Integrate with WMS etc.