Proposal 6.2: Capabilities Metadata
Author: Glenn Stowe, CubeWerx, gstowe@cubewerx.com
Author: Frank Warmerdam, 3i, warmerdam@pobox.com
Proposed: 2001/02/16
Last Edited: 2001/06/13
Status: Proposed
Summary
A mechanism is introduced to return version information, layer lists, and
related metadata from drivers in a format inspired by the OGC WFS
capabilities document.
Background
The current method used by OGDI to report the contents of a data
store is a two step process. A function called GetDictionary returns a
TCL/TK applet used to define a user interface, and a subsequent call to
UpdateDictionary fills in the data in that applet.
There are two major issues with this approach.
- A client application not written in
TCL/TK has no use for the applet provided by GetDictionary.
- There is no
standard format for driver writers to use when reporting the content of
their data store.
This leaves client application developers scrambling
to recognize the many different dictionary formats returned by drivers,
which violates the basic principal of OGDI. The main benefit of OGDI
resides in the capability of accessing a variety of native formats by
separating
the client and server applications.
Approach
The OGC WFS capabilities document (as normally returned by a GetCapabilities
request) is modified for our use, and will be returned by OGDI 3.1 compliant
drivers when cln_UpdateDictionary("ogdi_capabilities") is called. Note
that this is a required feature of 3.1 compliant OGDI drivers.
The existing OGC WFS standard should be referred to for background on tags
not specifically added, altered or reinterpreted by this proposal. It
is expected that this will become available on the public OGC web site
(www.opengis.org) in coming months.
In the meantime it is available under the member services area to OGC members.
In general terms, the OGC style capabilities document is intended to
describe more about a data server than it is practical to return from the
depths of an OGDI driver - keep in mind these documents are generated by the
dyn_UpdateDictionary() call of individual drivers. As such, some of the
general service description and capabilities information is not easily
generated. Furthermore, as it will be implemented a client can't get the
capabilities information till after connecting to the server so information
such as the gltp url, or supported protocols isn't really valuable anymore.
This mismatch of levels motivates a number of items being made optional in
this proposal that are requested by OGC WFS GetCapabilities operations. It
is intended that the OGDI capabilities document being discussed in this
proposal could be used to populate higher level services catalogs at which
point much of the services and capabilities information would be filled in;
however, that is not important to the most direct use under this proposal.
As well as ogdi_capabilities support, 3.1 drivers are required to
return the same document with the FeatureTypeList element, and all
subelements omitted when a cln_UpdateDictionary("ogdi_server_capabilities")
request is made. This is intended to provide a mechanism for applications
to perform version and extention negotiation with servers having many layers
efficiently when layer information is not required.
Element Changes
- The OGDI_Capabilities element replaces the WFS_Capabilities
element.
- The version attribute of the OGDI_Capabilities node
now refers to the OGDI version supported by the driver, this is more fully
defined in a following section.
- The Service element is made optional and generally will not be
filled in by OGDI drivers.
- The Request element of Capability is made optional, and
generally
won't be filled by OGDI drivers. At some point in the future alternate
definitions to the existing DCPType sub-elements will need to be
defined, but they are not significant to low level use of the capabilities.
- The Extension element is introduced, and is used to list
an extension (extensions are defined later).
- One or more Extensions may be included under Capability
indicating extensions supported for all layers in the dataset.
- The Operation element should always, and only, contain the Query
operation.
- The FeatureTypeList element can now have FeatureTypeList
elements as children (to express heirarchy), and a Name element as
a child (to name nodes in the heirarchy).
- The FeatureTypeList element is optional in the DTD. It is
intended that a list should be provided for ogdi_capabilities but
not included for ogdi_server_capabilities requests.
- The Name element (when used under FeatureType)
will contain a name suitable to pass to cln_SelectLayer(). In cases where
layers may contain query strings, the default query string selecting all
features will be listed, for instance
we might use buildnga@col(*) for a VRF layer.
- The SRS element will contain a coordinate system definition
expressed in PROJ.4 syntax, as normally returned by cln_GetServerProjection()
but prepended with PROJ4:. This is intended to treat
PROJ4 as a pseudo-authority in OGC terms.
- Add the Family element (1 or more) which must contain one of
Matrix, Image, Point, Text, Line, or Area as the text contents. One or more
of these are used with each layer to indicate the list of family types
existing in that layer.
- The LatLonBoundingBox has been made optional so that a
eventually supporting un-georeferenced data will be possible.
- The BoundingBox element under FeatureType
has been made manditory with semantics just like BoundingBox in
WMS or except that the SRS element isn't accepted (the SRS is implicitly
the one specified in the tag). Note that the x and y resolutions
(resx, and resy) should be a divisor of the x and y extents of the bounding
box. The resolution has no intended meaning in the case of vector layers
(though it must still be provided).
- Add the QueryExpression element under FeatureType
which is used to describe some
information about substituting query strings in the layer name. This
element is described more fully in a following section.
- One or more Extensions may be included under FeatureType
indicating extensions supported for all layers in the dataset.
Versioning
The version is a textual representation of a numerical version number.
It indicates the version of the OGDI specification supported by the
driver/server.
Each legal version number will be defined by the 3i, with an associated
specification document indicating the requirements for
claiming to support that version.
Version numbers will be decimal values (such as "3.0", "3.1"), where a
higher version number always implies that all capabilities of previous
versions are supported. (This may be violated when the major version changes,
for instance a switch from 3.x to 4.x). The version numbers will always be
numerically comparable, so 3.10 is really just 3.1. If we want to have minor
versions after 3.9 we might number them 3.91 rather than 3.10.
The version is returned as the value of the version attribute of
the OGDI_Capabilities element.
Extensions
The extensions supported by a server are represented as a list of extension
identifiers.
The presence of the extension identifier indicates that this server (at least
for the current datastore or layer) supports the indicated extensions.
The extension identifiers will conform to the following restrictions:
- Identifiers only contain the characters a-z, 0-9, '_', '-', '.'. Note
only lower case to avoid case sensitivity issues.
- Identifiers may only have the prefix "ogdi_" if issued by the 3i as
standard predefined extensions.
- Other vendors may create their own extension identifiers. To guarantee
no collisions, vendors may prefix the extension with a DNS domain they
control in reversed order. For instance "com.cubewerx.". Vendors will avoid
using a prefix that is currently, or could ever be, a valid DNS domain.
Extension applying to the whole datastore, or all layers may be returned as
Extension elements under the Capability element. Extensions
that only apply to some returned layers should be returned as children of the
appropriate FeatureType element(s).
QueryExpression
The QueryExpression element is used to define some information about
the query expression format for layers (FeatureTypes) that allow some sort
of query expression to be passed in the layer name. The VRF driver is an
example of where this might be used. It is intended to allow sophisticated
clients to identify drivers allowing attribute queries without having an
exaustive list of drivers available.
The QueryExpression element's contents (if present) are taken to be
a textual description that may be shown to the user as a hint to help
composing query expressions. The text is unstructured, but should be human
readable.
The following attributes included with the QueryExpression:
- qe_prefix - REQUIRED: the portion of the layer name that
preceeds the expression when forming the layer name.
- qe_suffix - REQUIRED: the portion of the layer name that
follows the expression when forming the layer name.
- qe_format - OPTIONAL: an indentifier giving the format of the
expression string. Currently only restricted_where is supported, but
in the future other standardized formats for expressions may be added.
Note that the prefix and suffix data can be ignored when using the default
form of the layer name, and the value from the Name element is used.
qe_format=restricted_where
The qe_format value restricted_where indicates the expression
takes the form of the SQL WHERE clause with restrictions, the fields being
the feature attributes. The following defines the manner in which the
restricted where clauses can be constructed. Intepretation is according
to the SQL standard.
The following production rules describe the syntax of restricted where
conditions. Note that the SQL NOT operator is not available. Also,
SQL regex and LIKE operators are not available.
@condition@ = @field_name@ @binary_operator@ @value@
| "(" @condition@ ")" @binary_logical_operator@ "(" @condition@ ")"
@binary_operator@ = "<" | ">" | "<=" | ">=" | "<>" | "="
@binary_logical_operator@ = "AND" | "OR"
@field_name@ = @string_token@
@value@ = @string_token@ | @numeric_value@ | @string_value@
@string_value@ = "'" @characters@ "'"
The @numeric_value@ item can be a normal integer, decimal or
exponential number. The @characters@ can be any sequence of
characters but may not containing single quotes. The @string_token@
starts with a character in a-z,A-Z and is followed by any number
of characters in the set a-z,A-Z,0-9 and underscore.
OGDI_Capabilities DTD
A proposed DTD has been prepared for those wanting
to validate OGDI_Capabilities documents, though it isn't anticipated that
this would be used in normal practise. In normal practise extra elements
should be gracefully ignored, to support forward compatibility.
GeoTIFF Example
Example: geotiff.xml
Notes:
- The version is set to "3.1", indicating the overall version of the
driver.
- The Capability section is completly omitted since there is
no pertinent information.
- Each layer has a PROJ.4 style SRS.
- Each layer can be accessed as either a Matrix or an Image, so both
families are listed.
- There is an BoundingBox for each layer, showing it's extents, and
resolution. In the past it wasn't possible to safely establish the extents
and resolutions of particular layers from OGDI.
VRF Example
Example: vrf.xml
Note:
- Unlike the geotiff example, this document includes the optional
Capability section so that the ogdi_unique_identity extension
can be associated with the whole datastore.
- This example also demonstrates heirarchy, with two coverages (elev and
col) represented as named sub FeatureTypeLists, each of which has more than
one FeatureType representing the layers supported for that coverage.
- The VRF query expression is represented via a QueryExpression
element. It has to be included with every layer, even though it is the
same for all.
API Changes
This proposal does not require any changes or additions to the RPC prototcol
or the list of possible entry points to a driver. The client api could also
be left unchanged, but it is desirable to provide a standard (and simple) API
for clients to collect information from capabilities documents without
each client having the details of how to parse the capabilities document.
Note that, clients may ignore this API, and get the capabilities document
themselves. In fact, clients wanting to access all aspects of the
capabilities document will need to do so, since this API is simplified
and won't necessarily be extended when new capabilities are added to the
capabilities document.
It is my intention that this API should be implemented in the client c-api
as, either using an existing xml parser like expat, or a simple ad-hoc
parser.
cln_GetVersion()
ecs_Result *cln_GetVersion(int ClientID);
Returns the version string for the current driver. If the current driver
does not return an "ogdi_capabilities" response, a value of "3.0" will be
assumed and returned. The returned value is an ecs_Text structure, or error
if something goes badly wrong.
cln_CheckExtension()
int cln_CheckExtension(int ClientID, const char *extension,
char *layer);
Returns TRUE if the given extension is supported on the indicated layer
(or at the driver level if layer is NULL). Note that the layer name must
be exactly the value is the Name element for that layer
(FeatureType).
Even if a layer name is provided, this function will also check the driver
wide capabilities. In the future it may be able to deduce that some extensions
are supported if the version returned in the capabilities implies that it must.
If an error occurs processing the capabilities document, this function will
return FALSE. It is generally advised to use cln_GetVersion() before
cln_CheckExtension() so that errors processing the capabilities can be
properly captured and reported.
cln_GetLayerCapabilities()
typedef struct {
char *name;
char *title;
char *srs;
int families[MAX_FAMILIES];
char **parents;
char **extensions;
int ll_bounds_set;
double ll_north;
double ll_south;
double ll_east;
double ll_west;
int srs_bounds_set;
double srs_north;
double srs_south;
double srs_east;
double srs_west;
double srs_nsres;
double srs_ewres;
int query_expression_set;
char *qe_prefix;
char *qe_suffix;
char *qe_format;
char *qe_description;
} ecs_LayerCapabilities;
const ecs_LayerCapabilities *cln_GetLayerCapabilities( int ClientID,
int layer_id );
This function fetches a pointer to an internal structure defining all the
information about the indicated layer. The structure is maintained within
the client connection and should not be altered or freed by the caller.
The layer_id is a value between 0 and n-1 where n is the number of
layers (FeatureTypes) defined in the capabilities document. NULL is
returned if layer_id is out of the legal range. Callers are expected to call
the function repeatedly, starting with a layer_id of zero till a NULL is
returned to discover the number of layers available.
- name: The default layer name, as per the Name element.
- title: The longer description of the layer, as per the Title
element. This is usually human readable and one line, and expected to be
suitable for including pick lists of layers.
- srs: The SRS (including the PROJ4: prefix). If missing from the
capabilities document, cln_GetServerProjection() will be used to fill this in.
- families: An array of TRUE/FALSE flags indicating which families
are supported. Test families[Area] to see if the Area family is supported
for instance.
- parents: The layers are returned in non-heirarchical format, but
the parents field contains a NULL terminated string list of names of the
categories forming the path to this feature type. Normally this will be
NULL when the layer has no named parents.
- extensions: The NULL terminated list of extensions applying to
this layer specifically.
- ll_bounds_set: TRUE if the LatLonBoundingBox element was provided,
indicating the following fields are set.
- ll_north, ll_south, ll_east, ll_west: bounds of layer in lat/long.
- srs_north, srs_south, srs_east, srs_west, srs_nsres, srs_ewres:
Bounds and resolution of the layer in layers coordinate system.
- query_expression_set: TRUE if a QueryExpression element was found,
indicating the following fields are set.
- qe_prefix, qe_suffix, qe_format: values of the similarly named
attributes on the QueryExpression element. Qe_format is "" if not provided
in the capabilities.
- qe_description: The value of the query expression description, or
an empty string ("") if not provided. This comes from the data contents of
the QueryExpression tag if any.
Compatibility Issues
- It is required that all OGDI 3.1 drivers/servers will return
a valid OGDI_Capabilities document listing all available layers. This
implies that no currently existing drivers will qualify as 3.1 drivers till
they have been upgraded. This should be a relatively simple process.
- Clients wishing to take advantage of this capabilities will have to
either implement their own support for parsing the capabilities document,
or incorporate an OGDI 3.1 client source update with the client side parsing
support. These clients will still need an adhoc mechanism to establish the
layers of pre-3.1 drivers. Note that clients are not required to consult
the capabilities document, if they require the user to supply the layer
name(s) they are requesting.
- The client API and data model for layer discovery is significantly
different than the current Global Geomatics cln_GetDictionary(),
cln_GetToken() and cln_GetRequest() API. There is no concept of layer names
being split into tokens for instance, with the exception of the replacability
of the query expression. While it should be possible for Global Geomatics
to generate reasonable results from their current API based on a capabilities
document, it won't necessarily be a good fit.
- A few drivers (such as the grid driver, and the Global Geomatics
Arc/Info driver with arbitrary joins from Info) will not be able to be
represented smoothly using the proposed capabilities format, because the
amount of variability possible in the layer names. However, even in these
cases some level of support should be achievable.