.. _app-schema.tutorial:
Tutorial
========
This tutorial demonstrates how to configure two complex feature types using the app-schema plugin and data from two property files.
GeoSciML
---------
This example uses `Geoscience Markup Language (GeoSciML) 2.0 `_, a GML application schema:
*"GeoSciML is an application schema that specifies a set of feature-types and supporting structures for information used in the solid-earth geosciences."*
The tutorial defines two feature types:
#. ``gsml:GeologicUnit``, which describes "a body of material in the Earth".
#. ``gsml:MappedFeature``, which describes the representation on a map of a feature, in this case ``gsml:GeologicUnit``.
Because a single ``gsml:GeologicUnit`` can be observed at several distinct locations on the Earth's surface, it can have a multivalued ``gsml:occurrence`` property, each being a ``gsml:MappedFeature``.
Installation
------------
* Install GeoServer as usual.
* Install the app-schema plugin (place the jar files in ``WEB-INF/lib``).
* The tutorial configuration is a complete working GeoServer data directory. It includes all the schema (XSD) files required to use GeoSciML 2.0, the data files, and the app-schema configuration files. There are two ways you can get it:
#. Download :download:`geoserver-app-schema-tutorial-config.zip` and unzip it into the folder that you will use as your data directory.
#. Check it out from the `AuScope subversion repository `_.
* If the data directory differs from the default, edit ``WEB-INF/web.xml`` to set ``GEOSERVER_DATA_DIR``. (Be sure to uncomment the section that sets ``GEOSERVER_DATA_DIR``.)
* Perform any configuration required by your servlet container, and then start the servlet. For example, if you are using Tomcat, configure a new context in ``server.xml`` and then restart Tomcat.
datastore.xml
-------------
Each data store configuration file ``datastore.xml`` specifies the location of a mapping file and triggers its loading as an app-schema data source. This file should not be confused with the source data store, which is specified inside the mapping file.
For ``gsml_GeologicUnit`` the file is ``workspaces/gsml/gsml_GeologicUnit/datastore.xml``::
gsml_GeologicUnit_datastore
gsml_GeologicUnit
true
gsml_workspace
urn:cgi:xmlns:CGI:GeoSciML:2.0
file:workspaces/gsml/gsml_GeologicUnit/gsml_GeologicUnit.xml
app-schema
For ``gsml:MappedFeature`` the file is ``workspaces/gsml/gsml_MappedFeature/datastore.xml``::
gsml_MappedFeature_datastore
gsml_MappedFeature
true
gsml_workspace
urn:cgi:xmlns:CGI:GeoSciML:2.0
file:workspaces/gsml/gsml_MappedFeature/gsml_MappedFeature.xml
app-schema
.. note:: Ensure that there is no whitespace inside an ``entry`` element.
Mapping files
-------------
Configuration of app-schema feature types is performed in mapping files:
* ``workspaces/gsml/gsml_GeologicUnit/gsml_GeologicUnit.xml``
* ``workspaces/gsml/gsml_MappedFeature/gsml_MappedFeature.xml``
Namespaces
``````````
Each mapping file contains namespace prefix definitions::
gml
http://www.opengis.net/gml
gsml
urn:cgi:xmlns:CGI:GeoSciML:2.0
xlink
http://www.w3.org/1999/xlink
Only those namespace prefixes used in the mapping file need to be declared, so the mapping file for ``gsml:GeologicUnit`` has less.
Source data store
`````````````````
The data for this tutorial is contained in two property files:
* ``workspaces/gsml/gsml_GeologicUnit/gsml_GeologicUnit.properties``
* ``workspaces/gsml/gsml_MappedFeature/gsml_MappedFeature.properties``
:ref:`data_java_properties` describes the format of property files.
For this example, each feature type uses an identical source data store configuration. This ``directory`` parameter indicates that the source data is contained in property files named by their feature type, in the same directory as the corresponding mapping file::
datastore
directory
file:./
See :ref:`app-schema.data-stores` for a description of how to use other types of data stores such as databases.
Catalog
```````
Both feature types use the same OASIS XML Catalog, given as a path relative to the mapping file::
../../../schemas/catalog.xml
* The catalog contains the the XSD schemas for GeoSciML 2.0 its dependencies.
* Note that some dependencies are imported as relative filesystem paths, and so are not resolved through the OASIS Catalog, but are still present on the filesystem.
* GML 3.1.1 is also a dependency, but is not required because it is distributed with GeoServer.
* Use of a catalog is required because the implementation otherwise fails to honour relative imports.
Target types
````````````
Both feature types are defined the same XML Schema, the top-level schema for GeoSciML 2.0. This is specified in the ``targetTypes`` section. The type of the output feature is defined in ``targetElement`` in the ``typeMapping`` section below``::
http://www.geosciml.org/geosciml/2.0/xsd/geosciml.xsd
In this case the schema is published, but because the OASIS XML Catalog is used for schema resolution, a private or modified schema in the catalog can be used if desired.
Mappings
````````
The ``typeMappings`` element begins with configuration elements. From the mapping file for ``gsml:GeologicUnit``::
datastore
gsml_GeologicUnit
gsml:GeologicUnit
* The mapping starts with ``sourceDataStore``, which gives the arbitrary identifier used above to name the source of the input data in the ``sourceDataStores`` section.
* ``sourceType`` gives the name of the source simple feature type. In this case it is the simple feature type ``gsml_GeologicUnit``, sourced from the rows of the file ``gsml_GeologicUnit.properties`` in the same directory as the mapping file.
* When working with databases ``sourceType`` is the name of a table or view. Database identifiers must be lowercase for PostGIS or uppercase for Oracle Spatial.
* ``targetElement`` is the name of the output complex feature type.
gml:id mapping
``````````````
The first mapping sets the ``gml:id`` to be the feature id specified in the source property file::
gsml:GeologicUnit
getId()
* ``targetAttribute`` is the XPath to the element for which the mapping applies, in this case, the top-level feature type.
* ``idExpression`` is a special form that can only be used to set the ``gml:id`` on a feature. For database sources, ``getId()`` will synthesise an id from the table or view name, a dot ".", and the primary key of the table. If this is not desirable, any other field or CQL expression can be used, if it evaluates to an `NCName `_.
Ordinary mapping
````````````````
Most mappings consist of a target and source. Here is one from ``gsml:GeologicUnit``::
gml:description
DESCRIPTION
* In this case, the value of ``gml:description`` is just the value of the ``DESCRIPTION`` field in the property file.
* For a database, the field name is the name of the column (the table/view is set in ``sourceType`` above). Database identifiers must be lowercase for PostGIS or uppercase for Oracle Spatial.
* CQL expressions can be used to calculate content. Use caution because queries on CQL-calculated values prevent the construction of efficient SQL queries.
* Source expressions can be CQL literals, which are single-quoted.
Client properties
`````````````````
In addition to the element content, a mapping can set one or more "client properties" (XML attributes). Here is one from ``gsml:MappedFeature``::
gsml:specification
xlink:href
GU_URN
* This mapping leaves the content of the ``gsml:specification`` element empty but sets an ``xlink:href`` attribute to the value of the ``GU_URN`` field.
* Multiple ``ClientProperty`` mappings can be set.
In this example from the mapping for ``gsml:GeologicUnit`` both element content and an XML attribute are provided::
gml:name[1]
NAME
codeSpace
'urn:x-test:classifierScheme:TestAuthority:GeologicUnitName'
* The ``codespace`` XML attribute is set to a fixed value by providing a CQL literal.
* There are multiple mappings for ``gml:name``, and the index ``[1]`` means that this mapping targets the first.
targetAttributeNode
```````````````````
If the type of a property is abstract, a ``targetAttributeNode`` mapping must be used to specify a concrete type. This mapping must occur before the mapping for the content of the property.
Here is an example from the mapping file for ``gsml:MappedFeature``::
gsml:positionalAccuracy
gsml:CGI_TermValuePropertyType
gsml:positionalAccuracy/gsml:CGI_TermValue/gsml:value
'urn:ogc:def:nil:OGC:missing'
codeSpace
'urn:ietf:rfc:2141'
* ``gsml:positionalAccuracy`` is of type ``gsml:CGI_TermValuePropertyType``, which is abstract, so must be mapped to its concrete subtype ``gsml:CGI_TermValuePropertyType`` with a ``targetAttributeNode`` mapping before its contents can be mapped.
* This example also demonstrates that mapping can be applied to nested properties to arbitrary depth. This becomes unmanageable for deep nesting, where feature chaining is preferred.
Feature chaining
````````````````
In feature chaining, one feature type is used as a property of an enclosing feature type, by value or by reference::
gsml:occurrence
URN
gsml:MappedFeature
gml:name[2]
true
* In this case from the mapping for ``gsml:GeologicUnit``, we specify a mapping for its ``gsml:occurrence``.
* The ``URN`` field of the source ``gsml_GeologicUnit`` simple feature is use as the "foreign key", which maps to the second ``gml:name`` in each ``gsml:MappedFeature``.
* Every ``gsml:MappedFeature`` with ``gml:name[2]`` equal to the ``URN`` of the ``gsml:GeologicUnit`` under construction is included as a ``gsml:occurrence`` property of the ``gsml:GeologicUnit`` (by value).
WFS response
------------
When GeoServer is running, test app-schema WFS in a web browser. If GeoServer is listening on ``localhost:8080`` you can query the two feature types using these links:
* http://localhost:8080/geoserver/wfs?request=GetFeature&typeName=gsml:GeologicUnit
* http://localhost:8080/geoserver/wfs?request=GetFeature&typeName=gsml:MappedFeature
gsml:GeologicUnit
`````````````````
* :download:`The WFS response for gsml:GeologicUnit ` contains two features corresponding to the two rows in ``gsml_GeologicUnit.properties``. The response document has been manually pretty-printed, so contains more whitespace than the original GeoServer response, but is otherwise a complete WFS response.
* Feature chaining has been used to construct the multivalued property ``gsml:occurrence`` of ``gsml:GeologicUnit``. This property is a ``gsml:MappedFeature``. The WFS response for ``gsml:GeologicUnit`` combines the output of both feature types into a single response. The first ``gsml:GeologicUnit`` has two ``gsml:occurrence`` properties, while the second has one. The relationships between the feature instances are data driven.
.. note:: The data in this tutorial is fictitious. Some of the text and numbers have been taken from real data, but have been modified to the extent that they have no real-world meaning.