<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.opendap.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mjohnson</id>
	<title>OPeNDAP Documentation - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.opendap.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mjohnson"/>
	<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php/Special:Contributions/Mjohnson"/>
	<updated>2026-05-27T21:52:22Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.38.4</generator>
	<entry>
		<id>https://docs.opendap.org/index.php?title=NCML_Module_Aggregation_JoinExisting&amp;diff=6141</id>
		<title>NCML Module Aggregation JoinExisting</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=NCML_Module_Aggregation_JoinExisting&amp;diff=6141"/>
		<updated>2010-12-16T19:31:53Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Explicit Listing of Granules */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Aggregation]]&lt;br /&gt;
[[Category:NCML]]&lt;br /&gt;
&lt;br /&gt;
= Join Existing Aggregation =&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;joinExisting&#039;&#039; aggregation joins multiple granule datasets by concatenating the specified outer dimensional data from the granules into the output.  This results in matrices of the same number of dimensions, but with larger outer dimension cardinality.  The outer dimension sizes of the granules may vary across granule, but any inner dimensions for multi-dimensional data still are required to match.  &lt;br /&gt;
&lt;br /&gt;
The reader is also directed to a basic tutorial of this NcML aggregation which may be found at http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Aggregation.html#joinExisting.  Note that version 1.1.0 of the module does not support all features of joinExisting!  Future versions will add more features.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;PLEASE NOTE&#039;&#039;&#039; that our syntax is slightly different than that of the THREDDS Data Server (TDS), so please refer to this tutorial when using the Hyrax NcML Module!  In particular, we do not process the &amp;lt;aggregation&amp;gt; element prior to other elements in the dataset, so in some cases the relative ordering of the &amp;lt;aggregation&amp;gt; and references to variables within the aggregation matters.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This page describes the behavior of the initial implementation of joinExisting for version 1.1.0 of the NcML Module, bundled with Hyrax 1.6.2.  It is a limited feature set described below.  Please see the Limitations section for more information.&lt;br /&gt;
&lt;br /&gt;
In version 1.1.0, a joinExisting aggregation may be specified in two ways currently:&lt;br /&gt;
&lt;br /&gt;
* Using explicit lists of &#039;&#039;&#039;netcdf&#039;&#039;&#039; elements with the &#039;&#039;ncoords&#039;&#039; attribute correctly specified for all of them.&lt;br /&gt;
* Using a &#039;&#039;&#039;scan&#039;&#039;&#039; element with &#039;&#039;ncoords&#039;&#039; specified and all matching granule datasets having this dimension size&lt;br /&gt;
&lt;br /&gt;
Our example below will clarify this.&lt;br /&gt;
&lt;br /&gt;
Future versions of the module  will implement more of the joinExisting feature set.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
Here we give an example that illustrates the functionality offered by the current version of the aggregation.  This example may also be found on:&lt;br /&gt;
&lt;br /&gt;
http://test.opendap.org:8090/opendap/ioos/mday_joinExist.ncml&lt;br /&gt;
&lt;br /&gt;
with the data granules located in&lt;br /&gt;
&lt;br /&gt;
http://test.opendap.org:8090/opendap/coverage/mday/&lt;br /&gt;
&lt;br /&gt;
=== Granules ===&lt;br /&gt;
&lt;br /&gt;
Assume we have some number of granule datasets with a DDS the same as the following (modulo the dataset name):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Float32 PHssta[time = 1][altitude = 1][lat = 4096][lon = 8192];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 1];&lt;br /&gt;
        Float64 altitude[altitude = 1];&lt;br /&gt;
        Float64 lat[lat = 4096];&lt;br /&gt;
        Float64 lon[lon = 8192];&lt;br /&gt;
    } PHssta;&lt;br /&gt;
} PH2006001_2006031_ssta.nc;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Explicit Listing of Granules ===&lt;br /&gt;
&lt;br /&gt;
We see that here &#039;&#039;time&#039;&#039; is the outer dimension, which is the only dimension we may join along (it is an error to specify an inner).    Given some number of granules with this same shape, consider the following explicit joinExisting aggregation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinExisting test on netcdf Grid granules&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinExisting&amp;quot; &lt;br /&gt;
	       dimName=&amp;quot;time&amp;quot; &amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Note explicit use of ncoords specifying size of &amp;quot;time&amp;quot; in file required --&amp;gt;&lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;/coverage/mday/PH2006001_2006031_ssta.nc&amp;quot;&lt;br /&gt;
                   ncoords=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;/coverage/mday/PH2006032_2006059_ssta.nc&amp;quot;&lt;br /&gt;
                   ncoords=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;/coverage/mday/PH2006060_2006090_ssta.nc&amp;quot;&lt;br /&gt;
                   ncoords=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
First, note that the &#039;&#039;ncoords&#039;&#039; attribute &#039;&#039;&#039;MUST&#039;&#039;&#039; be specified on the individual granules for this version of the module (future versions will relax this requirement and automatically and efficiently load the sizes).  Note that we also specify the &#039;&#039;dimName&#039;&#039;.  Any data array whose outer dimension is called this will be subject to aggregation in the output. &lt;br /&gt;
&lt;br /&gt;
Serving this from Hyrax will result in the following DDS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Float32 PHssta[time = 3][altitude = 1][lat = 4096][lon = 8192];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 3];&lt;br /&gt;
        Float64 altitude[altitude = 1];&lt;br /&gt;
        Float64 lat[lat = 4096];&lt;br /&gt;
        Float64 lon[lon = 8192];&lt;br /&gt;
    } PHssta;&lt;br /&gt;
    Float64 time[time = 3];&lt;br /&gt;
} mday_joinExist.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that the time dimension is now of size 3 to match that we joined three granule datasets together.&lt;br /&gt;
&lt;br /&gt;
Also notice that the map vector for the joined dimension, time, has been duplicated as a sibling of the dataset.  This is done automatically by the aggregation and it is copied into the actual map of the Grid.  This copy is to facilitate datasets which have multiple Grid&#039;s that are to be joined --- the top-level map vector is used as the canonical template map which is then copied into the maps for all the aggregated Grids.  In the case of the joined data being of type Array, this vector would already exist as the coordinate variable for the data matrix.  Since this is the source map for all aggregated Grid&#039;s, any attribute (metadata) changes should be made explicitly on this top-level coordinate variable so that the metadata is shared among all the aggregated Grid map vectors.&lt;br /&gt;
&lt;br /&gt;
=== Using the scan element with ncoords extension ===&lt;br /&gt;
&lt;br /&gt;
Since all of the granules are of uniform size, we may also use the syntactic sugar provided by a Hyrax-specific extension to NcML -- adding the &#039;&#039;ncoords&#039;&#039; attribute to a &#039;&#039;&#039;scan&#039;&#039;&#039; element.   The behavior of this extension is to set the &#039;&#039;ncoords&#039;&#039; for each granule matching the scan to be this value, as if the datasets were each listed explicitly with this value of the attribute.  Here&#039;s an example of using the syntactic sugar that results in the same exact aggregation as the previous explicit one:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!-- joinExisting test on netcdf granules using scan@ncoords extension--&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinExisting test on netcdf Grid granules using scan@ncoords&amp;quot;&lt;br /&gt;
	&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&lt;br /&gt;
	     value=&amp;quot; joinExisting test on netcdf Grid granules using scan@ncoords&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinExisting&amp;quot; &lt;br /&gt;
	       dimName=&amp;quot;time&amp;quot; &amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Filenames have lexicographic and chronological ordering match --&amp;gt;&lt;br /&gt;
    &amp;lt;scan location=&amp;quot;/coverage/mday&amp;quot;&lt;br /&gt;
	  subdirs=&amp;quot;false&amp;quot;&lt;br /&gt;
	  suffix=&amp;quot;.nc&amp;quot;&lt;br /&gt;
	  ncoords=&amp;quot;1&amp;quot;&lt;br /&gt;
	  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
which we see results in the same DDS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Float32 PHssta[time = 3][altitude = 1][lat = 4096][lon = 8192];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 3];&lt;br /&gt;
        Float64 altitude[altitude = 1];&lt;br /&gt;
        Float64 lat[lat = 4096];&lt;br /&gt;
        Float64 lon[lon = 8192];&lt;br /&gt;
    } PHssta;&lt;br /&gt;
    Float64 time[time = 3];&lt;br /&gt;
} mday_joinExist.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Limitations ==&lt;br /&gt;
&lt;br /&gt;
The current version implements only basic functionality.  If there is extended functionality that is needed for your use, please send &amp;lt;mailto:support@opendap.org&amp;gt; to let us know!  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Join Dimension Sizes Must Be Explicitly Declared ===&lt;br /&gt;
&lt;br /&gt;
As we have seen, the most important limitation is that the ncoords must be specified for efficiency reasons.  Future versions will relax this requirement.  The problem is that the size of the output join dimension is dependent on checking the DDS of &#039;&#039;every&#039;&#039; granule in the aggregation, which is computationally expensive for large aggregations unless it is computed once and cached.  The next feature release of the module will include a caching system for solving this general problem and allowing the ncoords to be loaded automatically rather than being specified.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Source of Data for Agrgegated Coordinate Variable on Join Dimension ===&lt;br /&gt;
&lt;br /&gt;
This version does not allow the join dimension&#039;s data to be declared explicitly in the NcML as the NcML tutorial page describes.  This version automatically aggregates &#039;&#039;&#039;all&#039;&#039;&#039; variables with the outer dimension matching the &#039;&#039;dimName&#039;&#039;.  This includes the coordinate variable (map vector in the case of Grid&#039;s) for the join dimension.  These data cannot be overridden from those pulled from the files.  Currently the TDS lists about 5 ways this data can be specified in addition to pulling them from the granules --- we only can pull them from granules now, which seems the most common use.&lt;br /&gt;
&lt;br /&gt;
=== Source of Join Dimension Metadata ===&lt;br /&gt;
&lt;br /&gt;
The metadata for the coordinate variable is pulled from the &#039;&#039;first&#039;&#039; granule dataset.  Modification of coordinate variable metadata is not fully supported yet.&lt;br /&gt;
&lt;br /&gt;
== Future Work ==&lt;br /&gt;
&lt;br /&gt;
The most important addition in the next release will be the ability to efficiently load and cache the granule dimension sizes offline to allow for a highly interactive user experience when data is requested.  This means that the &#039;&#039;ncoords&#039;&#039; attribute will no longer be required on the granules, although doing so results in a more efficient aggregation speed.  &lt;br /&gt;
&lt;br /&gt;
We also plan to allow the data and metadata for the join dimension coordinate variable to be overridden and modified.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=BES_-_Modules_-_NcML_Module&amp;diff=5916</id>
		<title>BES - Modules - NcML Module</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=BES_-_Modules_-_NcML_Module&amp;diff=5916"/>
		<updated>2010-10-27T20:19:36Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Aggregation Tutorials */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
[[Category:NCML]]&lt;br /&gt;
[[Category:BES Modules|NCML Module]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Welcome to the OPeNDAP NcML Data Handler Module v1.1.0 for [http://www.opendap.org/download/hyrax.html Hyrax 1.6.2]!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[Updated for NcML Module v1.1.0 for Hyrax 1.6.2 Release --   15 September 2010]&lt;br /&gt;
&lt;br /&gt;
This module may be added to a [http://www.opendap.org/download/hyrax.html Hyrax 1.6.2] server to extend its data&lt;br /&gt;
serving capability to NcML 2.2 files (see&lt;br /&gt;
http://www.unidata.ucar.edu/software/netcdf/ncml/).  NcML provides support for modifying other datasets in various ways, such as adding metadata and data and aggregating multiple datasets in several ways.&lt;br /&gt;
&lt;br /&gt;
We refer the reader to the Unidata NcML tutorial: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Tutorial.html which will give the basics of using NcML.  We then give a reference manual for the various elements and their attributes.  Additionally we have provided a more extensive tutorial on NcML aggregation.  Please see [[#Aggregation Tutorials]].&lt;br /&gt;
&lt;br /&gt;
Since the DAP Grid is a common case, we will also give a simple example for adding metadata to the various parts of a Grid dataset using NcML.  Please see [[Grid_Metadata_Tutorial]].&lt;br /&gt;
&lt;br /&gt;
== Current Release ==&lt;br /&gt;
&lt;br /&gt;
The most recent release is 1.1.0, which is bundled with (and requires) Hyrax server 1.6.2.  To download, visit the [http://www.opendap.org/download/ncml_handler.html NcML Module Page].&lt;br /&gt;
&lt;br /&gt;
New features in this release:&lt;br /&gt;
&lt;br /&gt;
* joinExisting aggregation initial implementation ([[NCML_Module_Aggregation_JoinExisting]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Features==         &lt;br /&gt;
   &lt;br /&gt;
This version currently implements a subset of NcML 2.2&lt;br /&gt;
functionality, along with some OPeNDAP extensions:&lt;br /&gt;
&lt;br /&gt;
* Metadata Manipulation&lt;br /&gt;
** Addition, Removal, and Modification of attributes to other datasets (NetCDF, HDF4, HD5, etc.) served by the same Hyrax 1.6 server&lt;br /&gt;
** Extends NcML 2.2 to allow for common nested &amp;quot;attribute containers&amp;quot; &lt;br /&gt;
** Attributes can be DAP2 types as well as the NcML types &lt;br /&gt;
** Attributes can be of the special &amp;quot;OtherXML&amp;quot; type for injecting arbitrary XML into a DDX response&lt;br /&gt;
* Data Manipulation&lt;br /&gt;
** Addition of new data variables (scalars or arrays of basic types as well as structures) &lt;br /&gt;
** Variables may be removed from the wrapped dataset&lt;br /&gt;
** Allows the creation of &amp;quot;pure virtual&amp;quot; datasets which do not wrap another dataset&lt;br /&gt;
* Aggregations: JoinNew, JoinExisting Union [[#Aggregation Tutorials]]&lt;br /&gt;
** JoinNew Aggregation ([[NCML_Module_Aggregation_JoinNew]])&lt;br /&gt;
*** Allows multiple datasets to be &amp;quot;joined&amp;quot; by creating a new outer dimension for the aggregated variable&lt;br /&gt;
*** Aggregation member datasets can be listed explicitly with explicit coordinates for the new dimension for each member&lt;br /&gt;
*** Scan: Aggregations can be specified &amp;quot;automatically&amp;quot; by scanning a directory for files matching certain criteria, such as a suffix or regular expression.&lt;br /&gt;
*** Metadata may be added to the new coordinate variable for the new dimension&lt;br /&gt;
** JoinExisting Aggregation ([[NCML_Module_Aggregation_JoinExisting]])&lt;br /&gt;
*** Currently requires the author to specify the &#039;&#039;ncoords&#039;&#039; attribute.&lt;br /&gt;
*** Scan may also be used with &#039;&#039;ncoords&#039;&#039; attribute for uniform sized granules&lt;br /&gt;
*** Only allows join dimension to be aggregated from granules and not overridden in NcML&lt;br /&gt;
** Union Aggregation ([[NCML_Module_Aggregation_Union]])&lt;br /&gt;
*** Merges all member datasets into one by taking the first named instance of variables and metadata from the members&lt;br /&gt;
*** Useful for combining two or more datasets with different variables into a single set&lt;br /&gt;
&lt;br /&gt;
== Installation from Source ==&lt;br /&gt;
For information on how to build and install the NcML Data Module, please see the INSTALL file that came with the source distribution.&lt;br /&gt;
&lt;br /&gt;
= Installation Overview =&lt;br /&gt;
&lt;br /&gt;
The NcML Module requires a working Hyrax 1.6 installation.  It is a module&lt;br /&gt;
that is dynamically loaded into the Hyrax BES (Back End Server) to&lt;br /&gt;
allow it to handle NcML files.  &lt;br /&gt;
&lt;br /&gt;
Please see the file INSTALL for full build and install instructions as&lt;br /&gt;
well as requirements.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; After installation, you MUST restart Hyrax by restarting the BES and&lt;br /&gt;
OLFS so the NcML Module is loaded!&lt;br /&gt;
&lt;br /&gt;
== Requirement: International Components for Unicode (ICU) Library == &lt;br /&gt;
&lt;br /&gt;
The most important external requirement is an installation of the International Components for Unicode (ICU) version 3.6 or higher (tested up to 4.2.1).   The source distributions (as well as some binaries) may be found at the site: http://site.icu-project.org/download&lt;br /&gt;
&lt;br /&gt;
If you are using Linux RPM&#039;s to run Hyrax, you can get an RPM for ICU as well.  Search for the RPM named &amp;quot;libicu&amp;quot; using a package manager or yum, e.g.   If you are compiling the module from source, you will also need the RPM &amp;quot;libicu-devel&amp;quot; to get the headers installed.  &lt;br /&gt;
&lt;br /&gt;
If you install in the default locations, the ncml_module should find the libraries and headers.  Otherwise, please consult the INSTALL file for more information about installing ICU to a non-standard location.&lt;br /&gt;
&lt;br /&gt;
== Testing Installation ==&lt;br /&gt;
&lt;br /&gt;
Test data is provided to see if the installation was successful.  The file sample_virtual_dataset.ncml is a dataset purely created in NcML and doesn&#039;t contain an underlying dataset.  &lt;br /&gt;
You may also view fnoc1_improved.ncml to test adding attributes to an existing netCDF dataset (fnoc1.nc), but this requires the netCDF data handler to be&lt;br /&gt;
installed first!  Several other examples installed also use the HDF4 and HDF5 handlers.&lt;br /&gt;
&lt;br /&gt;
= Functionality =&lt;br /&gt;
&lt;br /&gt;
This version of the NcML Module implements a subset of NcML 2.2&lt;br /&gt;
functionality.  The reader is directed to http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/ for more information on NcML.&lt;br /&gt;
&lt;br /&gt;
Our module can currently:&lt;br /&gt;
&lt;br /&gt;
*Refer only to files being served locally (not remotely)&lt;br /&gt;
*Add, modify, and remove attribute metadata to a dataset&lt;br /&gt;
*Create a purely virtual dataset using just NcML and no underlying dataset&lt;br /&gt;
*Create new scalar variables of any simple NcML type or simple DAP type&lt;br /&gt;
*Create new Structure variables (which can contain new child variables)&lt;br /&gt;
*Create new N-dimensional arrays of simple types (NcML or DAP)&lt;br /&gt;
*Remove existing variables from a wrapped dataset&lt;br /&gt;
*Rename existing variables in a wrapped dataset&lt;br /&gt;
*Name dimensions as a mnemonic for specifying Array shapes&lt;br /&gt;
*Perform union aggregations on multiple datasets, virtual or wrapped or both&lt;br /&gt;
*Perform joinNew aggregations to merge a variable across multiple datasets by creating a new outer dimension&lt;br /&gt;
*Specify aggregation member datasets by scanning directories for files matching certain criteria&lt;br /&gt;
&lt;br /&gt;
We describe each supported NcML element in detail below.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;netcdf&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;netcdf&amp;gt; element is used to define a dataset, either a wrapped dataset that is to be modified, a pure virtual dataset, or a member dataset of an aggregation.  The &amp;lt;netcdf&amp;gt; element is assumed to be the topmost node, or as a child of an aggregation element.&lt;br /&gt;
&lt;br /&gt;
=== Local vs. Remote Datasets ===&lt;br /&gt;
&lt;br /&gt;
We assume that the location attribute (&#039;&#039;netcdf@location&#039;&#039;) refers to the full path (with respect to the BES data root directory) of a &#039;&#039;&#039;&#039;&#039;local&#039;&#039;&#039;&#039;&#039; dataset (served by the same Hyrax server).  The current version of the module cannot be used to modify remote datasets.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;netcdf@location&#039;&#039; is the empty string (or unspecified, as empty is the default), the dataset is a pure virtual dataset, fully specified within the NcML file itself.  Attributes and variables may be fully described and accessed with constraints just as normal datasets in this manner.  The installed sample datafile &amp;quot;sample_virtual_dataset.ncml&amp;quot; is an example test case for this functionality.&lt;br /&gt;
&lt;br /&gt;
=== Unsupported Attributes ===&lt;br /&gt;
&lt;br /&gt;
The current version does not support the following attributes of &amp;lt;netcdf&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
*enhance&lt;br /&gt;
*addRecords&lt;br /&gt;
*fmrcDefinition (will be supported when FMRC aggregation is added)&lt;br /&gt;
*ncoords (will be supported when joinExisting is added)&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;readMetadata&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;readMetadata/&amp;gt; element is the default, so is effectively not needed.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;explicit&amp;gt; element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;explicit/&amp;gt; element simply clears all attribute tables in the referred to netcdf@location before applying the rest of the &lt;br /&gt;
NcML transformations to the metadata.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;dimension&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;dimension&amp;gt; element has limited functionality in this release since the DAP2 doesn&#039;t support dimensions as more than mnemonics at this time.  The limitations are:&lt;br /&gt;
&lt;br /&gt;
* We only parse the &#039;&#039;dimension@name&#039;&#039; and &#039;&#039;dimension@length&#039;&#039; attributes.  &lt;br /&gt;
* Dimensions can only be specified as a direct child of a &amp;lt;netcdf&amp;gt; element prior to any reference to them&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt; &lt;br /&gt;
  &amp;lt;dimension name=&amp;quot;station&amp;quot; length=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;dimension name=&amp;quot;samples&amp;quot; length=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;!-- Some variable elements refer to the dimensions here --&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The dimension element sets up a mapping from the &#039;&#039;name&#039;&#039; to the unsigned integer &#039;&#039;length&#039;&#039; and can be used in a &#039;&#039;variable@shape&#039;&#039; to specify a length for an array dimension (see the section on &amp;lt;variable&amp;gt; below).  The dimension map is cleared when &amp;lt;/netcdf&amp;gt; is encountered (though this doesn&#039;t matter currently since we allow only one right now, but it will matter for aggregation, potentially).  We also do not support &amp;lt;group&amp;gt;, which is the only other legal place in NcML 2.2 for a dimension element.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* If the name and length are not both specified.&lt;br /&gt;
* If the dimension name already exists in the current scope&lt;br /&gt;
* If the length is not an unsigned integer&lt;br /&gt;
* If any of the other attributes specified in NcML 2.2 are used.  We do not handle them, so we consider them errors now.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;variable&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;variable&amp;gt; element is used to:&lt;br /&gt;
&lt;br /&gt;
* Provide lexical scope for a contained &amp;lt;attribute&amp;gt; or &amp;lt;variable&amp;gt; element&lt;br /&gt;
* Rename existing variables &lt;br /&gt;
* Add new scalar variables of simple types&lt;br /&gt;
* Add new Structure variables&lt;br /&gt;
* Add new N-dimensional Array&#039;s of simple types&lt;br /&gt;
* Specify the coordinate variable for the new dimension in a joinNew aggregation &lt;br /&gt;
&lt;br /&gt;
We describe each in turn in more detail.&lt;br /&gt;
&lt;br /&gt;
=== Specifying Lexical Scope with &amp;lt;variable type=&amp;quot;&amp;quot;&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Consider the following example:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;variable name=&amp;quot;u&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Metadata&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;This is metadata!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code assumes that a variable named &amp;quot;u&amp;quot; exists (of any type since we do not specify) and provides the lexical scope for the&lt;br /&gt;
attribute &amp;quot;Metadata&amp;quot; which will be added or modified within the attribute table for the variable &amp;quot;u&amp;quot; (it&#039;s qualified name would be &amp;quot;u.Metadata&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
==== Nested DAP Structure and Grid Scopes ====&lt;br /&gt;
&lt;br /&gt;
Scoping variable elements may be nested if the containing variable is a Structure (this includes the special case of Grid)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;DATA_GRANULE&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;PlanetaryGrid&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;variable name=&amp;quot;percipitate&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;inches&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This adds a &amp;quot;unit&amp;quot; attribute to the variable &amp;quot;percipitate&amp;quot; within the nested Structure&#039;s &lt;br /&gt;
(&amp;quot;DATA_GRANULE.PlanetaryGrid.percipitate&amp;quot; as fully qualified name).  &lt;br /&gt;
Note that we &#039;&#039;&#039;must&#039;&#039;&#039; refer to the type explicitly as a &amp;quot;Structure&amp;quot; so the parser knows&lt;br /&gt;
to traverse the tree.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; the variable might be of type Grid, but the type &amp;quot;Structure&amp;quot; must be used in the NcML to traverse it.&lt;br /&gt;
&lt;br /&gt;
==== Adding Multiple Attributes to the Same Variable ====&lt;br /&gt;
&lt;br /&gt;
Once the variable&#039;s scope is set by the opening &amp;lt;variable&amp;gt; element, more than one attribute can be specified within it.  This will make the NcML more readable and also will make the parsing more efficient since the variable will only need to be looked up once.&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_1&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Hello&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_2&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;World!&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
should be preferred over:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_1&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Hello&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_2&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;World!&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
although they produce the same result.  Any number of attributes can be specified before the variable is closed.&lt;br /&gt;
&lt;br /&gt;
=== Renaming Existing Variables ===&lt;br /&gt;
&lt;br /&gt;
The attribute &#039;&#039;variable@orgName&#039;&#039; is used to rename an existing variable. &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;NewName&amp;quot; orgName=&amp;quot;OldName&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing variable at the current scope named &amp;quot;OldName&amp;quot; to &amp;quot;NewName&amp;quot;.  After this point in the NcML file (such as in constraints specified for the DAP request), the variable is known by &amp;quot;NewName&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note that the type is not required here --- the variable is assumed to exist and its existing type is used.  It is not possible to change the type of an existing variable at this time!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:  &lt;br /&gt;
* If a variable with &#039;&#039;variable@orgName&#039;&#039; doesn&#039;t exist in the current scope&lt;br /&gt;
* If the new name &#039;&#039;variable@name&#039;&#039; is already taken in the current scope&lt;br /&gt;
* If a new variable is created but does not have exactly one values element&lt;br /&gt;
&lt;br /&gt;
=== Adding a New Scalar Variable ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;variable&amp;gt; element can be used to create a new scalar variable of a simple type (i.e. an atomic NcML type such as &amp;quot;int&amp;quot; or &amp;quot;float&amp;quot;, or any DAP atomic type, such as &amp;quot;UInt32&amp;quot; or &amp;quot;URL&amp;quot;) by specifying an empty &#039;&#039;variable@shape&#039;&#039; (which is the default), a simple type for &#039;&#039;variable@type&#039;&#039;, and a contained &amp;lt;values&amp;gt; element with the one value of correct type. &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;TheAnswerToLifeTheUniverseAndEverything&amp;quot; type=&amp;quot;double&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;SolvedBy&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;Deep Thought&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;values&amp;gt;42.000&amp;lt;/values&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create a new variable named &amp;quot;TheAnswerToLifeTheUniverseAndEverything&amp;quot; at the current scope.  It has no shape so will be a scalar of type &amp;quot;double&amp;quot; and will have the value 42.0.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* It is a parse error to not specify a &amp;lt;values&amp;gt; element with exactly one proper value of the variable type.&lt;br /&gt;
* It is a parse error to specify a malformed or out of bounds value for the data type&lt;br /&gt;
&lt;br /&gt;
=== Adding a New Structure Variable ===&lt;br /&gt;
&lt;br /&gt;
A new Structure variable can be specified at the global scope or within another Structure.  It is illegal for an array to have type structure, so the shape must be empty.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;MyNewStructure&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;MetaData&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;This is metadata!&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;ContainedScalar1&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&amp;lt;values&amp;gt;I live in a new structure!&amp;lt;/values&amp;gt;&amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;ContainedInt1&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;&amp;lt;values&amp;gt;42&amp;lt;/values&amp;gt;&amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
specifies a new structure called &amp;quot;MyNewStructure&amp;quot; which contains two scalar variable fields &amp;quot;ContainedScalar1&amp;quot; and &amp;quot;ContainedInt1&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
Nested structures are allowed as well.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Error&#039;&#039;&#039;: &lt;br /&gt;
* If another variable or attribute exists at the current scope with the new name.  &lt;br /&gt;
* If a &amp;lt;values&amp;gt; element is specified as a direct child of a new Structure --- structures cannot contain values, only attributes and other variables.&lt;br /&gt;
&lt;br /&gt;
=== Adding a New N-dimensional Array ===&lt;br /&gt;
&lt;br /&gt;
An N-dimensional array of a simple type may be created virtually as well by specifying a non-empty &#039;&#039;variable@shape&#039;&#039;.  The shape contains the array dimensions in left-to-right order of slowest varying dimension first.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;FloatArray&amp;quot; type=&amp;quot;float&amp;quot; shape=&amp;quot;2 5&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;!-- values specified in row major order (leftmost dimension in shape varies slowest) &lt;br /&gt;
	Any whitespace is a valid separator by default, so we can use newlines to pretty print 2D matrices.&lt;br /&gt;
	--&amp;gt;&lt;br /&gt;
      &amp;lt;values&amp;gt;&lt;br /&gt;
	0.1 0.2 0.3 0.4 0.5&lt;br /&gt;
	1.1 1.1 1.3 1.4 1.5&lt;br /&gt;
      &amp;lt;/values&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will specify a 2x5 dimension array of float values called &amp;quot;FloatArray&amp;quot;.  The &amp;lt;values&amp;gt; element must contain 2x5=10 values in row major order (slowest varying dimension first).  Since whitespace is the default separator, we use a newline to show the dimension boundary for the values, which is easy to see for a 2D matrix such as this.&lt;br /&gt;
&lt;br /&gt;
A dimension name may also be used to refer mnemonically to a length.  The DAP response will use this mnemonic in its output, but it is not currently used for shared dimensions, only as a mnemonic.   See the section on the &amp;lt;dimension&amp;gt; element for more information.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt;&lt;br /&gt;
 &amp;lt;dimension name=&amp;quot;station&amp;quot; length=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;dimension name=&amp;quot;sample&amp;quot; length=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;FloatArray&amp;quot; type=&amp;quot;float&amp;quot; shape=&amp;quot;station sample&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;values&amp;gt;&lt;br /&gt;
	0.1 0.2 0.3 0.4 0.5&lt;br /&gt;
	1.1 1.1 1.3 1.4 1.5&lt;br /&gt;
      &amp;lt;/values&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will produce the same 2x5 array, but will incorporate the dimension mnemonics into the response.  For example, here&#039;s the DDS response:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
     Float32 FloatArray[station = 2][samples = 5];&lt;br /&gt;
} sample_virtual_dataset.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;values&amp;gt; element respects the &#039;&#039;values@separator&#039;&#039; attribute if whitespace isn&#039;t correct.  This is very useful for arrays of strings with whitespace, for example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;StringArray&amp;quot; type=&amp;quot;string&amp;quot; shape=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;values separator=&amp;quot;*&amp;quot;&amp;gt;String 1*String 2*String 3&amp;lt;/values&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
creates a length 3 array of string StringArray = {&amp;quot;String 1&amp;quot;, &amp;quot;String 2&amp;quot;, &amp;quot;String 3&amp;quot;}.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:  &lt;br /&gt;
* It is an error to specify the incorrect number of values&lt;br /&gt;
* It is an error if any value is malformed or out of range for the data type.&lt;br /&gt;
* It is an error to specify a named dimension which does not exist in the current &amp;lt;netcdf&amp;gt; scope.&lt;br /&gt;
* It is an error to specify an Array whose flattened size (product of dimensions) is &amp;gt; 2^31-1.&lt;br /&gt;
&lt;br /&gt;
=== Specifying the new coordinate variable for a joinNew aggregation ===&lt;br /&gt;
&lt;br /&gt;
In the special case of a joinNew aggregation, the new coordinate variable may be specified with the &amp;lt;variable&amp;gt; element.  The new coordinate variable is &#039;&#039;defined&#039;&#039; to have the same name as the new dimension.  This allows for several things:&lt;br /&gt;
&lt;br /&gt;
*Explicit specification of the variable type and coordinates for the new dimension&lt;br /&gt;
*Specification of the metadata for the new coordinate variable &lt;br /&gt;
&lt;br /&gt;
In the first case, the author can specify explicitly the type of the new coordinate variable and the actual values for each dataset.  In this case, the variable &#039;&#039;must&#039;&#039; be specified &#039;&#039;after&#039;&#039; the aggregation element in the file so the new dimension&#039;s size (number of member datasets) may be known and error checking performed.  Metadata can also be added to the variable here.&lt;br /&gt;
&lt;br /&gt;
In the second case, the author may just specify the variable name, which allows one to specify the metadata for a coordinate variable that is automatically generated by the aggregation itself.  This is the only allowable case for a variable element to &#039;&#039;not&#039;&#039; contain a values element!  Coordinate variables are generated automatically in two cases:&lt;br /&gt;
&lt;br /&gt;
*The author has specified an explicit list of member datasets, with or without explicit coordVal attributes.  &lt;br /&gt;
*The author has used a &amp;lt;scan&amp;gt; element to specify the member datasets via a directory scan&lt;br /&gt;
&lt;br /&gt;
In this case, the &amp;lt;variable&amp;gt; element may come before or after the &amp;lt;aggregation&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*If an explicit variable is declared for the new coordinate variable:&lt;br /&gt;
** And it contains explicit values, the number of values must be equal to the number of member datasets in the aggregation.&lt;br /&gt;
** It must be specifed &#039;&#039;after&#039;&#039; the &amp;lt;aggregation&amp;gt; element&lt;br /&gt;
&lt;br /&gt;
* If a numeric coordVal is used to specify the first member dataset&#039;s coordinate, then &#039;&#039;all&#039;&#039; datasets must contain a numerical coordinate.&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variable (variableAgg) is not found in &#039;&#039;all&#039;&#039; member datasets.&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variable is not of the same type in &#039;&#039;all&#039;&#039; member datasets.  Coercion is &#039;&#039;not&#039;&#039; performed!&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variables in all member datasets do not have the same shape&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if an explicit coordinate variable is specified with a shape that is &#039;&#039;not&#039;&#039; the same as the new dimension name (and the variable name itself).&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;values&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;values&amp;gt; element can only be used in the context of a &#039;&#039;&#039;new&#039;&#039;&#039; variable of scalar or array type.  We cannot change the values for existing variables in this version of the handler. &lt;br /&gt;
The characters content of a &amp;lt;values&amp;gt; element is considered to be a separated list of value tokens valid for the type of the variable of the parent element.  The number of specified tokens in the content &#039;&#039;must&#039;&#039; equal the product of the dimensions of the enclosing &#039;&#039;variable@shape&#039;&#039;, or be one value for a scalar.  It is an error to &#039;&#039;not&#039;&#039; specify a &amp;lt;values&amp;gt; element for a declared new variable as well.  &lt;br /&gt;
&lt;br /&gt;
=== Changing the Separator Tokens === &lt;br /&gt;
&lt;br /&gt;
The author may specify values@separator to change the default value token separator from the default whitespace.  This is very useful for specifying arrays of strings with whitespace in them, or if data in CSV form is being pasted in.  &lt;br /&gt;
&lt;br /&gt;
=== Autogeneration of Uniform Arrays ===&lt;br /&gt;
&lt;br /&gt;
We also can parse &#039;&#039;values@start&#039;&#039; and &#039;&#039;values@increment&#039;&#039; INSTEAD OF tokens in the content.  This will &amp;quot;autogenerate&amp;quot; a uniform array of values of the given product of dimensions length for the containing variable.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Evens&amp;quot; type=&amp;quot;int&amp;quot; shape=&amp;quot;100&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;values start=&amp;quot;0&amp;quot; increment=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will specify an array of the first 100 even numbers (including 0).  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* If the incorrect number of tokens are specified for the containing variable&#039;s shape&lt;br /&gt;
* If any value token cannot be parsed as a valid value for the containing variable&#039;s type&lt;br /&gt;
* If content is specified in addition to start and increment&lt;br /&gt;
* If only one of start or increment is specified&lt;br /&gt;
* If the values element is placed anywhere except within a NEW variable.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;attribute&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
As an overview, whenever the parser encounters an &amp;lt;attribute&amp;gt; with a non-existing name (at the current scope),&lt;br /&gt;
it creates a new one, whether a container or atomic attribute (see below).  If the attribute exists,&lt;br /&gt;
its value and/or type is modified to those specified in the &amp;lt;attribute&amp;gt; element.  If an attribute&lt;br /&gt;
structure (container) exists, it is used to define a nested lexical scope for child attributes.  &lt;br /&gt;
&lt;br /&gt;
Attributes may be scalar (one value) or one dimensional arrays.  Arrays are specified by using whitespace (default) to separate the different values.  The attribute@separator may also be set in order to specify a different separator, such as CSV format or to specify a non-whitespace separator so strings with whitespace are not tokenized.  We will give examples of creating array attributes below.&lt;br /&gt;
&lt;br /&gt;
=== Adding New Attributes or Modifying an Existing Attribute ===&lt;br /&gt;
&lt;br /&gt;
If a specified attribute with the attribute@name does not exist at the current lexical scope, &lt;br /&gt;
a new one is created with the given type and value.  For example, assume &amp;quot;new_metadata&amp;quot; doesn&#039;t&lt;br /&gt;
exist at the current parse scope.  Then:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;new_metadata&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;This is a new entry!&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create the attribute at that scope.  Note that value can be specified in the content of the &lt;br /&gt;
element as well.  This is identical to the above:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;new_metadata&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;This is a new entry!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the attribute@name already exists at the scope, it is modified to contain the specified type and value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Arrays ====&lt;br /&gt;
&lt;br /&gt;
As in NcML, for numerical types an array can be specified by separating the tokens by whitespace (default) or be&lt;br /&gt;
specifying the token separator with attribute@separator.  For example,&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;myArray&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 2 3&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;myArray&amp;quot; type=&amp;quot;int&amp;quot; separator=&amp;quot;,&amp;quot;&amp;gt;1,2,3&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
both specify the same array of three integers named &amp;quot;myArray&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
TODO Add more information on splitting with a separator!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Structures (Containers) ====&lt;br /&gt;
&lt;br /&gt;
We use attribute@type=&amp;quot;Structure&amp;quot; to define a new (or existing) attribute container.   So if we&lt;br /&gt;
wanted to add a new attribute structure, we&#039;d use something like this: &lt;br /&gt;
&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;MySamples&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Location&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Station 1&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Samples&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 4 6&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assuming &amp;quot;MySamples&amp;quot; doesn&#039;t already exist, an attribute container will be created at the current scope&lt;br /&gt;
and the &amp;quot;Location&amp;quot; and &amp;quot;Samples&amp;quot; attributes will be added to it.&lt;br /&gt;
&lt;br /&gt;
Note that we can create nested attribute structures to arbitrary depth this way as well.&lt;br /&gt;
&lt;br /&gt;
If the attribute container with the given name already exists at the current scope, &lt;br /&gt;
then the attribute@type=&amp;quot;Structure&amp;quot; form is used to define&lt;br /&gt;
the lexical scope for the container.  In other words, child &amp;lt;attribute&amp;gt; elements will&lt;br /&gt;
be processed within the scope of the container.   For example, in the above example, if&lt;br /&gt;
&amp;quot;MySamples&amp;quot; already exists, then the &amp;quot;Location&amp;quot; and &amp;quot;Samples&amp;quot; will be processed within the&lt;br /&gt;
existing container (they may or may not already exist as well).&lt;br /&gt;
&lt;br /&gt;
==== Renaming an Existing Attribute or Attribute Container ====&lt;br /&gt;
&lt;br /&gt;
We also support the attribute@orgName attribute for renaming attributes.   &lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;NewName&amp;quot; orgName=&amp;quot;OldName&amp;quot; type=&amp;quot;string&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing attribute &amp;quot;OldName&amp;quot; to &amp;quot;NewName&amp;quot; while leaving its value alone.&lt;br /&gt;
If attribute@value is also specified, then the attribute is renamed &#039;&#039;and&#039;&#039; has its value modified.&lt;br /&gt;
&lt;br /&gt;
This works for renaming attribute containers as well:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;MyNewContainer&amp;quot; orgName=&amp;quot;MyOldContainer&amp;quot; type=&amp;quot;Structure&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing &amp;quot;MyOldContainer&amp;quot; to &amp;quot;MyNewContainer&amp;quot;.  Note that any children&lt;br /&gt;
of this container will remain in it.&lt;br /&gt;
&lt;br /&gt;
=== DAP &#039;&#039;OtherXML&#039;&#039; Extension ===&lt;br /&gt;
&lt;br /&gt;
The module now allows specification of attributes of the new DAP type &amp;quot;OtherXML&amp;quot;.  This allows the NCML file author to inject arbitrary well-formed XML into an attribute for clients that want XML metadata rather than just string or url.  Internally, the attribute is still a string (and in a DAP DAS response will be quoted inside one string).  However, since it is XML, the NCMLParser still parses it and checks it for well-formedness (but NOT against schemas).  This extension allows the NCMLParser to parse the arbitrary XML within the given attribute without causing errors, since it can be any XML.  &lt;br /&gt;
&lt;br /&gt;
The injected XML is most useful in the DDX response, where it shows up directly in the response as XML.  XSLT and other clients can then parse it.&lt;br /&gt;
&lt;br /&gt;
==== Errors ====&lt;br /&gt;
&lt;br /&gt;
*The XML &#039;&#039;&#039;must&#039;&#039;&#039; be in the content of the &amp;lt;attribute type=&amp;quot;OtherXML&amp;quot;&amp;gt; element.  It is a parser error for &#039;&#039;attribute@value&#039;&#039; to be set if &#039;&#039;attribute@type&#039;&#039; is &amp;quot;OtherXML&amp;quot;.  &lt;br /&gt;
*The XML must also be well-formed since it is parsed.  A parse error will be thrown if the OtherXML is malformed.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of the use of this special case.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf xmlns=&amp;quot;http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2&amp;quot; location=&amp;quot;/coverage/200803061600_HFRadar_USEGC_6km_rtv_SIO.nc&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;someName&amp;quot; type=&amp;quot;OtherXML&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;Domain xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot; &lt;br /&gt;
                xmlns:ows=&amp;quot;http://www.opengis.net/ows/1.1&amp;quot;&lt;br /&gt;
                xmlns:gml=&amp;quot;http://www.opengis.net/gml/3.2&amp;quot;&lt;br /&gt;
                &amp;gt;&lt;br /&gt;
            &amp;lt;SpatialDomain&amp;gt;&lt;br /&gt;
                &amp;lt;ows:BoundingBox crs=&amp;quot;urn:ogc:def:crs:EPSG::4326&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;ows:LowerCorner&amp;gt;-97.8839 21.736&amp;lt;/ows:LowerCorner&amp;gt;&lt;br /&gt;
                    &amp;lt;ows:UpperCorner&amp;gt;-57.2312 46.4944&amp;lt;/ows:UpperCorner&amp;gt;&lt;br /&gt;
                &amp;lt;/ows:BoundingBox&amp;gt;&lt;br /&gt;
            &amp;lt;/SpatialDomain&amp;gt;&lt;br /&gt;
            &amp;lt;TemporalDomain&amp;gt;&lt;br /&gt;
                &amp;lt;gml:timePosition&amp;gt;2008-03-27T16:00:00.000Z&amp;lt;/gml:timePosition&amp;gt;&lt;br /&gt;
            &amp;lt;/TemporalDomain&amp;gt;&lt;br /&gt;
        &amp;lt;/Domain&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedCRS xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;urn:ogc:def:crs:EPSG::4326&amp;lt;/SupportedCRS&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedFormat xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;netcdf-cf1.0&amp;lt;/SupportedFormat&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedFormat xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;dap2.0&amp;lt;/SupportedFormat&amp;gt;&lt;br /&gt;
    &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039; Put the DDX response for the above in here!&lt;br /&gt;
&lt;br /&gt;
====Namespace Closure====&lt;br /&gt;
&lt;br /&gt;
Furthermore, the parser will make the chunk of OtherXML &amp;quot;namespace closed&amp;quot;.  This means any namespaces specified in parent NCML elements of the OtherXML tree will be &amp;quot;brought down&amp;quot; and added to the &#039;&#039;root&#039;&#039; OtherXML elements so that the subtree may be pulled out and added to the DDX and still have its namespaces.  The algorithm doesn&#039;t just bring used prefixes, but brings &#039;&#039;all&#039;&#039; of the lexically scoped closest namespaces in all ancestors.  In other words, it adds unique namespaces (as determined by prefix) in order from the root of the OtherXML tree as it traverses to the root of the NCML document.  &lt;br /&gt;
&lt;br /&gt;
Namespace closure is a syntactic sugar that simplifies the author&#039;s task since they can specify the namespaces just once at the top of the NCML file and expect that when the subtree of XML is added to the DDX that these namespaces will come along with that subtree of XML.  Otherwise they have to explicitly add the namespaces to each attributes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039; Add an example!&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;remove&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;remove&amp;gt; element can remove attributes and variables.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;attribute name=&amp;quot;NC_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;remove name=&amp;quot;base_time&amp;quot; type=&amp;quot;attribute&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will remove the attribute named &amp;quot;base_time&amp;quot; in the attribute structure named &amp;quot;NC_GLOBAL&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Note that this works for attribute containers as well!  We could recursively remove the &#039;&#039;entire&#039;&#039;&lt;br /&gt;
attribute container (i.e. it and all its children) with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;remove name=&amp;quot;NC_GLOBAL&amp;quot; type=&amp;quot;attribute&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It also can be used to remove variables from existing datasets:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
  &amp;lt;remove name=&amp;quot;SomeExistingVariable&amp;quot; type=&amp;quot;variable&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This also recurses on variables of type Structure --- the entire structure including all of its children are removed from the dataset&#039;s response.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* It is a parse error if the given attribute or variable doesn&#039;t exist in the current scope&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;aggregation&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
Aggregation involves combining multiple datasets (&amp;lt;netcdf&amp;gt;) into a virtual &amp;quot;single&amp;quot; dataset in various ways.  For a tutorial on aggregation in NcML 2.2, the reader is referred to the Unidata page: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Aggregation.html&lt;br /&gt;
&lt;br /&gt;
NcML 2.2 supports multiple types of aggregation: union, joinNew, joinExisting, and fmrc (forecast model run collection).  &lt;br /&gt;
&lt;br /&gt;
The current version of the NcML module supports two of these aggregations:&lt;br /&gt;
&lt;br /&gt;
*Union [[NCML_Module_Aggregation_Union]]&lt;br /&gt;
*JoinNew [[NCML_Module_Aggregation_JoinNew]]&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;union&#039;&#039; aggregation specifies that the first instance of a variable or attribute (by name) that is found in the ordered list of datasets will be the one in the output aggregation.   This is useful for combining two dataset files, each which may contain a single variable, into a composite dataset with both variables.&lt;br /&gt;
&lt;br /&gt;
A JoinNew aggregation joins a variable which exists in multiple datasets (usually samples of a datum over time) into a new variable containing the data from &#039;&#039;all&#039;&#039; member datasets by creating a new outer dimension.  The &#039;&#039;i&#039;&#039;th component in the new outer dimension is the variable&#039;s data from the &#039;&#039;i&#039;&#039;th member dataset.  It also adds a new coordinate variable of whose name is the new dimension&#039;s name and whose shape (length) is the new dimension as well.  This new coordinate variable may be explicitly given by the author or may be autogenerated in one of several ways.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;scan&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The scan element can be used within an aggregation context to allow a directory to be searched in various ways in order to specify the members of an aggregation.  This allows a static NcML file to refer to an aggregation which may change over time, such as where a new data file is generated each day.&lt;br /&gt;
&lt;br /&gt;
We describe usage of the &amp;lt;scan&amp;gt; element in detail in the joinNew aggregation tutorial at [[NCML_Module_Aggregation_JoinNew]].&lt;br /&gt;
&lt;br /&gt;
= Errors =&lt;br /&gt;
&lt;br /&gt;
There are three types of error messages that may be returned:&lt;br /&gt;
&lt;br /&gt;
* Internal Error&lt;br /&gt;
* Resource Not Found Error&lt;br /&gt;
* Parse Error&lt;br /&gt;
&lt;br /&gt;
== Internal Errors ==&lt;br /&gt;
&#039;&#039;&#039;Internal errors&#039;&#039;&#039; should be reported to support@opendap.org as they are likely bugs.&lt;br /&gt;
&lt;br /&gt;
== Resource Not Found Errors ==&lt;br /&gt;
&lt;br /&gt;
If the netcdf@location specifies a non-existent local dataset (one that is not being served by&lt;br /&gt;
the same Hyrax server), it will specify the resource was not found.   This may also be returned&lt;br /&gt;
if a handler for the specified dataset is not currently loaded in the BES.  Users should test that the&lt;br /&gt;
dataset to be wrapped already exists and can be viewed on the running server before writing NcML &lt;br /&gt;
to add metadata.  It&#039;s also an error to refer to remote datasets (at this time).&lt;br /&gt;
&lt;br /&gt;
== Parse Errors ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse errors&#039;&#039;&#039; are user errors in the NcML file.  These could be malformed XML, malformed NcML, &lt;br /&gt;
unimplemented features of NcML, or could be errors in referring to the wrapped dataset.  &lt;br /&gt;
&lt;br /&gt;
The error message should specify &lt;br /&gt;
the error condition as well as the &amp;quot;current scope&amp;quot; as a fully qualified DAP name within the &lt;br /&gt;
loaded dataset.  This should be enough information to correct the parse error as new NcML&lt;br /&gt;
files are created.&lt;br /&gt;
&lt;br /&gt;
The parser will generate parse errors in various &lt;br /&gt;
situations where it expects to find certain structure in the underlying dataset.  Some examples:&lt;br /&gt;
&lt;br /&gt;
* A variable of the given name was not found at the current scope&lt;br /&gt;
* attribute@orgName was specified, but the attribute cannot be found at current scope.&lt;br /&gt;
* attribute@orgName was specified, but the new name is already used at current scope.&lt;br /&gt;
* remove specified a non-existing attribute name&lt;br /&gt;
&lt;br /&gt;
= Grid Metadata Tutorial =&lt;br /&gt;
&lt;br /&gt;
Please see the page [[Grid_Metadata_Tutorial]] for an example of adding metadata to the various parts of a DAP Grid variable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Aggregation Tutorials =&lt;br /&gt;
&lt;br /&gt;
The NcML module may also be used to aggregate multiple datasets into one virtual dataset.  We currently support two of the NcML aggregtions:&lt;br /&gt;
&lt;br /&gt;
*Union [[NCML_Module_Aggregation_Union]]:  combine multiple datasets into one by merging variables together, selecting the first of each unique name.&lt;br /&gt;
*JoinNew [[NCML_Module_Aggregation_JoinNew]]: combine variables across multiple datasets by creating a new outer dimension and coordinate variable for each of the sample datasets.&lt;br /&gt;
*JoinExisting [[NCML_Module_Aggregation_JoinExisting]]: combine variables with a common named outer dimension along that dimension by concatenating data for that dimension&lt;br /&gt;
Please see the sections for a tutorial on the various uses of these aggregations.&lt;br /&gt;
&lt;br /&gt;
= Additions/Changes to NcML 2.2 =&lt;br /&gt;
&lt;br /&gt;
This section will keep track of changes to the NcML 2.2 schema.  Eventually these&lt;br /&gt;
will be rolled into a new schema.&lt;br /&gt;
&lt;br /&gt;
== Attribute Structures (Containers) ==&lt;br /&gt;
This module also adds functionality beyond the current NcML 2.2 schema&lt;br /&gt;
--- it can handle nested &amp;lt;attribute&amp;gt; elements in order to make&lt;br /&gt;
attribute structures.  This is done by using the &amp;lt;attribute&lt;br /&gt;
type=&amp;quot;Structure&amp;quot;&amp;gt; form, for example:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;MySamples&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Location&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Station 1&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Samples&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 4 6&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;MyContainer&amp;quot; describes an attribute structure with two attribute fields,&lt;br /&gt;
a string &amp;quot;Location&amp;quot; and an array of int&#039;s called &amp;quot;Samples&amp;quot;.  &lt;br /&gt;
Note that an attribute structure of this form can&lt;br /&gt;
only contain other &amp;lt;attribute&amp;gt; elements and NOT a value.&lt;br /&gt;
&lt;br /&gt;
If the container does not already exist, it will be created at the scope it is declared, which could&lt;br /&gt;
be:&lt;br /&gt;
&lt;br /&gt;
* Global (top of dataset)&lt;br /&gt;
* Within a variable&#039;s attribute table&lt;br /&gt;
* Within another attribute container&lt;br /&gt;
&lt;br /&gt;
If an attribute container of the given name already exists at the lexical scope, it is traversed &lt;br /&gt;
in order to define the scope for the nested (children) attributes it contains.&lt;br /&gt;
&lt;br /&gt;
== Unspecified Variable Type Matching for Lexical Scope ==&lt;br /&gt;
&lt;br /&gt;
We also allow the type attribute of a variable element (variable@type) to be the empty string &lt;br /&gt;
(or unspecified) when using existing variables to define the lexical scope of an &amp;lt;attribute&amp;gt; &lt;br /&gt;
transformation.  In the schema, variable@type is (normally) required.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DAP 2 Types ==&lt;br /&gt;
&lt;br /&gt;
Additionally, we allow DAP2 atomic types (such as UInt32, URL) in addition to the NcML types.  &lt;br /&gt;
The NcML types are mapped onto the closest DAP2 type internally.&lt;br /&gt;
&lt;br /&gt;
== DAP OtherXML Attribute Type ==&lt;br /&gt;
&lt;br /&gt;
We also allow attributes to be of the new DAP type &amp;quot;OtherXML&amp;quot; for injecting arbitrary XML into an attribute as content rather than trying to form a string.  This allows the parser to check well-formedness.&lt;br /&gt;
&lt;br /&gt;
== Forward Declaration of Dimensions ==&lt;br /&gt;
&lt;br /&gt;
Since we use a SAX parser for efficiency, we require the &amp;lt;dimension&amp;gt; elements to come &#039;&#039;before&#039;&#039; their use in a &#039;&#039;variable@shape&#039;&#039;.  One way to change the schema to allow this is to force the dimension elements to be specified in a sequence after explicit and metadata choice and before all other elements.&lt;br /&gt;
&lt;br /&gt;
== Aggregation Element Location and Processing Order Differences ==&lt;br /&gt;
&lt;br /&gt;
NcML specifies that if a dataset (&amp;lt;netcdf&amp;gt; element) specifies an aggregation element, the aggregation element is always processed first, regardless of its ordering within the &amp;lt;netcdf&amp;gt; element.  Our parser, since it is SAX and not DOM, modifies this behavior in that order matters in some cases:&lt;br /&gt;
&lt;br /&gt;
* Metadata (&amp;lt;attribute&amp;gt;) elements specified &#039;&#039;prior&#039;&#039; to an aggregation &amp;quot;shadow&amp;quot; the aggregation versions.  This is be useful for &amp;quot;overriding&amp;quot; an attribute or variable in a union aggregation, where the first found will take precedence. &lt;br /&gt;
* JoinNew: If the new coordinate variable&#039;s data is to be set explicitly by specifying the new dimension&#039;s shape (either with explicit data or the autogenerated data using values@start and values@increment attributes), the &amp;lt;variable&amp;gt; &#039;&#039;must&#039;&#039; come after the aggregation since the size of the dimension is unknown until the aggregation element is processed.&lt;br /&gt;
&lt;br /&gt;
= Backward Compatibility Issues =&lt;br /&gt;
&lt;br /&gt;
Due to the way shared dimensions were implemented in the NetCDF, HDF4, and HDF5 handlers, the DAS responses did not follow the DAP2 specification.  The NcML module, on the other hand, generates DAP2 compliant DAS for these datasets, which means that wrapping some datasets in NcML will generate a DAS with a different structure.  This is important for the NcML author since it changes the names of attributes and variables.  In order for the module to find the correct scope for adding metadata, for example, the DAP2 DAS must be used.  &lt;br /&gt;
&lt;br /&gt;
In general, what this means is that an empty &amp;quot;passthrough&amp;quot; NcML file should be the starting point for authoring an NcML file.  This file would just specify a dataset and nothing else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;/data/ncml/myNetcdf.nc&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The author would then request the DAS response for the NCML file and use that as the starting point for modifications to the original dataset. &lt;br /&gt;
&lt;br /&gt;
More explicit examples are given below.&lt;br /&gt;
&lt;br /&gt;
== NetCDF ==&lt;br /&gt;
&lt;br /&gt;
The NetCDF handler represents some NC datasets as a DAP 2 Grid, but the returned DAS is not consistent with the DAP 2 spec for the attribute hierarchy for such a Grid.  The map vector attributes are placed as siblings of the grid attributes rather than within the grid lexical scope.  For example, here&#039;s the NetCDF Handler DDS for a given file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Int16 cldc[time = 456][lat = 21][lon = 360];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 456];&lt;br /&gt;
        Float32 lat[lat = 21];&lt;br /&gt;
        Float32 lon[lon = 360];&lt;br /&gt;
    } cldc;&lt;br /&gt;
} cldc.mean.nc;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
showing the Grid.  Here&#039;s the DAS the NetCDF handler generates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    lat {&lt;br /&gt;
        String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
        String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
        Float32 actual_range 10.00000000, -10.00000000;&lt;br /&gt;
    }&lt;br /&gt;
    lon {&lt;br /&gt;
        String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
        String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
        Float32 actual_range 0.5000000000, 359.5000000;&lt;br /&gt;
    }&lt;br /&gt;
    time {&lt;br /&gt;
        String units &amp;quot;days since 1-1-1 00:00:0.0&amp;quot;;&lt;br /&gt;
        String long_name &amp;quot;Time&amp;quot;;&lt;br /&gt;
        String delta_t &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
        String avg_period &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
        Float64 actual_range 715511.00000000000, 729360.00000000000;&lt;br /&gt;
    }&lt;br /&gt;
    cldc {&lt;br /&gt;
        Float32 valid_range 0.000000000, 8.000000000;&lt;br /&gt;
        Float32 actual_range 0.000000000, 8.000000000;&lt;br /&gt;
        String units &amp;quot;okta&amp;quot;;&lt;br /&gt;
        Int16 precision 1;&lt;br /&gt;
        Int16 missing_value 32766;&lt;br /&gt;
        Int16 _FillValue 32766;&lt;br /&gt;
        String long_name &amp;quot;Cloudiness Monthly Mean at Surface&amp;quot;;&lt;br /&gt;
        String dataset &amp;quot;COADS 1-degree Equatorial Enhanced\\012AI&amp;quot;;&lt;br /&gt;
        String var_desc &amp;quot;Cloudiness\\012C&amp;quot;;&lt;br /&gt;
        String level_desc &amp;quot;Surface\\0120&amp;quot;;&lt;br /&gt;
        String statistic &amp;quot;Mean\\012M&amp;quot;;&lt;br /&gt;
        String parent_stat &amp;quot;Individual Obs\\012I&amp;quot;;&lt;br /&gt;
        Float32 add_offset 3276.500000;&lt;br /&gt;
        Float32 scale_factor 0.1000000015;&lt;br /&gt;
    }&lt;br /&gt;
    NC_GLOBAL {&lt;br /&gt;
        String title &amp;quot;COADS 1-degree Equatorial Enhanced&amp;quot;;&lt;br /&gt;
        String history &amp;quot;&amp;quot;;&lt;br /&gt;
        String Conventions &amp;quot;COARDS&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    DODS_EXTRA {&lt;br /&gt;
        String Unlimited_Dimension &amp;quot;time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the map vector attributes are in the &amp;quot;dataset&amp;quot; scope.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the DAS that the NcML Module produces from the correctly formed DDX:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    NC_GLOBAL {&lt;br /&gt;
        String title &amp;quot;COADS 1-degree Equatorial Enhanced&amp;quot;;&lt;br /&gt;
        String history &amp;quot;&amp;quot;;&lt;br /&gt;
        String Conventions &amp;quot;COARDS&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    DODS_EXTRA {&lt;br /&gt;
        String Unlimited_Dimension &amp;quot;time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    cldc {&lt;br /&gt;
        Float32 valid_range 0.000000000, 8.000000000;&lt;br /&gt;
        Float32 actual_range 0.000000000, 8.000000000;&lt;br /&gt;
        String units &amp;quot;okta&amp;quot;;&lt;br /&gt;
        Int16 precision 1;&lt;br /&gt;
        Int16 missing_value 32766;&lt;br /&gt;
        Int16 _FillValue 32766;&lt;br /&gt;
        String long_name &amp;quot;Cloudiness Monthly Mean at Surface&amp;quot;;&lt;br /&gt;
        String dataset &amp;quot;COADS 1-degree Equatorial Enhanced\\012AI&amp;quot;;&lt;br /&gt;
        String var_desc &amp;quot;Cloudiness\\012C&amp;quot;;&lt;br /&gt;
        String level_desc &amp;quot;Surface\\0120&amp;quot;;&lt;br /&gt;
        String statistic &amp;quot;Mean\\012M&amp;quot;;&lt;br /&gt;
        String parent_stat &amp;quot;Individual Obs\\012I&amp;quot;;&lt;br /&gt;
        Float32 add_offset 3276.500000;&lt;br /&gt;
        Float32 scale_factor 0.1000000015;&lt;br /&gt;
        cldc {&lt;br /&gt;
        }&lt;br /&gt;
        time {&lt;br /&gt;
            String units &amp;quot;days since 1-1-1 00:00:0.0&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;Time&amp;quot;;&lt;br /&gt;
            String delta_t &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
            String avg_period &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
            Float64 actual_range 715511.00000000000, 729360.00000000000;&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
            Float32 actual_range 10.00000000, -10.00000000;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
            Float32 actual_range 0.5000000000, 359.5000000;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here the Grid Structure &amp;quot;cldc&amp;quot;  and its contained data array (of the same name &amp;quot;cldc&amp;quot;) and map vectors have their own attribute containers as DAP 2 specifies.&lt;br /&gt;
&lt;br /&gt;
What this means for the author of an NcML file adding metadata to a NetCDF dataset that returns a Grid is that they should generate a &amp;quot;passthrough&amp;quot; file and get the DAS and then specify modifications based on that structure.  &lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example passthrough:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/cldc.mean.nc&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For example, to add an attribute to the map vector &amp;quot;lat&amp;quot; in the above, we&#039;d need the following NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/cldc.mean.nc&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;!-- Traverse into the Grid as a Structure --&amp;gt;&lt;br /&gt;
  &amp;lt;variable name=&amp;quot;cldc&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Traverse into the &amp;quot;lat&amp;quot; map vector (Array) --&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lat&amp;quot;&amp;gt; &lt;br /&gt;
      &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;I am a new attribute in the Grid map vector named lat!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lon&amp;quot;&amp;gt; &lt;br /&gt;
      &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;I am a new attribute in the Grid map vector named lon!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This clearly shows that the structure of the Grid must be used in the NcML:  the attribute being added is technically &amp;quot;cldc.lat.Description&amp;quot; in a fully qualified name.  The parser would return an error if it was attempted as &amp;quot;lat.Description&amp;quot; as the NetCDF DAS for the original file would have led one to believe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== HDF4/HDF5 ==&lt;br /&gt;
&lt;br /&gt;
Similarly to the NetCDF case, the Hyrax HDF4 Module produces DAS responses that do not respect the DAP2 specification.  If an NcML file is used to &amp;quot;wrap&amp;quot; an HDF4 dataset, the&lt;br /&gt;
correct DAP2 DAS response will be generated, however. &lt;br /&gt;
&lt;br /&gt;
This is important for those writing NcML for HDF4 data since the&lt;br /&gt;
lexical scope for attributes relies on the correct DAS form --- to&lt;br /&gt;
handle this, the user should start with a &amp;quot;passthrough&amp;quot; NcML file (see the above NetCDF example) and&lt;br /&gt;
use the DAS from that as the starting point for knowing the structure&lt;br /&gt;
the NcML handler expects to see in the NcML file.  Alternatively, the DDX has the &lt;br /&gt;
proper attribute structure as well (the DAS is generated from it).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Known Bugs =&lt;br /&gt;
&lt;br /&gt;
There are no known bugs currently.&lt;br /&gt;
&lt;br /&gt;
= Planned Future Enhancements =&lt;br /&gt;
&lt;br /&gt;
Planned enhancements for future versions of the module include:&lt;br /&gt;
&lt;br /&gt;
* New NcML Aggregations&lt;br /&gt;
** JoinExisting&lt;br /&gt;
*** Joins a variable across multiple datasets by appending the data for a given dimension from each dataset &lt;br /&gt;
*** Will also allow directory scans for specifying the aggregation&lt;br /&gt;
** Forecast Model Run Collection (FMRC)&lt;br /&gt;
*** Special case of JoinNew for forecast data with two time variables&lt;br /&gt;
*** See: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/FmrcAggregation.html&lt;br /&gt;
&lt;br /&gt;
= Copyright =&lt;br /&gt;
&lt;br /&gt;
This software is copyrighted under the GNU Lesser GPL.  Please see the&lt;br /&gt;
files COPYING and COPYRIGHT that came with this distribution.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=OPeNDAP_Developer%27s_Workshop_2010&amp;diff=5869</id>
		<title>OPeNDAP Developer&#039;s Workshop 2010</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=OPeNDAP_Developer%27s_Workshop_2010&amp;diff=5869"/>
		<updated>2010-10-18T16:35:28Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* The NcML handler will have to do its own caching */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Where &amp;amp;  When ==&lt;br /&gt;
* Location: &#039;&#039;&#039;Troy, NY&#039;&#039;&#039;&lt;br /&gt;
* Dates: &#039;&#039;&#039;6-8 Oct&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Meeting modus operandi == &lt;br /&gt;
* mockups&lt;br /&gt;
* whiteboard designs&lt;br /&gt;
* use cases&lt;br /&gt;
* best to exploit face-to-face for what it affords.&lt;br /&gt;
&lt;br /&gt;
== Agenda ==&lt;br /&gt;
----&lt;br /&gt;
----&lt;br /&gt;
===Wednesday===&lt;br /&gt;
&lt;br /&gt;
;0830 - Coffee&lt;br /&gt;
&lt;br /&gt;
==== Server Side Functions ====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Registration&#039;&#039;&#039; &lt;br /&gt;
** modularized&lt;br /&gt;
** each function -&amp;gt; class &lt;br /&gt;
** version&lt;br /&gt;
*** can you handle this &lt;br /&gt;
*** service&lt;br /&gt;
*** how do we package this&lt;br /&gt;
* &#039;&#039;&#039;Discovery&#039;&#039;&#039;&lt;br /&gt;
** Ask the OLFS/BES what functions for dataset&lt;br /&gt;
*** what functions&lt;br /&gt;
*** capabilities&lt;br /&gt;
* &#039;&#039;&#039;Format&#039;&#039;&#039;&lt;br /&gt;
** function(p1,p2,p3,p4...)&lt;br /&gt;
* &#039;&#039;&#039;Usage&#039;&#039;&#039;&lt;br /&gt;
** Run by handler during loading - slection&lt;br /&gt;
** Run during constraint parsing&lt;br /&gt;
** Run during transmission/serialization (constraint evaluation)&lt;br /&gt;
** What about functions like &amp;quot;version&amp;quot;??&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 void&lt;br /&gt;
 function_version(int, BaseType *[], DDS &amp;amp;, BaseType **btpp)&lt;br /&gt;
 &lt;br /&gt;
 typedef void(*bool_func)(int argc, BaseType *argv[], DDS &amp;amp;dds, bool *result);&lt;br /&gt;
 typedef void(*btp_func)(int argc, BaseType *argv[], DDS &amp;amp;dds, BaseType **btpp);&lt;br /&gt;
 typedef void(*proj_func)(int argc, BaseType *argv[], DDS &amp;amp;dds, ConstraintEvaluator &amp;amp;ce);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Use Cases =====&lt;br /&gt;
* Scientist has a dataset and wants to discover what functions are available to apply to that dataset&lt;br /&gt;
* Data provider has a set of server-side functions that they wish to provide for data users. They want to add these modules to the OPeNDAP via dynamically loaded modules&lt;br /&gt;
* Scientist has a dataset and wants to apply geogrid function to that dataset&lt;br /&gt;
* Scientist wants to discover the the shape and size (metadata) of a particular function against a dataset&lt;br /&gt;
&lt;br /&gt;
===== Plan: Define a class/hierarchy =====&lt;br /&gt;
* Define a set of classes for server-saide functions&lt;br /&gt;
* Have the BES instantiate those from .so files&lt;br /&gt;
* Those instances are then passed into a ConstraintEvaluator instance which is then passed to a handler&lt;br /&gt;
* The BES conf file(s) can include information so that some functions are always loaded and some are loaded only for specific handlers (e.g., FreeForm).&lt;br /&gt;
&lt;br /&gt;
* Take the server side functions out of libdap and add to BES modules&lt;br /&gt;
* Add the server side functions to server side class&lt;br /&gt;
* These classes will be able to handle things like get version, given a ddx(?) can this function be run against it (return true/false)&lt;br /&gt;
* At load time the classes are created within the BES, the functions are registered with libdap. This maintains binary compatability.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Server Administration ====&lt;br /&gt;
===== Admin interface =====&lt;br /&gt;
* admin connects to a listener&lt;br /&gt;
* can restart a listener&lt;br /&gt;
* can restart the BES with ADMIN&lt;br /&gt;
* turn on/off debugging through admin interface&lt;br /&gt;
* keep track of how many connections are allowed/active&lt;br /&gt;
* re-write besdaemon/beslistener (2-3 hrs)&lt;br /&gt;
* allowed size of response from BES (1 hr)&lt;br /&gt;
&lt;br /&gt;
:: http://docs.opendap.org/index.php/Hyrax_Admin_Interface&lt;br /&gt;
&lt;br /&gt;
===== BES design changes =====&lt;br /&gt;
* drop the besdaemon from the architecture&lt;br /&gt;
* listener is started instead of daemon&lt;br /&gt;
* listener keeps track of connections made and socket connected to&lt;br /&gt;
* listener keeps track of connections dropped, removes from list&lt;br /&gt;
* limit the number of open connections&lt;br /&gt;
* besdaemon will be able to have both hard and graceful restart&lt;br /&gt;
* Out of band comm will enable access to logs and conf files in addition to the restarts&lt;br /&gt;
* capability to send back configuration information&lt;br /&gt;
* capability to receive new configuration information and write to disk and reload&lt;br /&gt;
* we don&#039;t sweat the fact that the logs are shared - we can build a fancy interface out at the servlet level to filter by specific client using the PID info in the log.&lt;br /&gt;
* Changes in the conf only are used when a process is started.&lt;br /&gt;
* Soft shutdown, listener sends certain signal to child, when done handling current request, go down&lt;br /&gt;
* Hard shutdown, listener sends certain signal to child, go down now&lt;br /&gt;
* capability to stream back the log file&lt;br /&gt;
&lt;br /&gt;
===== Authentication and Authorization =====&lt;br /&gt;
* Will people be authenticating through ESG to get to Hyrax? Or will Hyrax need to have an authentication piece? Authorization to ESG AuthZ.&lt;br /&gt;
* encrypting the data? Is it through the BES or through the middle tier? If middle tier then no need to encrypt the information through the BES.&lt;br /&gt;
* client application to need to allow login to get data? Scientist gets a URL back to access data through OPeNDAP. To get that data, have to be logged in? Authorization needs to happen.&lt;br /&gt;
* Certificate is on the client disk, when request made within matlab client, grabs certificate and sends along with data URL&lt;br /&gt;
&lt;br /&gt;
===== Throttling the response =====&lt;br /&gt;
* Function added to DDS and base types to be able to pre-compute the response size based on projections and selections&lt;br /&gt;
* Should also work for sequences, at least be able to say that you can have x number of rows returned.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==== Lunch ====&lt;br /&gt;
{|&lt;br /&gt;
|James&lt;br /&gt;
| : &lt;br /&gt;
|Pizza Margarita&lt;br /&gt;
|-&lt;br /&gt;
|Dan&lt;br /&gt;
| : &lt;br /&gt;
|Corned Beef&lt;br /&gt;
|-&lt;br /&gt;
|Patrick&lt;br /&gt;
| : &lt;br /&gt;
|Veggy Pizza &lt;br /&gt;
|-&lt;br /&gt;
|Michael&lt;br /&gt;
| : &lt;br /&gt;
|Chikin Sandwich &lt;br /&gt;
|-&lt;br /&gt;
|Nathan&lt;br /&gt;
| : &lt;br /&gt;
|Turkey Club Sandwich &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==== Easier install for Hyrax ====&lt;br /&gt;
&lt;br /&gt;
# Modify nightly build to use &#039;&#039;shrew&#039;&#039;&lt;br /&gt;
# Build RPMs from the NB shrew&lt;br /&gt;
## Add dependencies to all RPM spec files&lt;br /&gt;
# Modify all Makefiles to support pkg/dmg binaries&lt;br /&gt;
# Integrate into NB on OS/X Server VMs&lt;br /&gt;
# build meta package for OS/X using above &lt;br /&gt;
# Run RPM/Linux NB on VMs too&lt;br /&gt;
# Test both PRMs and pkg/dmgs on &#039;&#039;completely&#039;&#039; clean VMs&lt;br /&gt;
&lt;br /&gt;
==== SQL Handler ====&lt;br /&gt;
&lt;br /&gt;
# Add to README and INSTALL; fill these in and make them standard WRT the other README/INSTALL files.&lt;br /&gt;
# Add to the README so that there is a simple &#039;How To&#039; for the server&#039;s configutation and then write stuff up for the docs wiki.&lt;br /&gt;
# Look at SQL Handler requirements in docs wiki and match up to current developed functionality&lt;br /&gt;
# Getting attributes&lt;br /&gt;
&lt;br /&gt;
==== JGOFS ====&lt;br /&gt;
* Still a lot of organizations using jgofs and wanting opendap access&lt;br /&gt;
* Current library is very difficult to work with and still fork/exec the methods&lt;br /&gt;
* Could take the library and convert to use the autotools&lt;br /&gt;
** Also change from fork and exec to dynamically loaded module&lt;br /&gt;
* Or be a pass-thru/gateway/proxy module, like WCS, and just pass the request back to the proper JGOFS server that is already running.&lt;br /&gt;
** Figure out how to return catalog information from the jgofs servers&lt;br /&gt;
** How do we get attributes/metadata...&lt;br /&gt;
&lt;br /&gt;
==== Active file system ====&lt;br /&gt;
&#039;&#039;A filesystem that creates a &amp;quot;signal&amp;quot; whenever something changes.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;In many cases this boils down to caching binary objects in/around the BES&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* One way to do this is to use ODB (http://www.codesynthesis.com/products/odb/)&lt;br /&gt;
* Another way is to use the boost library (http://www.boost.org/)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==== 1800 - Dinner ====&lt;br /&gt;
&lt;br /&gt;
Mmmmmmm Irish/Mexican&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
===Thursday===&lt;br /&gt;
&lt;br /&gt;
==== 0830 - Coffee ====&lt;br /&gt;
: Mmmmmm that was tasty...&lt;br /&gt;
&lt;br /&gt;
==== NcML Ingestion ====&lt;br /&gt;
&lt;br /&gt;
* Sending in NcML from a client&lt;br /&gt;
* Use a proxy server to shield clients from the mechanics&lt;br /&gt;
** The aggregations need to persist and at least some of this must be at the origin server&lt;br /&gt;
** The NcML is held at a proxy server and sent to the origin server where it&#039;s validated, etc. and the origin server (must be a Hyrax) returns an id that can be used to reference the aggregation&lt;br /&gt;
** The proxy retains that id and takes requests against it.&lt;br /&gt;
* Can we simplfy this and remove the proxy given that the aggregation has to persist?&lt;br /&gt;
* How long does the aggregation persist? That is, what criteria are used to &#039;flush&#039; an &#039;uploaded&#039; aggregation.&lt;br /&gt;
&lt;br /&gt;
===== Why we want this? =====&lt;br /&gt;
* EML --&amp;gt; Building aggreagations at a client&lt;br /&gt;
* TDS migration&lt;br /&gt;
&lt;br /&gt;
===== Design mechanics for this feature =====&lt;br /&gt;
* Errors: How to get information about bad ncml back to a client&lt;br /&gt;
* Assme that the server (Hyrax) is modified to use POST for this feature&lt;br /&gt;
* Handle errors by returning text as built by the NCML handler&lt;br /&gt;
* OLFS currently has no POST termini and we could make an explict terminus for this &#039;&#039;but&#039;&#039; we could make a special servlet for this feature &lt;br /&gt;
&lt;br /&gt;
===== Alternatives =====&lt;br /&gt;
* Two things: We add support for HTTP acccess to the ncml handler - this is how we handle aggreagtions of remote entities&lt;br /&gt;
* For the NcML migration we modify the BES/NcML commands to support uploading NCML from the OLFS to a specific BES/NCML-handler instance&lt;br /&gt;
* Advantages: This solves the first problem w/o any changes to exisitng origin servers at the cost of poor accesses to real-world aggreations. Actually useful aggregations would be sent to the &#039;origin server&#039; by hand between people.&lt;br /&gt;
* There seem to be no real increased costs for NCML migration.&lt;br /&gt;
&lt;br /&gt;
===== To support exteranal access =====&lt;br /&gt;
* NcML handler becomes a HTTP client&lt;br /&gt;
* Might require remote URLs to be listed explicitly? Performance implemented&lt;br /&gt;
&lt;br /&gt;
==== BES Internal Caching ====&lt;br /&gt;
&lt;br /&gt;
===== Caching compressed data =====&lt;br /&gt;
&lt;br /&gt;
* The BES caching issue is only regarding the compressed files, their decompression and maintaining a restricted &#039;cache&#039; size.&lt;br /&gt;
* This caching scheme needs to include a two stage cache where a single space with no size limit is used for at most one item. This is used for the actual decompression phase. Only one writer may access this at any time.&lt;br /&gt;
* A second space is used to store N-bytes of decompressed files. This space must lock all accesses during a write (and must block on both reads and writes). Call this the &#039;main cache.&#039;&lt;br /&gt;
* The main cache must store spin locks for read access to all of the cache items.&lt;br /&gt;
* Modify access to items in the cache so that they are accessed using an object such that it&#039;s dtor updates the spin lock (so that the spin lock is manged even when exceptions are thrown).&lt;br /&gt;
* The object (above) also provides access to a path to the cached item; this path is accessed and passed to the handlers.&lt;br /&gt;
* See libdap&#039;s HTTPCache and Response classes for an example implmentation &lt;br /&gt;
&lt;br /&gt;
===== Caching binary objects =====&lt;br /&gt;
&lt;br /&gt;
* While it&#039;s desireable it&#039;s also really hard to retro-fit&lt;br /&gt;
* To serialize the DDS we would have to serialize BaseType and all of the concrete classes that are derived from it (NCByte, ...)&lt;br /&gt;
* It&#039;s not clear that caching these kinds o objects will provide a huge benefit for users/clients.&lt;br /&gt;
&lt;br /&gt;
===== The NcML handler will have to do its own caching and add information to HTTP caching GETs=====&lt;br /&gt;
* It will need to support the Last Modified Time of aggregations if we&#039;re going to get caching systems like Squid working correctly. Actually, for ANY ncml file, not just aggregations, we need to give the BES a proxy for the modification time.  The wrapped dataset could change, but not the NcML, which implies the cache is invalidated but not reflected by the ncml file time.&lt;br /&gt;
&lt;br /&gt;
* This will need to be a feature added to the BES for the showInfo command.  Basically, it will need to allow the modules to register a delegate function to fill in the info response for a given file.  This include the last modified time as well as the size of the file, since the NcML does not reflect the size of the actual wrapped dataset.  The default response (for no delegate registered) will be the current BES behaviour of filling in the file mod time and size.&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==== Lunch ====&lt;br /&gt;
{|&lt;br /&gt;
|James&lt;br /&gt;
| : &lt;br /&gt;
|Veggie Burger&lt;br /&gt;
|-&lt;br /&gt;
|Dan&lt;br /&gt;
| : &lt;br /&gt;
|Something tasty&lt;br /&gt;
|-&lt;br /&gt;
|Patrick&lt;br /&gt;
| : &lt;br /&gt;
|Veggy Burger &lt;br /&gt;
|-&lt;br /&gt;
|Michael&lt;br /&gt;
| : &lt;br /&gt;
|Corned Beef on Rye &lt;br /&gt;
|-&lt;br /&gt;
|Nathan&lt;br /&gt;
| : &lt;br /&gt;
|Chikin Salad &lt;br /&gt;
|}&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== BES module architecture ===&lt;br /&gt;
&lt;br /&gt;
* Show Version: This is a built-in BES command&lt;br /&gt;
* &amp;lt;showVersion .../&amp;gt;&lt;br /&gt;
* show version  --&amp;gt; BESVersionResponseHandler (if this mapping exists, then we can build a response for this command)&lt;br /&gt;
* a ResponseHandler knows hw to make the response object and how to get it filled in (and in this case it does fill it in a little bit)&lt;br /&gt;
* So you do get a repnse from this command from this command with no modules loaded.&lt;br /&gt;
* Sequence:&lt;br /&gt;
** BESVersionResponseHandler&lt;br /&gt;
*** Makes response object&lt;br /&gt;
*** knows how to get it filled in&lt;br /&gt;
**** Go to each response handler and see if they know how to fill in version&lt;br /&gt;
* Now... Load a module like the Dap Module or NCRequestHandler knows how to fill in a version response.&lt;br /&gt;
* It (NCResponseHandler) registers this capability&lt;br /&gt;
&lt;br /&gt;
* Response handlers are assoicated with commands (like &#039;show version&#039; or &#039;get&#039;)&lt;br /&gt;
* Request handlers are associated with modules (like things that read files or process DAP object)&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;get type=&amp;quot;dds&amp;quot; defintion=&amp;quot;d&amp;quot; /&amp;gt;  (BES command)&lt;br /&gt;
* The XML command that reads the above turns this into: getDDS&lt;br /&gt;
* Ths calls the DapDDSResponseHandler.&lt;br /&gt;
** Thsi knows how to make the response object (whcih is a DDS)&lt;br /&gt;
** It goes to eac container in the definition (d in this ex) and goes to te matching Request Handler and asks for the dds&lt;br /&gt;
** The Response handler knows how to send the response&lt;br /&gt;
&lt;br /&gt;
Now, for the caching....&lt;br /&gt;
&lt;br /&gt;
* &amp;lt; UpdateCache/&amp;gt;&lt;br /&gt;
* NcML_Module&lt;br /&gt;
** Init&lt;br /&gt;
*** updateCache --&amp;gt; XML___&lt;br /&gt;
*** updateCache --&amp;gt; UCResponseHandler&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==== 1800 - Dinner ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
----&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Friday ===&lt;br /&gt;
&lt;br /&gt;
==== 0830 - Coffee ====&lt;br /&gt;
==== Module check ====&lt;br /&gt;
:: Making sure a loaded module matches the version of BES and any required modules&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== SSL authentication/authorization issues ====&lt;br /&gt;
:: Currently problem with SSL authentication and keeping SSL channel open for secure communication&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Multiple catalogs ====&lt;br /&gt;
:: BES and OLFS integration &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== 1230 - Lunch ====&lt;br /&gt;
&lt;br /&gt;
==== Strategy Breakout (cont) ====&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
==== 1800 - Dinner and Departure ====&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=BES_-_Modules_-_NcML_Module&amp;diff=5793</id>
		<title>BES - Modules - NcML Module</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=BES_-_Modules_-_NcML_Module&amp;diff=5793"/>
		<updated>2010-09-17T18:35:45Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
[[Category:NCML]]&lt;br /&gt;
[[Category:BES Modules|NCML Module]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Welcome to the OPeNDAP NcML Data Handler Module v1.1.0 for [http://www.opendap.org/download/hyrax.html Hyrax 1.6.2]!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[Updated for NcML Module v1.1.0 for Hyrax 1.6.2 Release --   15 September 2010]&lt;br /&gt;
&lt;br /&gt;
This module may be added to a [http://www.opendap.org/download/hyrax.html Hyrax 1.6.2] server to extend its data&lt;br /&gt;
serving capability to NcML 2.2 files (see&lt;br /&gt;
http://www.unidata.ucar.edu/software/netcdf/ncml/).  NcML provides support for modifying other datasets in various ways, such as adding metadata and data and aggregating multiple datasets in several ways.&lt;br /&gt;
&lt;br /&gt;
We refer the reader to the Unidata NcML tutorial: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Tutorial.html which will give the basics of using NcML.  We then give a reference manual for the various elements and their attributes.  Additionally we have provided a more extensive tutorial on NcML aggregation.  Please see [[#Aggregation Tutorials]].&lt;br /&gt;
&lt;br /&gt;
Since the DAP Grid is a common case, we will also give a simple example for adding metadata to the various parts of a Grid dataset using NcML.  Please see [[Grid_Metadata_Tutorial]].&lt;br /&gt;
&lt;br /&gt;
== Current Release ==&lt;br /&gt;
&lt;br /&gt;
The most recent release is 1.1.0, which is bundled with (and requires) Hyrax server 1.6.2.  To download, visit the [http://www.opendap.org/download/ncml_handler.html NcML Module Page].&lt;br /&gt;
&lt;br /&gt;
New features in this release:&lt;br /&gt;
&lt;br /&gt;
* joinExisting aggregation initial implementation ([[NCML_Module_Aggregation_JoinExisting]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Features==         &lt;br /&gt;
   &lt;br /&gt;
This version currently implements a subset of NcML 2.2&lt;br /&gt;
functionality, along with some OPeNDAP extensions:&lt;br /&gt;
&lt;br /&gt;
* Metadata Manipulation&lt;br /&gt;
** Addition, Removal, and Modification of attributes to other datasets (NetCDF, HDF4, HD5, etc.) served by the same Hyrax 1.6 server&lt;br /&gt;
** Extends NcML 2.2 to allow for common nested &amp;quot;attribute containers&amp;quot; &lt;br /&gt;
** Attributes can be DAP2 types as well as the NcML types &lt;br /&gt;
** Attributes can be of the special &amp;quot;OtherXML&amp;quot; type for injecting arbitrary XML into a DDX response&lt;br /&gt;
* Data Manipulation&lt;br /&gt;
** Addition of new data variables (scalars or arrays of basic types as well as structures) &lt;br /&gt;
** Variables may be removed from the wrapped dataset&lt;br /&gt;
** Allows the creation of &amp;quot;pure virtual&amp;quot; datasets which do not wrap another dataset&lt;br /&gt;
* Aggregations: JoinNew, JoinExisting Union [[#Aggregation Tutorials]]&lt;br /&gt;
** JoinNew Aggregation ([[NCML_Module_Aggregation_JoinNew]])&lt;br /&gt;
*** Allows multiple datasets to be &amp;quot;joined&amp;quot; by creating a new outer dimension for the aggregated variable&lt;br /&gt;
*** Aggregation member datasets can be listed explicitly with explicit coordinates for the new dimension for each member&lt;br /&gt;
*** Scan: Aggregations can be specified &amp;quot;automatically&amp;quot; by scanning a directory for files matching certain criteria, such as a suffix or regular expression.&lt;br /&gt;
*** Metadata may be added to the new coordinate variable for the new dimension&lt;br /&gt;
** JoinExisting Aggregation ([[NCML_Module_Aggregation_JoinExisting]])&lt;br /&gt;
*** Currently requires the author to specify the &#039;&#039;ncoords&#039;&#039; attribute.&lt;br /&gt;
*** Scan may also be used with &#039;&#039;ncoords&#039;&#039; attribute for uniform sized granules&lt;br /&gt;
*** Only allows join dimension to be aggregated from granules and not overridden in NcML&lt;br /&gt;
** Union Aggregation ([[NCML_Module_Aggregation_Union]])&lt;br /&gt;
*** Merges all member datasets into one by taking the first named instance of variables and metadata from the members&lt;br /&gt;
*** Useful for combining two or more datasets with different variables into a single set&lt;br /&gt;
&lt;br /&gt;
== Installation from Source ==&lt;br /&gt;
For information on how to build and install the NcML Data Module, please see the INSTALL file that came with the source distribution.&lt;br /&gt;
&lt;br /&gt;
= Installation Overview =&lt;br /&gt;
&lt;br /&gt;
The NcML Module requires a working Hyrax 1.6 installation.  It is a module&lt;br /&gt;
that is dynamically loaded into the Hyrax BES (Back End Server) to&lt;br /&gt;
allow it to handle NcML files.  &lt;br /&gt;
&lt;br /&gt;
Please see the file INSTALL for full build and install instructions as&lt;br /&gt;
well as requirements.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; After installation, you MUST restart Hyrax by restarting the BES and&lt;br /&gt;
OLFS so the NcML Module is loaded!&lt;br /&gt;
&lt;br /&gt;
== Requirement: International Components for Unicode (ICU) Library == &lt;br /&gt;
&lt;br /&gt;
The most important external requirement is an installation of the International Components for Unicode (ICU) version 3.6 or higher (tested up to 4.2.1).   The source distributions (as well as some binaries) may be found at the site: http://site.icu-project.org/download&lt;br /&gt;
&lt;br /&gt;
If you are using Linux RPM&#039;s to run Hyrax, you can get an RPM for ICU as well.  Search for the RPM named &amp;quot;libicu&amp;quot; using a package manager or yum, e.g.   If you are compiling the module from source, you will also need the RPM &amp;quot;libicu-devel&amp;quot; to get the headers installed.  &lt;br /&gt;
&lt;br /&gt;
If you install in the default locations, the ncml_module should find the libraries and headers.  Otherwise, please consult the INSTALL file for more information about installing ICU to a non-standard location.&lt;br /&gt;
&lt;br /&gt;
== Testing Installation ==&lt;br /&gt;
&lt;br /&gt;
Test data is provided to see if the installation was successful.  The file sample_virtual_dataset.ncml is a dataset purely created in NcML and doesn&#039;t contain an underlying dataset.  &lt;br /&gt;
You may also view fnoc1_improved.ncml to test adding attributes to an existing netCDF dataset (fnoc1.nc), but this requires the netCDF data handler to be&lt;br /&gt;
installed first!  Several other examples installed also use the HDF4 and HDF5 handlers.&lt;br /&gt;
&lt;br /&gt;
= Functionality =&lt;br /&gt;
&lt;br /&gt;
This version of the NcML Module implements a subset of NcML 2.2&lt;br /&gt;
functionality.  The reader is directed to http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/ for more information on NcML.&lt;br /&gt;
&lt;br /&gt;
Our module can currently:&lt;br /&gt;
&lt;br /&gt;
*Refer only to files being served locally (not remotely)&lt;br /&gt;
*Add, modify, and remove attribute metadata to a dataset&lt;br /&gt;
*Create a purely virtual dataset using just NcML and no underlying dataset&lt;br /&gt;
*Create new scalar variables of any simple NcML type or simple DAP type&lt;br /&gt;
*Create new Structure variables (which can contain new child variables)&lt;br /&gt;
*Create new N-dimensional arrays of simple types (NcML or DAP)&lt;br /&gt;
*Remove existing variables from a wrapped dataset&lt;br /&gt;
*Rename existing variables in a wrapped dataset&lt;br /&gt;
*Name dimensions as a mnemonic for specifying Array shapes&lt;br /&gt;
*Perform union aggregations on multiple datasets, virtual or wrapped or both&lt;br /&gt;
*Perform joinNew aggregations to merge a variable across multiple datasets by creating a new outer dimension&lt;br /&gt;
*Specify aggregation member datasets by scanning directories for files matching certain criteria&lt;br /&gt;
&lt;br /&gt;
We describe each supported NcML element in detail below.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;netcdf&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;netcdf&amp;gt; element is used to define a dataset, either a wrapped dataset that is to be modified, a pure virtual dataset, or a member dataset of an aggregation.  The &amp;lt;netcdf&amp;gt; element is assumed to be the topmost node, or as a child of an aggregation element.&lt;br /&gt;
&lt;br /&gt;
=== Local vs. Remote Datasets ===&lt;br /&gt;
&lt;br /&gt;
We assume that the location attribute (&#039;&#039;netcdf@location&#039;&#039;) refers to the full path (with respect to the BES data root directory) of a &#039;&#039;&#039;&#039;&#039;local&#039;&#039;&#039;&#039;&#039; dataset (served by the same Hyrax server).  The current version of the module cannot be used to modify remote datasets.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;netcdf@location&#039;&#039; is the empty string (or unspecified, as empty is the default), the dataset is a pure virtual dataset, fully specified within the NcML file itself.  Attributes and variables may be fully described and accessed with constraints just as normal datasets in this manner.  The installed sample datafile &amp;quot;sample_virtual_dataset.ncml&amp;quot; is an example test case for this functionality.&lt;br /&gt;
&lt;br /&gt;
=== Unsupported Attributes ===&lt;br /&gt;
&lt;br /&gt;
The current version does not support the following attributes of &amp;lt;netcdf&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
*enhance&lt;br /&gt;
*addRecords&lt;br /&gt;
*fmrcDefinition (will be supported when FMRC aggregation is added)&lt;br /&gt;
*ncoords (will be supported when joinExisting is added)&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;readMetadata&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;readMetadata/&amp;gt; element is the default, so is effectively not needed.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;explicit&amp;gt; element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;explicit/&amp;gt; element simply clears all attribute tables in the referred to netcdf@location before applying the rest of the &lt;br /&gt;
NcML transformations to the metadata.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;dimension&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;dimension&amp;gt; element has limited functionality in this release since the DAP2 doesn&#039;t support dimensions as more than mnemonics at this time.  The limitations are:&lt;br /&gt;
&lt;br /&gt;
* We only parse the &#039;&#039;dimension@name&#039;&#039; and &#039;&#039;dimension@length&#039;&#039; attributes.  &lt;br /&gt;
* Dimensions can only be specified as a direct child of a &amp;lt;netcdf&amp;gt; element prior to any reference to them&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt; &lt;br /&gt;
  &amp;lt;dimension name=&amp;quot;station&amp;quot; length=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;dimension name=&amp;quot;samples&amp;quot; length=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;!-- Some variable elements refer to the dimensions here --&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The dimension element sets up a mapping from the &#039;&#039;name&#039;&#039; to the unsigned integer &#039;&#039;length&#039;&#039; and can be used in a &#039;&#039;variable@shape&#039;&#039; to specify a length for an array dimension (see the section on &amp;lt;variable&amp;gt; below).  The dimension map is cleared when &amp;lt;/netcdf&amp;gt; is encountered (though this doesn&#039;t matter currently since we allow only one right now, but it will matter for aggregation, potentially).  We also do not support &amp;lt;group&amp;gt;, which is the only other legal place in NcML 2.2 for a dimension element.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* If the name and length are not both specified.&lt;br /&gt;
* If the dimension name already exists in the current scope&lt;br /&gt;
* If the length is not an unsigned integer&lt;br /&gt;
* If any of the other attributes specified in NcML 2.2 are used.  We do not handle them, so we consider them errors now.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;variable&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;variable&amp;gt; element is used to:&lt;br /&gt;
&lt;br /&gt;
* Provide lexical scope for a contained &amp;lt;attribute&amp;gt; or &amp;lt;variable&amp;gt; element&lt;br /&gt;
* Rename existing variables &lt;br /&gt;
* Add new scalar variables of simple types&lt;br /&gt;
* Add new Structure variables&lt;br /&gt;
* Add new N-dimensional Array&#039;s of simple types&lt;br /&gt;
* Specify the coordinate variable for the new dimension in a joinNew aggregation &lt;br /&gt;
&lt;br /&gt;
We describe each in turn in more detail.&lt;br /&gt;
&lt;br /&gt;
=== Specifying Lexical Scope with &amp;lt;variable type=&amp;quot;&amp;quot;&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Consider the following example:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;variable name=&amp;quot;u&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Metadata&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;This is metadata!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code assumes that a variable named &amp;quot;u&amp;quot; exists (of any type since we do not specify) and provides the lexical scope for the&lt;br /&gt;
attribute &amp;quot;Metadata&amp;quot; which will be added or modified within the attribute table for the variable &amp;quot;u&amp;quot; (it&#039;s qualified name would be &amp;quot;u.Metadata&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
==== Nested DAP Structure and Grid Scopes ====&lt;br /&gt;
&lt;br /&gt;
Scoping variable elements may be nested if the containing variable is a Structure (this includes the special case of Grid)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;DATA_GRANULE&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;PlanetaryGrid&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;variable name=&amp;quot;percipitate&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;inches&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This adds a &amp;quot;unit&amp;quot; attribute to the variable &amp;quot;percipitate&amp;quot; within the nested Structure&#039;s &lt;br /&gt;
(&amp;quot;DATA_GRANULE.PlanetaryGrid.percipitate&amp;quot; as fully qualified name).  &lt;br /&gt;
Note that we &#039;&#039;&#039;must&#039;&#039;&#039; refer to the type explicitly as a &amp;quot;Structure&amp;quot; so the parser knows&lt;br /&gt;
to traverse the tree.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; the variable might be of type Grid, but the type &amp;quot;Structure&amp;quot; must be used in the NcML to traverse it.&lt;br /&gt;
&lt;br /&gt;
==== Adding Multiple Attributes to the Same Variable ====&lt;br /&gt;
&lt;br /&gt;
Once the variable&#039;s scope is set by the opening &amp;lt;variable&amp;gt; element, more than one attribute can be specified within it.  This will make the NcML more readable and also will make the parsing more efficient since the variable will only need to be looked up once.&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_1&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Hello&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_2&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;World!&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
should be preferred over:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_1&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Hello&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_2&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;World!&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
although they produce the same result.  Any number of attributes can be specified before the variable is closed.&lt;br /&gt;
&lt;br /&gt;
=== Renaming Existing Variables ===&lt;br /&gt;
&lt;br /&gt;
The attribute &#039;&#039;variable@orgName&#039;&#039; is used to rename an existing variable. &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;NewName&amp;quot; orgName=&amp;quot;OldName&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing variable at the current scope named &amp;quot;OldName&amp;quot; to &amp;quot;NewName&amp;quot;.  After this point in the NcML file (such as in constraints specified for the DAP request), the variable is known by &amp;quot;NewName&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note that the type is not required here --- the variable is assumed to exist and its existing type is used.  It is not possible to change the type of an existing variable at this time!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:  &lt;br /&gt;
* If a variable with &#039;&#039;variable@orgName&#039;&#039; doesn&#039;t exist in the current scope&lt;br /&gt;
* If the new name &#039;&#039;variable@name&#039;&#039; is already taken in the current scope&lt;br /&gt;
* If a new variable is created but does not have exactly one values element&lt;br /&gt;
&lt;br /&gt;
=== Adding a New Scalar Variable ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;variable&amp;gt; element can be used to create a new scalar variable of a simple type (i.e. an atomic NcML type such as &amp;quot;int&amp;quot; or &amp;quot;float&amp;quot;, or any DAP atomic type, such as &amp;quot;UInt32&amp;quot; or &amp;quot;URL&amp;quot;) by specifying an empty &#039;&#039;variable@shape&#039;&#039; (which is the default), a simple type for &#039;&#039;variable@type&#039;&#039;, and a contained &amp;lt;values&amp;gt; element with the one value of correct type. &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;TheAnswerToLifeTheUniverseAndEverything&amp;quot; type=&amp;quot;double&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;SolvedBy&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;Deep Thought&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;values&amp;gt;42.000&amp;lt;/values&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create a new variable named &amp;quot;TheAnswerToLifeTheUniverseAndEverything&amp;quot; at the current scope.  It has no shape so will be a scalar of type &amp;quot;double&amp;quot; and will have the value 42.0.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* It is a parse error to not specify a &amp;lt;values&amp;gt; element with exactly one proper value of the variable type.&lt;br /&gt;
* It is a parse error to specify a malformed or out of bounds value for the data type&lt;br /&gt;
&lt;br /&gt;
=== Adding a New Structure Variable ===&lt;br /&gt;
&lt;br /&gt;
A new Structure variable can be specified at the global scope or within another Structure.  It is illegal for an array to have type structure, so the shape must be empty.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;MyNewStructure&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;MetaData&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;This is metadata!&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;ContainedScalar1&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&amp;lt;values&amp;gt;I live in a new structure!&amp;lt;/values&amp;gt;&amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;ContainedInt1&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;&amp;lt;values&amp;gt;42&amp;lt;/values&amp;gt;&amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
specifies a new structure called &amp;quot;MyNewStructure&amp;quot; which contains two scalar variable fields &amp;quot;ContainedScalar1&amp;quot; and &amp;quot;ContainedInt1&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
Nested structures are allowed as well.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Error&#039;&#039;&#039;: &lt;br /&gt;
* If another variable or attribute exists at the current scope with the new name.  &lt;br /&gt;
* If a &amp;lt;values&amp;gt; element is specified as a direct child of a new Structure --- structures cannot contain values, only attributes and other variables.&lt;br /&gt;
&lt;br /&gt;
=== Adding a New N-dimensional Array ===&lt;br /&gt;
&lt;br /&gt;
An N-dimensional array of a simple type may be created virtually as well by specifying a non-empty &#039;&#039;variable@shape&#039;&#039;.  The shape contains the array dimensions in left-to-right order of slowest varying dimension first.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;FloatArray&amp;quot; type=&amp;quot;float&amp;quot; shape=&amp;quot;2 5&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;!-- values specified in row major order (leftmost dimension in shape varies slowest) &lt;br /&gt;
	Any whitespace is a valid separator by default, so we can use newlines to pretty print 2D matrices.&lt;br /&gt;
	--&amp;gt;&lt;br /&gt;
      &amp;lt;values&amp;gt;&lt;br /&gt;
	0.1 0.2 0.3 0.4 0.5&lt;br /&gt;
	1.1 1.1 1.3 1.4 1.5&lt;br /&gt;
      &amp;lt;/values&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will specify a 2x5 dimension array of float values called &amp;quot;FloatArray&amp;quot;.  The &amp;lt;values&amp;gt; element must contain 2x5=10 values in row major order (slowest varying dimension first).  Since whitespace is the default separator, we use a newline to show the dimension boundary for the values, which is easy to see for a 2D matrix such as this.&lt;br /&gt;
&lt;br /&gt;
A dimension name may also be used to refer mnemonically to a length.  The DAP response will use this mnemonic in its output, but it is not currently used for shared dimensions, only as a mnemonic.   See the section on the &amp;lt;dimension&amp;gt; element for more information.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt;&lt;br /&gt;
 &amp;lt;dimension name=&amp;quot;station&amp;quot; length=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;dimension name=&amp;quot;sample&amp;quot; length=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;FloatArray&amp;quot; type=&amp;quot;float&amp;quot; shape=&amp;quot;station sample&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;values&amp;gt;&lt;br /&gt;
	0.1 0.2 0.3 0.4 0.5&lt;br /&gt;
	1.1 1.1 1.3 1.4 1.5&lt;br /&gt;
      &amp;lt;/values&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will produce the same 2x5 array, but will incorporate the dimension mnemonics into the response.  For example, here&#039;s the DDS response:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
     Float32 FloatArray[station = 2][samples = 5];&lt;br /&gt;
} sample_virtual_dataset.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;values&amp;gt; element respects the &#039;&#039;values@separator&#039;&#039; attribute if whitespace isn&#039;t correct.  This is very useful for arrays of strings with whitespace, for example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;StringArray&amp;quot; type=&amp;quot;string&amp;quot; shape=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;values separator=&amp;quot;*&amp;quot;&amp;gt;String 1*String 2*String 3&amp;lt;/values&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
creates a length 3 array of string StringArray = {&amp;quot;String 1&amp;quot;, &amp;quot;String 2&amp;quot;, &amp;quot;String 3&amp;quot;}.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:  &lt;br /&gt;
* It is an error to specify the incorrect number of values&lt;br /&gt;
* It is an error if any value is malformed or out of range for the data type.&lt;br /&gt;
* It is an error to specify a named dimension which does not exist in the current &amp;lt;netcdf&amp;gt; scope.&lt;br /&gt;
* It is an error to specify an Array whose flattened size (product of dimensions) is &amp;gt; 2^31-1.&lt;br /&gt;
&lt;br /&gt;
=== Specifying the new coordinate variable for a joinNew aggregation ===&lt;br /&gt;
&lt;br /&gt;
In the special case of a joinNew aggregation, the new coordinate variable may be specified with the &amp;lt;variable&amp;gt; element.  The new coordinate variable is &#039;&#039;defined&#039;&#039; to have the same name as the new dimension.  This allows for several things:&lt;br /&gt;
&lt;br /&gt;
*Explicit specification of the variable type and coordinates for the new dimension&lt;br /&gt;
*Specification of the metadata for the new coordinate variable &lt;br /&gt;
&lt;br /&gt;
In the first case, the author can specify explicitly the type of the new coordinate variable and the actual values for each dataset.  In this case, the variable &#039;&#039;must&#039;&#039; be specified &#039;&#039;after&#039;&#039; the aggregation element in the file so the new dimension&#039;s size (number of member datasets) may be known and error checking performed.  Metadata can also be added to the variable here.&lt;br /&gt;
&lt;br /&gt;
In the second case, the author may just specify the variable name, which allows one to specify the metadata for a coordinate variable that is automatically generated by the aggregation itself.  This is the only allowable case for a variable element to &#039;&#039;not&#039;&#039; contain a values element!  Coordinate variables are generated automatically in two cases:&lt;br /&gt;
&lt;br /&gt;
*The author has specified an explicit list of member datasets, with or without explicit coordVal attributes.  &lt;br /&gt;
*The author has used a &amp;lt;scan&amp;gt; element to specify the member datasets via a directory scan&lt;br /&gt;
&lt;br /&gt;
In this case, the &amp;lt;variable&amp;gt; element may come before or after the &amp;lt;aggregation&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*If an explicit variable is declared for the new coordinate variable:&lt;br /&gt;
** And it contains explicit values, the number of values must be equal to the number of member datasets in the aggregation.&lt;br /&gt;
** It must be specifed &#039;&#039;after&#039;&#039; the &amp;lt;aggregation&amp;gt; element&lt;br /&gt;
&lt;br /&gt;
* If a numeric coordVal is used to specify the first member dataset&#039;s coordinate, then &#039;&#039;all&#039;&#039; datasets must contain a numerical coordinate.&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variable (variableAgg) is not found in &#039;&#039;all&#039;&#039; member datasets.&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variable is not of the same type in &#039;&#039;all&#039;&#039; member datasets.  Coercion is &#039;&#039;not&#039;&#039; performed!&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variables in all member datasets do not have the same shape&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if an explicit coordinate variable is specified with a shape that is &#039;&#039;not&#039;&#039; the same as the new dimension name (and the variable name itself).&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;values&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;values&amp;gt; element can only be used in the context of a &#039;&#039;&#039;new&#039;&#039;&#039; variable of scalar or array type.  We cannot change the values for existing variables in this version of the handler. &lt;br /&gt;
The characters content of a &amp;lt;values&amp;gt; element is considered to be a separated list of value tokens valid for the type of the variable of the parent element.  The number of specified tokens in the content &#039;&#039;must&#039;&#039; equal the product of the dimensions of the enclosing &#039;&#039;variable@shape&#039;&#039;, or be one value for a scalar.  It is an error to &#039;&#039;not&#039;&#039; specify a &amp;lt;values&amp;gt; element for a declared new variable as well.  &lt;br /&gt;
&lt;br /&gt;
=== Changing the Separator Tokens === &lt;br /&gt;
&lt;br /&gt;
The author may specify values@separator to change the default value token separator from the default whitespace.  This is very useful for specifying arrays of strings with whitespace in them, or if data in CSV form is being pasted in.  &lt;br /&gt;
&lt;br /&gt;
=== Autogeneration of Uniform Arrays ===&lt;br /&gt;
&lt;br /&gt;
We also can parse &#039;&#039;values@start&#039;&#039; and &#039;&#039;values@increment&#039;&#039; INSTEAD OF tokens in the content.  This will &amp;quot;autogenerate&amp;quot; a uniform array of values of the given product of dimensions length for the containing variable.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Evens&amp;quot; type=&amp;quot;int&amp;quot; shape=&amp;quot;100&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;values start=&amp;quot;0&amp;quot; increment=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will specify an array of the first 100 even numbers (including 0).  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* If the incorrect number of tokens are specified for the containing variable&#039;s shape&lt;br /&gt;
* If any value token cannot be parsed as a valid value for the containing variable&#039;s type&lt;br /&gt;
* If content is specified in addition to start and increment&lt;br /&gt;
* If only one of start or increment is specified&lt;br /&gt;
* If the values element is placed anywhere except within a NEW variable.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;attribute&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
As an overview, whenever the parser encounters an &amp;lt;attribute&amp;gt; with a non-existing name (at the current scope),&lt;br /&gt;
it creates a new one, whether a container or atomic attribute (see below).  If the attribute exists,&lt;br /&gt;
its value and/or type is modified to those specified in the &amp;lt;attribute&amp;gt; element.  If an attribute&lt;br /&gt;
structure (container) exists, it is used to define a nested lexical scope for child attributes.  &lt;br /&gt;
&lt;br /&gt;
Attributes may be scalar (one value) or one dimensional arrays.  Arrays are specified by using whitespace (default) to separate the different values.  The attribute@separator may also be set in order to specify a different separator, such as CSV format or to specify a non-whitespace separator so strings with whitespace are not tokenized.  We will give examples of creating array attributes below.&lt;br /&gt;
&lt;br /&gt;
=== Adding New Attributes or Modifying an Existing Attribute ===&lt;br /&gt;
&lt;br /&gt;
If a specified attribute with the attribute@name does not exist at the current lexical scope, &lt;br /&gt;
a new one is created with the given type and value.  For example, assume &amp;quot;new_metadata&amp;quot; doesn&#039;t&lt;br /&gt;
exist at the current parse scope.  Then:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;new_metadata&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;This is a new entry!&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create the attribute at that scope.  Note that value can be specified in the content of the &lt;br /&gt;
element as well.  This is identical to the above:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;new_metadata&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;This is a new entry!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the attribute@name already exists at the scope, it is modified to contain the specified type and value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Arrays ====&lt;br /&gt;
&lt;br /&gt;
As in NcML, for numerical types an array can be specified by separating the tokens by whitespace (default) or be&lt;br /&gt;
specifying the token separator with attribute@separator.  For example,&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;myArray&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 2 3&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;myArray&amp;quot; type=&amp;quot;int&amp;quot; separator=&amp;quot;,&amp;quot;&amp;gt;1,2,3&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
both specify the same array of three integers named &amp;quot;myArray&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
TODO Add more information on splitting with a separator!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Structures (Containers) ====&lt;br /&gt;
&lt;br /&gt;
We use attribute@type=&amp;quot;Structure&amp;quot; to define a new (or existing) attribute container.   So if we&lt;br /&gt;
wanted to add a new attribute structure, we&#039;d use something like this: &lt;br /&gt;
&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;MySamples&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Location&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Station 1&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Samples&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 4 6&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assuming &amp;quot;MySamples&amp;quot; doesn&#039;t already exist, an attribute container will be created at the current scope&lt;br /&gt;
and the &amp;quot;Location&amp;quot; and &amp;quot;Samples&amp;quot; attributes will be added to it.&lt;br /&gt;
&lt;br /&gt;
Note that we can create nested attribute structures to arbitrary depth this way as well.&lt;br /&gt;
&lt;br /&gt;
If the attribute container with the given name already exists at the current scope, &lt;br /&gt;
then the attribute@type=&amp;quot;Structure&amp;quot; form is used to define&lt;br /&gt;
the lexical scope for the container.  In other words, child &amp;lt;attribute&amp;gt; elements will&lt;br /&gt;
be processed within the scope of the container.   For example, in the above example, if&lt;br /&gt;
&amp;quot;MySamples&amp;quot; already exists, then the &amp;quot;Location&amp;quot; and &amp;quot;Samples&amp;quot; will be processed within the&lt;br /&gt;
existing container (they may or may not already exist as well).&lt;br /&gt;
&lt;br /&gt;
==== Renaming an Existing Attribute or Attribute Container ====&lt;br /&gt;
&lt;br /&gt;
We also support the attribute@orgName attribute for renaming attributes.   &lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;NewName&amp;quot; orgName=&amp;quot;OldName&amp;quot; type=&amp;quot;string&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing attribute &amp;quot;OldName&amp;quot; to &amp;quot;NewName&amp;quot; while leaving its value alone.&lt;br /&gt;
If attribute@value is also specified, then the attribute is renamed &#039;&#039;and&#039;&#039; has its value modified.&lt;br /&gt;
&lt;br /&gt;
This works for renaming attribute containers as well:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;MyNewContainer&amp;quot; orgName=&amp;quot;MyOldContainer&amp;quot; type=&amp;quot;Structure&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing &amp;quot;MyOldContainer&amp;quot; to &amp;quot;MyNewContainer&amp;quot;.  Note that any children&lt;br /&gt;
of this container will remain in it.&lt;br /&gt;
&lt;br /&gt;
=== DAP &#039;&#039;OtherXML&#039;&#039; Extension ===&lt;br /&gt;
&lt;br /&gt;
The module now allows specification of attributes of the new DAP type &amp;quot;OtherXML&amp;quot;.  This allows the NCML file author to inject arbitrary well-formed XML into an attribute for clients that want XML metadata rather than just string or url.  Internally, the attribute is still a string (and in a DAP DAS response will be quoted inside one string).  However, since it is XML, the NCMLParser still parses it and checks it for well-formedness (but NOT against schemas).  This extension allows the NCMLParser to parse the arbitrary XML within the given attribute without causing errors, since it can be any XML.  &lt;br /&gt;
&lt;br /&gt;
The injected XML is most useful in the DDX response, where it shows up directly in the response as XML.  XSLT and other clients can then parse it.&lt;br /&gt;
&lt;br /&gt;
==== Errors ====&lt;br /&gt;
&lt;br /&gt;
*The XML &#039;&#039;&#039;must&#039;&#039;&#039; be in the content of the &amp;lt;attribute type=&amp;quot;OtherXML&amp;quot;&amp;gt; element.  It is a parser error for &#039;&#039;attribute@value&#039;&#039; to be set if &#039;&#039;attribute@type&#039;&#039; is &amp;quot;OtherXML&amp;quot;.  &lt;br /&gt;
*The XML must also be well-formed since it is parsed.  A parse error will be thrown if the OtherXML is malformed.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of the use of this special case.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf xmlns=&amp;quot;http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2&amp;quot; location=&amp;quot;/coverage/200803061600_HFRadar_USEGC_6km_rtv_SIO.nc&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;someName&amp;quot; type=&amp;quot;OtherXML&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;Domain xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot; &lt;br /&gt;
                xmlns:ows=&amp;quot;http://www.opengis.net/ows/1.1&amp;quot;&lt;br /&gt;
                xmlns:gml=&amp;quot;http://www.opengis.net/gml/3.2&amp;quot;&lt;br /&gt;
                &amp;gt;&lt;br /&gt;
            &amp;lt;SpatialDomain&amp;gt;&lt;br /&gt;
                &amp;lt;ows:BoundingBox crs=&amp;quot;urn:ogc:def:crs:EPSG::4326&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;ows:LowerCorner&amp;gt;-97.8839 21.736&amp;lt;/ows:LowerCorner&amp;gt;&lt;br /&gt;
                    &amp;lt;ows:UpperCorner&amp;gt;-57.2312 46.4944&amp;lt;/ows:UpperCorner&amp;gt;&lt;br /&gt;
                &amp;lt;/ows:BoundingBox&amp;gt;&lt;br /&gt;
            &amp;lt;/SpatialDomain&amp;gt;&lt;br /&gt;
            &amp;lt;TemporalDomain&amp;gt;&lt;br /&gt;
                &amp;lt;gml:timePosition&amp;gt;2008-03-27T16:00:00.000Z&amp;lt;/gml:timePosition&amp;gt;&lt;br /&gt;
            &amp;lt;/TemporalDomain&amp;gt;&lt;br /&gt;
        &amp;lt;/Domain&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedCRS xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;urn:ogc:def:crs:EPSG::4326&amp;lt;/SupportedCRS&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedFormat xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;netcdf-cf1.0&amp;lt;/SupportedFormat&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedFormat xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;dap2.0&amp;lt;/SupportedFormat&amp;gt;&lt;br /&gt;
    &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039; Put the DDX response for the above in here!&lt;br /&gt;
&lt;br /&gt;
====Namespace Closure====&lt;br /&gt;
&lt;br /&gt;
Furthermore, the parser will make the chunk of OtherXML &amp;quot;namespace closed&amp;quot;.  This means any namespaces specified in parent NCML elements of the OtherXML tree will be &amp;quot;brought down&amp;quot; and added to the &#039;&#039;root&#039;&#039; OtherXML elements so that the subtree may be pulled out and added to the DDX and still have its namespaces.  The algorithm doesn&#039;t just bring used prefixes, but brings &#039;&#039;all&#039;&#039; of the lexically scoped closest namespaces in all ancestors.  In other words, it adds unique namespaces (as determined by prefix) in order from the root of the OtherXML tree as it traverses to the root of the NCML document.  &lt;br /&gt;
&lt;br /&gt;
Namespace closure is a syntactic sugar that simplifies the author&#039;s task since they can specify the namespaces just once at the top of the NCML file and expect that when the subtree of XML is added to the DDX that these namespaces will come along with that subtree of XML.  Otherwise they have to explicitly add the namespaces to each attributes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039; Add an example!&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;remove&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;remove&amp;gt; element can remove attributes and variables.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;attribute name=&amp;quot;NC_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;remove name=&amp;quot;base_time&amp;quot; type=&amp;quot;attribute&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will remove the attribute named &amp;quot;base_time&amp;quot; in the attribute structure named &amp;quot;NC_GLOBAL&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Note that this works for attribute containers as well!  We could recursively remove the &#039;&#039;entire&#039;&#039;&lt;br /&gt;
attribute container (i.e. it and all its children) with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;remove name=&amp;quot;NC_GLOBAL&amp;quot; type=&amp;quot;attribute&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It also can be used to remove variables from existing datasets:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
  &amp;lt;remove name=&amp;quot;SomeExistingVariable&amp;quot; type=&amp;quot;variable&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This also recurses on variables of type Structure --- the entire structure including all of its children are removed from the dataset&#039;s response.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* It is a parse error if the given attribute or variable doesn&#039;t exist in the current scope&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;aggregation&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
Aggregation involves combining multiple datasets (&amp;lt;netcdf&amp;gt;) into a virtual &amp;quot;single&amp;quot; dataset in various ways.  For a tutorial on aggregation in NcML 2.2, the reader is referred to the Unidata page: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Aggregation.html&lt;br /&gt;
&lt;br /&gt;
NcML 2.2 supports multiple types of aggregation: union, joinNew, joinExisting, and fmrc (forecast model run collection).  &lt;br /&gt;
&lt;br /&gt;
The current version of the NcML module supports two of these aggregations:&lt;br /&gt;
&lt;br /&gt;
*Union [[NCML_Module_Aggregation_Union]]&lt;br /&gt;
*JoinNew [[NCML_Module_Aggregation_JoinNew]]&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;union&#039;&#039; aggregation specifies that the first instance of a variable or attribute (by name) that is found in the ordered list of datasets will be the one in the output aggregation.   This is useful for combining two dataset files, each which may contain a single variable, into a composite dataset with both variables.&lt;br /&gt;
&lt;br /&gt;
A JoinNew aggregation joins a variable which exists in multiple datasets (usually samples of a datum over time) into a new variable containing the data from &#039;&#039;all&#039;&#039; member datasets by creating a new outer dimension.  The &#039;&#039;i&#039;&#039;th component in the new outer dimension is the variable&#039;s data from the &#039;&#039;i&#039;&#039;th member dataset.  It also adds a new coordinate variable of whose name is the new dimension&#039;s name and whose shape (length) is the new dimension as well.  This new coordinate variable may be explicitly given by the author or may be autogenerated in one of several ways.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;scan&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The scan element can be used within an aggregation context to allow a directory to be searched in various ways in order to specify the members of an aggregation.  This allows a static NcML file to refer to an aggregation which may change over time, such as where a new data file is generated each day.&lt;br /&gt;
&lt;br /&gt;
We describe usage of the &amp;lt;scan&amp;gt; element in detail in the joinNew aggregation tutorial at [[NCML_Module_Aggregation_JoinNew]].&lt;br /&gt;
&lt;br /&gt;
= Errors =&lt;br /&gt;
&lt;br /&gt;
There are three types of error messages that may be returned:&lt;br /&gt;
&lt;br /&gt;
* Internal Error&lt;br /&gt;
* Resource Not Found Error&lt;br /&gt;
* Parse Error&lt;br /&gt;
&lt;br /&gt;
== Internal Errors ==&lt;br /&gt;
&#039;&#039;&#039;Internal errors&#039;&#039;&#039; should be reported to support@opendap.org as they are likely bugs.&lt;br /&gt;
&lt;br /&gt;
== Resource Not Found Errors ==&lt;br /&gt;
&lt;br /&gt;
If the netcdf@location specifies a non-existent local dataset (one that is not being served by&lt;br /&gt;
the same Hyrax server), it will specify the resource was not found.   This may also be returned&lt;br /&gt;
if a handler for the specified dataset is not currently loaded in the BES.  Users should test that the&lt;br /&gt;
dataset to be wrapped already exists and can be viewed on the running server before writing NcML &lt;br /&gt;
to add metadata.  It&#039;s also an error to refer to remote datasets (at this time).&lt;br /&gt;
&lt;br /&gt;
== Parse Errors ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse errors&#039;&#039;&#039; are user errors in the NcML file.  These could be malformed XML, malformed NcML, &lt;br /&gt;
unimplemented features of NcML, or could be errors in referring to the wrapped dataset.  &lt;br /&gt;
&lt;br /&gt;
The error message should specify &lt;br /&gt;
the error condition as well as the &amp;quot;current scope&amp;quot; as a fully qualified DAP name within the &lt;br /&gt;
loaded dataset.  This should be enough information to correct the parse error as new NcML&lt;br /&gt;
files are created.&lt;br /&gt;
&lt;br /&gt;
The parser will generate parse errors in various &lt;br /&gt;
situations where it expects to find certain structure in the underlying dataset.  Some examples:&lt;br /&gt;
&lt;br /&gt;
* A variable of the given name was not found at the current scope&lt;br /&gt;
* attribute@orgName was specified, but the attribute cannot be found at current scope.&lt;br /&gt;
* attribute@orgName was specified, but the new name is already used at current scope.&lt;br /&gt;
* remove specified a non-existing attribute name&lt;br /&gt;
&lt;br /&gt;
= Grid Metadata Tutorial =&lt;br /&gt;
&lt;br /&gt;
Please see the page [[Grid_Metadata_Tutorial]] for an example of adding metadata to the various parts of a DAP Grid variable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Aggregation Tutorials =&lt;br /&gt;
&lt;br /&gt;
The NcML module may also be used to aggregate multiple datasets into one virtual dataset.  We currently support two of the NcML aggregtions:&lt;br /&gt;
&lt;br /&gt;
*Union [[NCML_Module_Aggregation_Union]]:  combine multiple datasets into one by merging variables together, selecting the first of each unique name.&lt;br /&gt;
*JoinNew [[NCML_Module_Aggregation_JoinNew]]: combine variables across multiple datasets by creating a new outer dimension and coordinate variable for each of the sample datasets.&lt;br /&gt;
&lt;br /&gt;
Please see the sections for a tutorial on the various uses of these aggregations.&lt;br /&gt;
&lt;br /&gt;
= Additions/Changes to NcML 2.2 =&lt;br /&gt;
&lt;br /&gt;
This section will keep track of changes to the NcML 2.2 schema.  Eventually these&lt;br /&gt;
will be rolled into a new schema.&lt;br /&gt;
&lt;br /&gt;
== Attribute Structures (Containers) ==&lt;br /&gt;
This module also adds functionality beyond the current NcML 2.2 schema&lt;br /&gt;
--- it can handle nested &amp;lt;attribute&amp;gt; elements in order to make&lt;br /&gt;
attribute structures.  This is done by using the &amp;lt;attribute&lt;br /&gt;
type=&amp;quot;Structure&amp;quot;&amp;gt; form, for example:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;MySamples&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Location&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Station 1&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Samples&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 4 6&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;MyContainer&amp;quot; describes an attribute structure with two attribute fields,&lt;br /&gt;
a string &amp;quot;Location&amp;quot; and an array of int&#039;s called &amp;quot;Samples&amp;quot;.  &lt;br /&gt;
Note that an attribute structure of this form can&lt;br /&gt;
only contain other &amp;lt;attribute&amp;gt; elements and NOT a value.&lt;br /&gt;
&lt;br /&gt;
If the container does not already exist, it will be created at the scope it is declared, which could&lt;br /&gt;
be:&lt;br /&gt;
&lt;br /&gt;
* Global (top of dataset)&lt;br /&gt;
* Within a variable&#039;s attribute table&lt;br /&gt;
* Within another attribute container&lt;br /&gt;
&lt;br /&gt;
If an attribute container of the given name already exists at the lexical scope, it is traversed &lt;br /&gt;
in order to define the scope for the nested (children) attributes it contains.&lt;br /&gt;
&lt;br /&gt;
== Unspecified Variable Type Matching for Lexical Scope ==&lt;br /&gt;
&lt;br /&gt;
We also allow the type attribute of a variable element (variable@type) to be the empty string &lt;br /&gt;
(or unspecified) when using existing variables to define the lexical scope of an &amp;lt;attribute&amp;gt; &lt;br /&gt;
transformation.  In the schema, variable@type is (normally) required.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DAP 2 Types ==&lt;br /&gt;
&lt;br /&gt;
Additionally, we allow DAP2 atomic types (such as UInt32, URL) in addition to the NcML types.  &lt;br /&gt;
The NcML types are mapped onto the closest DAP2 type internally.&lt;br /&gt;
&lt;br /&gt;
== DAP OtherXML Attribute Type ==&lt;br /&gt;
&lt;br /&gt;
We also allow attributes to be of the new DAP type &amp;quot;OtherXML&amp;quot; for injecting arbitrary XML into an attribute as content rather than trying to form a string.  This allows the parser to check well-formedness.&lt;br /&gt;
&lt;br /&gt;
== Forward Declaration of Dimensions ==&lt;br /&gt;
&lt;br /&gt;
Since we use a SAX parser for efficiency, we require the &amp;lt;dimension&amp;gt; elements to come &#039;&#039;before&#039;&#039; their use in a &#039;&#039;variable@shape&#039;&#039;.  One way to change the schema to allow this is to force the dimension elements to be specified in a sequence after explicit and metadata choice and before all other elements.&lt;br /&gt;
&lt;br /&gt;
== Aggregation Element Location and Processing Order Differences ==&lt;br /&gt;
&lt;br /&gt;
NcML specifies that if a dataset (&amp;lt;netcdf&amp;gt; element) specifies an aggregation element, the aggregation element is always processed first, regardless of its ordering within the &amp;lt;netcdf&amp;gt; element.  Our parser, since it is SAX and not DOM, modifies this behavior in that order matters in some cases:&lt;br /&gt;
&lt;br /&gt;
* Metadata (&amp;lt;attribute&amp;gt;) elements specified &#039;&#039;prior&#039;&#039; to an aggregation &amp;quot;shadow&amp;quot; the aggregation versions.  This is be useful for &amp;quot;overriding&amp;quot; an attribute or variable in a union aggregation, where the first found will take precedence. &lt;br /&gt;
* JoinNew: If the new coordinate variable&#039;s data is to be set explicitly by specifying the new dimension&#039;s shape (either with explicit data or the autogenerated data using values@start and values@increment attributes), the &amp;lt;variable&amp;gt; &#039;&#039;must&#039;&#039; come after the aggregation since the size of the dimension is unknown until the aggregation element is processed.&lt;br /&gt;
&lt;br /&gt;
= Backward Compatibility Issues =&lt;br /&gt;
&lt;br /&gt;
Due to the way shared dimensions were implemented in the NetCDF, HDF4, and HDF5 handlers, the DAS responses did not follow the DAP2 specification.  The NcML module, on the other hand, generates DAP2 compliant DAS for these datasets, which means that wrapping some datasets in NcML will generate a DAS with a different structure.  This is important for the NcML author since it changes the names of attributes and variables.  In order for the module to find the correct scope for adding metadata, for example, the DAP2 DAS must be used.  &lt;br /&gt;
&lt;br /&gt;
In general, what this means is that an empty &amp;quot;passthrough&amp;quot; NcML file should be the starting point for authoring an NcML file.  This file would just specify a dataset and nothing else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;/data/ncml/myNetcdf.nc&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The author would then request the DAS response for the NCML file and use that as the starting point for modifications to the original dataset. &lt;br /&gt;
&lt;br /&gt;
More explicit examples are given below.&lt;br /&gt;
&lt;br /&gt;
== NetCDF ==&lt;br /&gt;
&lt;br /&gt;
The NetCDF handler represents some NC datasets as a DAP 2 Grid, but the returned DAS is not consistent with the DAP 2 spec for the attribute hierarchy for such a Grid.  The map vector attributes are placed as siblings of the grid attributes rather than within the grid lexical scope.  For example, here&#039;s the NetCDF Handler DDS for a given file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Int16 cldc[time = 456][lat = 21][lon = 360];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 456];&lt;br /&gt;
        Float32 lat[lat = 21];&lt;br /&gt;
        Float32 lon[lon = 360];&lt;br /&gt;
    } cldc;&lt;br /&gt;
} cldc.mean.nc;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
showing the Grid.  Here&#039;s the DAS the NetCDF handler generates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    lat {&lt;br /&gt;
        String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
        String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
        Float32 actual_range 10.00000000, -10.00000000;&lt;br /&gt;
    }&lt;br /&gt;
    lon {&lt;br /&gt;
        String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
        String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
        Float32 actual_range 0.5000000000, 359.5000000;&lt;br /&gt;
    }&lt;br /&gt;
    time {&lt;br /&gt;
        String units &amp;quot;days since 1-1-1 00:00:0.0&amp;quot;;&lt;br /&gt;
        String long_name &amp;quot;Time&amp;quot;;&lt;br /&gt;
        String delta_t &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
        String avg_period &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
        Float64 actual_range 715511.00000000000, 729360.00000000000;&lt;br /&gt;
    }&lt;br /&gt;
    cldc {&lt;br /&gt;
        Float32 valid_range 0.000000000, 8.000000000;&lt;br /&gt;
        Float32 actual_range 0.000000000, 8.000000000;&lt;br /&gt;
        String units &amp;quot;okta&amp;quot;;&lt;br /&gt;
        Int16 precision 1;&lt;br /&gt;
        Int16 missing_value 32766;&lt;br /&gt;
        Int16 _FillValue 32766;&lt;br /&gt;
        String long_name &amp;quot;Cloudiness Monthly Mean at Surface&amp;quot;;&lt;br /&gt;
        String dataset &amp;quot;COADS 1-degree Equatorial Enhanced\\012AI&amp;quot;;&lt;br /&gt;
        String var_desc &amp;quot;Cloudiness\\012C&amp;quot;;&lt;br /&gt;
        String level_desc &amp;quot;Surface\\0120&amp;quot;;&lt;br /&gt;
        String statistic &amp;quot;Mean\\012M&amp;quot;;&lt;br /&gt;
        String parent_stat &amp;quot;Individual Obs\\012I&amp;quot;;&lt;br /&gt;
        Float32 add_offset 3276.500000;&lt;br /&gt;
        Float32 scale_factor 0.1000000015;&lt;br /&gt;
    }&lt;br /&gt;
    NC_GLOBAL {&lt;br /&gt;
        String title &amp;quot;COADS 1-degree Equatorial Enhanced&amp;quot;;&lt;br /&gt;
        String history &amp;quot;&amp;quot;;&lt;br /&gt;
        String Conventions &amp;quot;COARDS&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    DODS_EXTRA {&lt;br /&gt;
        String Unlimited_Dimension &amp;quot;time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the map vector attributes are in the &amp;quot;dataset&amp;quot; scope.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the DAS that the NcML Module produces from the correctly formed DDX:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    NC_GLOBAL {&lt;br /&gt;
        String title &amp;quot;COADS 1-degree Equatorial Enhanced&amp;quot;;&lt;br /&gt;
        String history &amp;quot;&amp;quot;;&lt;br /&gt;
        String Conventions &amp;quot;COARDS&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    DODS_EXTRA {&lt;br /&gt;
        String Unlimited_Dimension &amp;quot;time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    cldc {&lt;br /&gt;
        Float32 valid_range 0.000000000, 8.000000000;&lt;br /&gt;
        Float32 actual_range 0.000000000, 8.000000000;&lt;br /&gt;
        String units &amp;quot;okta&amp;quot;;&lt;br /&gt;
        Int16 precision 1;&lt;br /&gt;
        Int16 missing_value 32766;&lt;br /&gt;
        Int16 _FillValue 32766;&lt;br /&gt;
        String long_name &amp;quot;Cloudiness Monthly Mean at Surface&amp;quot;;&lt;br /&gt;
        String dataset &amp;quot;COADS 1-degree Equatorial Enhanced\\012AI&amp;quot;;&lt;br /&gt;
        String var_desc &amp;quot;Cloudiness\\012C&amp;quot;;&lt;br /&gt;
        String level_desc &amp;quot;Surface\\0120&amp;quot;;&lt;br /&gt;
        String statistic &amp;quot;Mean\\012M&amp;quot;;&lt;br /&gt;
        String parent_stat &amp;quot;Individual Obs\\012I&amp;quot;;&lt;br /&gt;
        Float32 add_offset 3276.500000;&lt;br /&gt;
        Float32 scale_factor 0.1000000015;&lt;br /&gt;
        cldc {&lt;br /&gt;
        }&lt;br /&gt;
        time {&lt;br /&gt;
            String units &amp;quot;days since 1-1-1 00:00:0.0&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;Time&amp;quot;;&lt;br /&gt;
            String delta_t &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
            String avg_period &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
            Float64 actual_range 715511.00000000000, 729360.00000000000;&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
            Float32 actual_range 10.00000000, -10.00000000;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
            Float32 actual_range 0.5000000000, 359.5000000;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here the Grid Structure &amp;quot;cldc&amp;quot;  and its contained data array (of the same name &amp;quot;cldc&amp;quot;) and map vectors have their own attribute containers as DAP 2 specifies.&lt;br /&gt;
&lt;br /&gt;
What this means for the author of an NcML file adding metadata to a NetCDF dataset that returns a Grid is that they should generate a &amp;quot;passthrough&amp;quot; file and get the DAS and then specify modifications based on that structure.  &lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example passthrough:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/cldc.mean.nc&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For example, to add an attribute to the map vector &amp;quot;lat&amp;quot; in the above, we&#039;d need the following NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/cldc.mean.nc&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;!-- Traverse into the Grid as a Structure --&amp;gt;&lt;br /&gt;
  &amp;lt;variable name=&amp;quot;cldc&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Traverse into the &amp;quot;lat&amp;quot; map vector (Array) --&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lat&amp;quot;&amp;gt; &lt;br /&gt;
      &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;I am a new attribute in the Grid map vector named lat!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lon&amp;quot;&amp;gt; &lt;br /&gt;
      &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;I am a new attribute in the Grid map vector named lon!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This clearly shows that the structure of the Grid must be used in the NcML:  the attribute being added is technically &amp;quot;cldc.lat.Description&amp;quot; in a fully qualified name.  The parser would return an error if it was attempted as &amp;quot;lat.Description&amp;quot; as the NetCDF DAS for the original file would have led one to believe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== HDF4/HDF5 ==&lt;br /&gt;
&lt;br /&gt;
Similarly to the NetCDF case, the Hyrax HDF4 Module produces DAS responses that do not respect the DAP2 specification.  If an NcML file is used to &amp;quot;wrap&amp;quot; an HDF4 dataset, the&lt;br /&gt;
correct DAP2 DAS response will be generated, however. &lt;br /&gt;
&lt;br /&gt;
This is important for those writing NcML for HDF4 data since the&lt;br /&gt;
lexical scope for attributes relies on the correct DAS form --- to&lt;br /&gt;
handle this, the user should start with a &amp;quot;passthrough&amp;quot; NcML file (see the above NetCDF example) and&lt;br /&gt;
use the DAS from that as the starting point for knowing the structure&lt;br /&gt;
the NcML handler expects to see in the NcML file.  Alternatively, the DDX has the &lt;br /&gt;
proper attribute structure as well (the DAS is generated from it).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Known Bugs =&lt;br /&gt;
&lt;br /&gt;
There are no known bugs currently.&lt;br /&gt;
&lt;br /&gt;
= Planned Future Enhancements =&lt;br /&gt;
&lt;br /&gt;
Planned enhancements for future versions of the module include:&lt;br /&gt;
&lt;br /&gt;
* New NcML Aggregations&lt;br /&gt;
** JoinExisting&lt;br /&gt;
*** Joins a variable across multiple datasets by appending the data for a given dimension from each dataset &lt;br /&gt;
*** Will also allow directory scans for specifying the aggregation&lt;br /&gt;
** Forecast Model Run Collection (FMRC)&lt;br /&gt;
*** Special case of JoinNew for forecast data with two time variables&lt;br /&gt;
*** See: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/FmrcAggregation.html&lt;br /&gt;
&lt;br /&gt;
= Copyright =&lt;br /&gt;
&lt;br /&gt;
This software is copyrighted under the GNU Lesser GPL.  Please see the&lt;br /&gt;
files COPYING and COPYRIGHT that came with this distribution.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=NCML_Module_Aggregation_JoinExisting&amp;diff=5792</id>
		<title>NCML Module Aggregation JoinExisting</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=NCML_Module_Aggregation_JoinExisting&amp;diff=5792"/>
		<updated>2010-09-17T18:29:49Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Future Work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Aggregation]]&lt;br /&gt;
[[Category:NCML]]&lt;br /&gt;
&lt;br /&gt;
= Join Existing Aggregation =&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;joinExisting&#039;&#039; aggregation joins multiple granule datasets by concatenating the specified outer dimensional data from the granules into the output.  This results in matrices of the same number of dimensions, but with larger outer dimension cardinality.  The outer dimension sizes of the granules may vary across granule, but any inner dimensions for multi-dimensional data still are required to match.  &lt;br /&gt;
&lt;br /&gt;
The reader is also directed to a basic tutorial of this NcML aggregation which may be found at http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Aggregation.html#joinExisting.  Note that version 1.1.0 of the module does not support all features of joinExisting!  Future versions will add more features.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;PLEASE NOTE&#039;&#039;&#039; that our syntax is slightly different than that of the THREDDS Data Server (TDS), so please refer to this tutorial when using the Hyrax NcML Module!  In particular, we do not process the &amp;lt;aggregation&amp;gt; element prior to other elements in the dataset, so in some cases the relative ordering of the &amp;lt;aggregation&amp;gt; and references to variables within the aggregation matters.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This page describes the behavior of the initial implementation of joinExisting for version 1.1.0 of the NcML Module, bundled with Hyrax 1.6.2.  It is a limited feature set described below.  Please see the Limitations section for more information.&lt;br /&gt;
&lt;br /&gt;
In version 1.1.0, a joinExisting aggregation may be specified in two ways currently:&lt;br /&gt;
&lt;br /&gt;
* Using explicit lists of &#039;&#039;&#039;netcdf&#039;&#039;&#039; elements with the &#039;&#039;ncoords&#039;&#039; attribute correctly specified for all of them.&lt;br /&gt;
* Using a &#039;&#039;&#039;scan&#039;&#039;&#039; element with &#039;&#039;ncoords&#039;&#039; specified and all matching granule datasets having this dimension size&lt;br /&gt;
&lt;br /&gt;
Our example below will clarify this.&lt;br /&gt;
&lt;br /&gt;
Future versions of the module  will implement more of the joinExisting feature set.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
Here we give an example that illustrates the functionality offered by the current version of the aggregation.  This example may also be found on:&lt;br /&gt;
&lt;br /&gt;
http://test.opendap.org:8090/opendap/ioos/mday_joinExist.ncml&lt;br /&gt;
&lt;br /&gt;
with the data granules located in&lt;br /&gt;
&lt;br /&gt;
http://test.opendap.org:8090/opendap/coverage/mday/&lt;br /&gt;
&lt;br /&gt;
=== Granules ===&lt;br /&gt;
&lt;br /&gt;
Assume we have some number of granule datasets with a DDS the same as the following (modulo the dataset name):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Float32 PHssta[time = 1][altitude = 1][lat = 4096][lon = 8192];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 1];&lt;br /&gt;
        Float64 altitude[altitude = 1];&lt;br /&gt;
        Float64 lat[lat = 4096];&lt;br /&gt;
        Float64 lon[lon = 8192];&lt;br /&gt;
    } PHssta;&lt;br /&gt;
} PH2006001_2006031_ssta.nc;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Explicit Listing of Granules ===&lt;br /&gt;
&lt;br /&gt;
We see that here &#039;&#039;time&#039;&#039; is the outer dimension, which is the only dimension we may join along (it is an error to specify an inner).    Given some number of granules with this same shape, consider the following explicit joinExisting aggregation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinExisting test on netcdf Grid granules&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinExisting&amp;quot; &lt;br /&gt;
	       dimName=&amp;quot;time&amp;quot; &amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Note explicit use of ncoords specifying size of &amp;quot;time&amp;quot; in file required --&amp;gt;&lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;/coverage/mday/PH2006001_2006031_ssta.nc&amp;quot;&lt;br /&gt;
                   ncoords=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;/coverage/mday/PH2006032_2006059_ssta.nc&amp;quot;&lt;br /&gt;
                   ncoords=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;/coverage/mday/PH2006060_2006090_ssta.nc&amp;quot;&lt;br /&gt;
                   ncoords=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
First, note that the &#039;&#039;ncoords&#039;&#039; attribute &#039;&#039;&#039;MUST&#039;&#039;&#039; be specified on the individual granules for this version of the module (future versions will relax this requirement and automatically and efficiently load the sizes).  Note that we also specify the &#039;&#039;dimName&#039;&#039;.  Any data array whose outer dimension is called this will be subject to aggregation in the output. &lt;br /&gt;
&lt;br /&gt;
Serving this from Hyrax will result in the following DDS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Float32 PHssta[time = 3][altitude = 1][lat = 4096][lon = 8192];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 3];&lt;br /&gt;
        Float64 altitude[altitude = 1];&lt;br /&gt;
        Float64 lat[lat = 4096];&lt;br /&gt;
        Float64 lon[lon = 8192];&lt;br /&gt;
    } PHssta;&lt;br /&gt;
    Float64 time[time = 3];&lt;br /&gt;
} mday_joinExist.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that the time dimension is now of size 3 to match that we joined three granule datasets together.&lt;br /&gt;
&lt;br /&gt;
Also notice that the map vector for the joined dimension, time, has been duplicated as a sibling of the dataset.  This is done automatically by the aggregation and it is copied into the actual map of the Grid.  This copy is to facilitate datasets which have multiple Grid&#039;s that are to be joined --- the top-level map vector is used as the canonical template map which is then copied into the maps for all the aggregated Grids.  In the case of the joined data being of type Array, this vector would already exist as the coordinate variable for the data matrix.  Since this is the source map for all aggregated Grid&#039;s, any attribute (metadata) changes should be made explicitly on this top-level coordinate variable so that the metadata is shared among all the aggregated Grid map vectors.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Using the scan element with ncoords extension ===&lt;br /&gt;
&lt;br /&gt;
Since all of the granules are of uniform size, we may also use the syntactic sugar provided by a Hyrax-specific extension to NcML -- adding the &#039;&#039;ncoords&#039;&#039; attribute to a &#039;&#039;&#039;scan&#039;&#039;&#039; element.   The behavior of this extension is to set the &#039;&#039;ncoords&#039;&#039; for each granule matching the scan to be this value, as if the datasets were each listed explicitly with this value of the attribute.  Here&#039;s an example of using the syntactic sugar that results in the same exact aggregation as the previous explicit one:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!-- joinExisting test on netcdf granules using scan@ncoords extension--&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinExisting test on netcdf Grid granules using scan@ncoords&amp;quot;&lt;br /&gt;
	&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&lt;br /&gt;
	     value=&amp;quot; joinExisting test on netcdf Grid granules using scan@ncoords&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinExisting&amp;quot; &lt;br /&gt;
	       dimName=&amp;quot;time&amp;quot; &amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Filenames have lexicographic and chronological ordering match --&amp;gt;&lt;br /&gt;
    &amp;lt;scan location=&amp;quot;/coverage/mday&amp;quot;&lt;br /&gt;
	  subdirs=&amp;quot;false&amp;quot;&lt;br /&gt;
	  suffix=&amp;quot;.nc&amp;quot;&lt;br /&gt;
	  ncoords=&amp;quot;1&amp;quot;&lt;br /&gt;
	  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
which we see results in the same DDS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Float32 PHssta[time = 3][altitude = 1][lat = 4096][lon = 8192];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 3];&lt;br /&gt;
        Float64 altitude[altitude = 1];&lt;br /&gt;
        Float64 lat[lat = 4096];&lt;br /&gt;
        Float64 lon[lon = 8192];&lt;br /&gt;
    } PHssta;&lt;br /&gt;
    Float64 time[time = 3];&lt;br /&gt;
} mday_joinExist.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Limitations ==&lt;br /&gt;
&lt;br /&gt;
The current version implements only basic functionality.  If there is extended functionality that is needed for your use, please send &amp;lt;mailto:support@opendap.org&amp;gt; to let us know!  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Join Dimension Sizes Must Be Explicitly Declared ===&lt;br /&gt;
&lt;br /&gt;
As we have seen, the most important limitation is that the ncoords must be specified for efficiency reasons.  Future versions will relax this requirement.  The problem is that the size of the output join dimension is dependent on checking the DDS of &#039;&#039;every&#039;&#039; granule in the aggregation, which is computationally expensive for large aggregations unless it is computed once and cached.  The next feature release of the module will include a caching system for solving this general problem and allowing the ncoords to be loaded automatically rather than being specified.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Source of Data for Agrgegated Coordinate Variable on Join Dimension ===&lt;br /&gt;
&lt;br /&gt;
This version does not allow the join dimension&#039;s data to be declared explicitly in the NcML as the NcML tutorial page describes.  This version automatically aggregates &#039;&#039;&#039;all&#039;&#039;&#039; variables with the outer dimension matching the &#039;&#039;dimName&#039;&#039;.  This includes the coordinate variable (map vector in the case of Grid&#039;s) for the join dimension.  These data cannot be overridden from those pulled from the files.  Currently the TDS lists about 5 ways this data can be specified in addition to pulling them from the granules --- we only can pull them from granules now, which seems the most common use.&lt;br /&gt;
&lt;br /&gt;
=== Source of Join Dimension Metadata ===&lt;br /&gt;
&lt;br /&gt;
The metadata for the coordinate variable is pulled from the &#039;&#039;first&#039;&#039; granule dataset.  Modification of coordinate variable metadata is not fully supported yet.&lt;br /&gt;
&lt;br /&gt;
== Future Work ==&lt;br /&gt;
&lt;br /&gt;
The most important addition in the next release will be the ability to efficiently load and cache the granule dimension sizes offline to allow for a highly interactive user experience when data is requested.  This means that the &#039;&#039;ncoords&#039;&#039; attribute will no longer be required on the granules, although doing so results in a more efficient aggregation speed.  &lt;br /&gt;
&lt;br /&gt;
We also plan to allow the data and metadata for the join dimension coordinate variable to be overridden and modified.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=NCML_Module_Aggregation_JoinExisting&amp;diff=5791</id>
		<title>NCML Module Aggregation JoinExisting</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=NCML_Module_Aggregation_JoinExisting&amp;diff=5791"/>
		<updated>2010-09-17T18:26:42Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Limitations */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Aggregation]]&lt;br /&gt;
[[Category:NCML]]&lt;br /&gt;
&lt;br /&gt;
= Join Existing Aggregation =&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;joinExisting&#039;&#039; aggregation joins multiple granule datasets by concatenating the specified outer dimensional data from the granules into the output.  This results in matrices of the same number of dimensions, but with larger outer dimension cardinality.  The outer dimension sizes of the granules may vary across granule, but any inner dimensions for multi-dimensional data still are required to match.  &lt;br /&gt;
&lt;br /&gt;
The reader is also directed to a basic tutorial of this NcML aggregation which may be found at http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Aggregation.html#joinExisting.  Note that version 1.1.0 of the module does not support all features of joinExisting!  Future versions will add more features.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;PLEASE NOTE&#039;&#039;&#039; that our syntax is slightly different than that of the THREDDS Data Server (TDS), so please refer to this tutorial when using the Hyrax NcML Module!  In particular, we do not process the &amp;lt;aggregation&amp;gt; element prior to other elements in the dataset, so in some cases the relative ordering of the &amp;lt;aggregation&amp;gt; and references to variables within the aggregation matters.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This page describes the behavior of the initial implementation of joinExisting for version 1.1.0 of the NcML Module, bundled with Hyrax 1.6.2.  It is a limited feature set described below.  Please see the Limitations section for more information.&lt;br /&gt;
&lt;br /&gt;
In version 1.1.0, a joinExisting aggregation may be specified in two ways currently:&lt;br /&gt;
&lt;br /&gt;
* Using explicit lists of &#039;&#039;&#039;netcdf&#039;&#039;&#039; elements with the &#039;&#039;ncoords&#039;&#039; attribute correctly specified for all of them.&lt;br /&gt;
* Using a &#039;&#039;&#039;scan&#039;&#039;&#039; element with &#039;&#039;ncoords&#039;&#039; specified and all matching granule datasets having this dimension size&lt;br /&gt;
&lt;br /&gt;
Our example below will clarify this.&lt;br /&gt;
&lt;br /&gt;
Future versions of the module  will implement more of the joinExisting feature set.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
Here we give an example that illustrates the functionality offered by the current version of the aggregation.  This example may also be found on:&lt;br /&gt;
&lt;br /&gt;
http://test.opendap.org:8090/opendap/ioos/mday_joinExist.ncml&lt;br /&gt;
&lt;br /&gt;
with the data granules located in&lt;br /&gt;
&lt;br /&gt;
http://test.opendap.org:8090/opendap/coverage/mday/&lt;br /&gt;
&lt;br /&gt;
=== Granules ===&lt;br /&gt;
&lt;br /&gt;
Assume we have some number of granule datasets with a DDS the same as the following (modulo the dataset name):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Float32 PHssta[time = 1][altitude = 1][lat = 4096][lon = 8192];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 1];&lt;br /&gt;
        Float64 altitude[altitude = 1];&lt;br /&gt;
        Float64 lat[lat = 4096];&lt;br /&gt;
        Float64 lon[lon = 8192];&lt;br /&gt;
    } PHssta;&lt;br /&gt;
} PH2006001_2006031_ssta.nc;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Explicit Listing of Granules ===&lt;br /&gt;
&lt;br /&gt;
We see that here &#039;&#039;time&#039;&#039; is the outer dimension, which is the only dimension we may join along (it is an error to specify an inner).    Given some number of granules with this same shape, consider the following explicit joinExisting aggregation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinExisting test on netcdf Grid granules&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinExisting&amp;quot; &lt;br /&gt;
	       dimName=&amp;quot;time&amp;quot; &amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Note explicit use of ncoords specifying size of &amp;quot;time&amp;quot; in file required --&amp;gt;&lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;/coverage/mday/PH2006001_2006031_ssta.nc&amp;quot;&lt;br /&gt;
                   ncoords=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;/coverage/mday/PH2006032_2006059_ssta.nc&amp;quot;&lt;br /&gt;
                   ncoords=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;/coverage/mday/PH2006060_2006090_ssta.nc&amp;quot;&lt;br /&gt;
                   ncoords=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
First, note that the &#039;&#039;ncoords&#039;&#039; attribute &#039;&#039;&#039;MUST&#039;&#039;&#039; be specified on the individual granules for this version of the module (future versions will relax this requirement and automatically and efficiently load the sizes).  Note that we also specify the &#039;&#039;dimName&#039;&#039;.  Any data array whose outer dimension is called this will be subject to aggregation in the output. &lt;br /&gt;
&lt;br /&gt;
Serving this from Hyrax will result in the following DDS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Float32 PHssta[time = 3][altitude = 1][lat = 4096][lon = 8192];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 3];&lt;br /&gt;
        Float64 altitude[altitude = 1];&lt;br /&gt;
        Float64 lat[lat = 4096];&lt;br /&gt;
        Float64 lon[lon = 8192];&lt;br /&gt;
    } PHssta;&lt;br /&gt;
    Float64 time[time = 3];&lt;br /&gt;
} mday_joinExist.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that the time dimension is now of size 3 to match that we joined three granule datasets together.&lt;br /&gt;
&lt;br /&gt;
Also notice that the map vector for the joined dimension, time, has been duplicated as a sibling of the dataset.  This is done automatically by the aggregation and it is copied into the actual map of the Grid.  This copy is to facilitate datasets which have multiple Grid&#039;s that are to be joined --- the top-level map vector is used as the canonical template map which is then copied into the maps for all the aggregated Grids.  In the case of the joined data being of type Array, this vector would already exist as the coordinate variable for the data matrix.  Since this is the source map for all aggregated Grid&#039;s, any attribute (metadata) changes should be made explicitly on this top-level coordinate variable so that the metadata is shared among all the aggregated Grid map vectors.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Using the scan element with ncoords extension ===&lt;br /&gt;
&lt;br /&gt;
Since all of the granules are of uniform size, we may also use the syntactic sugar provided by a Hyrax-specific extension to NcML -- adding the &#039;&#039;ncoords&#039;&#039; attribute to a &#039;&#039;&#039;scan&#039;&#039;&#039; element.   The behavior of this extension is to set the &#039;&#039;ncoords&#039;&#039; for each granule matching the scan to be this value, as if the datasets were each listed explicitly with this value of the attribute.  Here&#039;s an example of using the syntactic sugar that results in the same exact aggregation as the previous explicit one:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!-- joinExisting test on netcdf granules using scan@ncoords extension--&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinExisting test on netcdf Grid granules using scan@ncoords&amp;quot;&lt;br /&gt;
	&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&lt;br /&gt;
	     value=&amp;quot; joinExisting test on netcdf Grid granules using scan@ncoords&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinExisting&amp;quot; &lt;br /&gt;
	       dimName=&amp;quot;time&amp;quot; &amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Filenames have lexicographic and chronological ordering match --&amp;gt;&lt;br /&gt;
    &amp;lt;scan location=&amp;quot;/coverage/mday&amp;quot;&lt;br /&gt;
	  subdirs=&amp;quot;false&amp;quot;&lt;br /&gt;
	  suffix=&amp;quot;.nc&amp;quot;&lt;br /&gt;
	  ncoords=&amp;quot;1&amp;quot;&lt;br /&gt;
	  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
which we see results in the same DDS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Float32 PHssta[time = 3][altitude = 1][lat = 4096][lon = 8192];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 3];&lt;br /&gt;
        Float64 altitude[altitude = 1];&lt;br /&gt;
        Float64 lat[lat = 4096];&lt;br /&gt;
        Float64 lon[lon = 8192];&lt;br /&gt;
    } PHssta;&lt;br /&gt;
    Float64 time[time = 3];&lt;br /&gt;
} mday_joinExist.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Limitations ==&lt;br /&gt;
&lt;br /&gt;
The current version implements only basic functionality.  If there is extended functionality that is needed for your use, please send &amp;lt;mailto:support@opendap.org&amp;gt; to let us know!  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Join Dimension Sizes Must Be Explicitly Declared ===&lt;br /&gt;
&lt;br /&gt;
As we have seen, the most important limitation is that the ncoords must be specified for efficiency reasons.  Future versions will relax this requirement.  The problem is that the size of the output join dimension is dependent on checking the DDS of &#039;&#039;every&#039;&#039; granule in the aggregation, which is computationally expensive for large aggregations unless it is computed once and cached.  The next feature release of the module will include a caching system for solving this general problem and allowing the ncoords to be loaded automatically rather than being specified.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Source of Data for Agrgegated Coordinate Variable on Join Dimension ===&lt;br /&gt;
&lt;br /&gt;
This version does not allow the join dimension&#039;s data to be declared explicitly in the NcML as the NcML tutorial page describes.  This version automatically aggregates &#039;&#039;&#039;all&#039;&#039;&#039; variables with the outer dimension matching the &#039;&#039;dimName&#039;&#039;.  This includes the coordinate variable (map vector in the case of Grid&#039;s) for the join dimension.  These data cannot be overridden from those pulled from the files.  Currently the TDS lists about 5 ways this data can be specified in addition to pulling them from the granules --- we only can pull them from granules now, which seems the most common use.&lt;br /&gt;
&lt;br /&gt;
=== Source of Join Dimension Metadata ===&lt;br /&gt;
&lt;br /&gt;
The metadata for the coordinate variable is pulled from the &#039;&#039;first&#039;&#039; granule dataset.  Modification of coordinate variable metadata is not fully supported yet.&lt;br /&gt;
&lt;br /&gt;
== Future Work ==&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=NCML_Module_Aggregation_JoinExisting&amp;diff=5790</id>
		<title>NCML Module Aggregation JoinExisting</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=NCML_Module_Aggregation_JoinExisting&amp;diff=5790"/>
		<updated>2010-09-17T18:16:07Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Aggregation]]&lt;br /&gt;
[[Category:NCML]]&lt;br /&gt;
&lt;br /&gt;
= Join Existing Aggregation =&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;joinExisting&#039;&#039; aggregation joins multiple granule datasets by concatenating the specified outer dimensional data from the granules into the output.  This results in matrices of the same number of dimensions, but with larger outer dimension cardinality.  The outer dimension sizes of the granules may vary across granule, but any inner dimensions for multi-dimensional data still are required to match.  &lt;br /&gt;
&lt;br /&gt;
The reader is also directed to a basic tutorial of this NcML aggregation which may be found at http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Aggregation.html#joinExisting.  Note that version 1.1.0 of the module does not support all features of joinExisting!  Future versions will add more features.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;PLEASE NOTE&#039;&#039;&#039; that our syntax is slightly different than that of the THREDDS Data Server (TDS), so please refer to this tutorial when using the Hyrax NcML Module!  In particular, we do not process the &amp;lt;aggregation&amp;gt; element prior to other elements in the dataset, so in some cases the relative ordering of the &amp;lt;aggregation&amp;gt; and references to variables within the aggregation matters.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This page describes the behavior of the initial implementation of joinExisting for version 1.1.0 of the NcML Module, bundled with Hyrax 1.6.2.  It is a limited feature set described below.  Please see the Limitations section for more information.&lt;br /&gt;
&lt;br /&gt;
In version 1.1.0, a joinExisting aggregation may be specified in two ways currently:&lt;br /&gt;
&lt;br /&gt;
* Using explicit lists of &#039;&#039;&#039;netcdf&#039;&#039;&#039; elements with the &#039;&#039;ncoords&#039;&#039; attribute correctly specified for all of them.&lt;br /&gt;
* Using a &#039;&#039;&#039;scan&#039;&#039;&#039; element with &#039;&#039;ncoords&#039;&#039; specified and all matching granule datasets having this dimension size&lt;br /&gt;
&lt;br /&gt;
Our example below will clarify this.&lt;br /&gt;
&lt;br /&gt;
Future versions of the module  will implement more of the joinExisting feature set.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
Here we give an example that illustrates the functionality offered by the current version of the aggregation.  This example may also be found on:&lt;br /&gt;
&lt;br /&gt;
http://test.opendap.org:8090/opendap/ioos/mday_joinExist.ncml&lt;br /&gt;
&lt;br /&gt;
with the data granules located in&lt;br /&gt;
&lt;br /&gt;
http://test.opendap.org:8090/opendap/coverage/mday/&lt;br /&gt;
&lt;br /&gt;
=== Granules ===&lt;br /&gt;
&lt;br /&gt;
Assume we have some number of granule datasets with a DDS the same as the following (modulo the dataset name):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Float32 PHssta[time = 1][altitude = 1][lat = 4096][lon = 8192];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 1];&lt;br /&gt;
        Float64 altitude[altitude = 1];&lt;br /&gt;
        Float64 lat[lat = 4096];&lt;br /&gt;
        Float64 lon[lon = 8192];&lt;br /&gt;
    } PHssta;&lt;br /&gt;
} PH2006001_2006031_ssta.nc;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Explicit Listing of Granules ===&lt;br /&gt;
&lt;br /&gt;
We see that here &#039;&#039;time&#039;&#039; is the outer dimension, which is the only dimension we may join along (it is an error to specify an inner).    Given some number of granules with this same shape, consider the following explicit joinExisting aggregation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinExisting test on netcdf Grid granules&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinExisting&amp;quot; &lt;br /&gt;
	       dimName=&amp;quot;time&amp;quot; &amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Note explicit use of ncoords specifying size of &amp;quot;time&amp;quot; in file required --&amp;gt;&lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;/coverage/mday/PH2006001_2006031_ssta.nc&amp;quot;&lt;br /&gt;
                   ncoords=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;/coverage/mday/PH2006032_2006059_ssta.nc&amp;quot;&lt;br /&gt;
                   ncoords=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;/coverage/mday/PH2006060_2006090_ssta.nc&amp;quot;&lt;br /&gt;
                   ncoords=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
First, note that the &#039;&#039;ncoords&#039;&#039; attribute &#039;&#039;&#039;MUST&#039;&#039;&#039; be specified on the individual granules for this version of the module (future versions will relax this requirement and automatically and efficiently load the sizes).  Note that we also specify the &#039;&#039;dimName&#039;&#039;.  Any data array whose outer dimension is called this will be subject to aggregation in the output. &lt;br /&gt;
&lt;br /&gt;
Serving this from Hyrax will result in the following DDS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Float32 PHssta[time = 3][altitude = 1][lat = 4096][lon = 8192];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 3];&lt;br /&gt;
        Float64 altitude[altitude = 1];&lt;br /&gt;
        Float64 lat[lat = 4096];&lt;br /&gt;
        Float64 lon[lon = 8192];&lt;br /&gt;
    } PHssta;&lt;br /&gt;
    Float64 time[time = 3];&lt;br /&gt;
} mday_joinExist.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that the time dimension is now of size 3 to match that we joined three granule datasets together.&lt;br /&gt;
&lt;br /&gt;
Also notice that the map vector for the joined dimension, time, has been duplicated as a sibling of the dataset.  This is done automatically by the aggregation and it is copied into the actual map of the Grid.  This copy is to facilitate datasets which have multiple Grid&#039;s that are to be joined --- the top-level map vector is used as the canonical template map which is then copied into the maps for all the aggregated Grids.  In the case of the joined data being of type Array, this vector would already exist as the coordinate variable for the data matrix.  Since this is the source map for all aggregated Grid&#039;s, any attribute (metadata) changes should be made explicitly on this top-level coordinate variable so that the metadata is shared among all the aggregated Grid map vectors.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Using the scan element with ncoords extension ===&lt;br /&gt;
&lt;br /&gt;
Since all of the granules are of uniform size, we may also use the syntactic sugar provided by a Hyrax-specific extension to NcML -- adding the &#039;&#039;ncoords&#039;&#039; attribute to a &#039;&#039;&#039;scan&#039;&#039;&#039; element.   The behavior of this extension is to set the &#039;&#039;ncoords&#039;&#039; for each granule matching the scan to be this value, as if the datasets were each listed explicitly with this value of the attribute.  Here&#039;s an example of using the syntactic sugar that results in the same exact aggregation as the previous explicit one:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;!-- joinExisting test on netcdf granules using scan@ncoords extension--&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinExisting test on netcdf Grid granules using scan@ncoords&amp;quot;&lt;br /&gt;
	&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&lt;br /&gt;
	     value=&amp;quot; joinExisting test on netcdf Grid granules using scan@ncoords&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinExisting&amp;quot; &lt;br /&gt;
	       dimName=&amp;quot;time&amp;quot; &amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Filenames have lexicographic and chronological ordering match --&amp;gt;&lt;br /&gt;
    &amp;lt;scan location=&amp;quot;/coverage/mday&amp;quot;&lt;br /&gt;
	  subdirs=&amp;quot;false&amp;quot;&lt;br /&gt;
	  suffix=&amp;quot;.nc&amp;quot;&lt;br /&gt;
	  ncoords=&amp;quot;1&amp;quot;&lt;br /&gt;
	  /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
which we see results in the same DDS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Float32 PHssta[time = 3][altitude = 1][lat = 4096][lon = 8192];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 3];&lt;br /&gt;
        Float64 altitude[altitude = 1];&lt;br /&gt;
        Float64 lat[lat = 4096];&lt;br /&gt;
        Float64 lon[lon = 8192];&lt;br /&gt;
    } PHssta;&lt;br /&gt;
    Float64 time[time = 3];&lt;br /&gt;
} mday_joinExist.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Limitations ==&lt;br /&gt;
&lt;br /&gt;
== Future Work ==&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=NCML_Module_Aggregation_JoinExisting&amp;diff=5789</id>
		<title>NCML Module Aggregation JoinExisting</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=NCML_Module_Aggregation_JoinExisting&amp;diff=5789"/>
		<updated>2010-09-17T17:34:39Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: New page: Category:Aggregation Category:NCML  = Join Existing Aggregation =  A &amp;#039;&amp;#039;joinExisting&amp;#039;&amp;#039; aggregation joins existing  TODO ....  The reader is also directed to a basic tutorial of this...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Aggregation]]&lt;br /&gt;
[[Category:NCML]]&lt;br /&gt;
&lt;br /&gt;
= Join Existing Aggregation =&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;joinExisting&#039;&#039; aggregation joins existing  TODO ....&lt;br /&gt;
&lt;br /&gt;
The reader is also directed to a basic tutorial of this NcML aggregation which may be found at http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Aggregation.html#joinExisting.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;PLEASE NOTE&#039;&#039;&#039; that our syntax is slightly different than that of the THREDDS Data Server (TDS), so please refer to this tutorial when using the Hyrax NcML Module!  In particular, we do not process the &amp;lt;aggregation&amp;gt; element prior to other elements in the dataset, so in some cases the relative ordering of the &amp;lt;aggregation&amp;gt; and references to variables within the aggregation matters.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
== Limitations ==&lt;br /&gt;
&lt;br /&gt;
== Future Work ==&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=BES_-_Modules_-_NcML_Module&amp;diff=5788</id>
		<title>BES - Modules - NcML Module</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=BES_-_Modules_-_NcML_Module&amp;diff=5788"/>
		<updated>2010-09-17T17:32:13Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
[[Category:NCML]]&lt;br /&gt;
[[Category:BES Modules|NCML Module]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Welcome to the OPeNDAP NcML Data Handler Module v1.1.0 for Hyrax 1.6.2!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[Updated for NcML Module v1.1.0 for Hyrax 1.6.2 Release --   15 September 2010]&lt;br /&gt;
&lt;br /&gt;
This module may be added to a Hyrax 1.6.2 server to extend its data&lt;br /&gt;
serving capability to NcML 2.2 files (see&lt;br /&gt;
http://www.unidata.ucar.edu/software/netcdf/ncml/).  NcML provides support for modifying other datasets in various ways, such as adding metadata and data and aggregating multiple datasets in several ways.&lt;br /&gt;
&lt;br /&gt;
We refer the reader to the Unidata NcML tutorial: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Tutorial.html which will give the basics of using NcML.  We then give a reference manual for the various elements and their attributes.  Additionally we have provided a more extensive tutorial on NcML aggregation.  Please see [[#Aggregation Tutorials]].&lt;br /&gt;
&lt;br /&gt;
Since the DAP Grid is a common case, we will also give a simple example for adding metadata to the various parts of a Grid dataset using NcML.  Please see [[Grid_Metadata_Tutorial]].&lt;br /&gt;
&lt;br /&gt;
==Features==         &lt;br /&gt;
   &lt;br /&gt;
This version currently implements a subset of NcML 2.2&lt;br /&gt;
functionality, along with some OPeNDAP extensions:&lt;br /&gt;
&lt;br /&gt;
* Metadata Manipulation&lt;br /&gt;
** Addition, Removal, and Modification of attributes to other datasets (NetCDF, HDF4, HD5, etc.) served by the same Hyrax 1.6 server&lt;br /&gt;
** Extends NcML 2.2 to allow for common nested &amp;quot;attribute containers&amp;quot; &lt;br /&gt;
** Attributes can be DAP2 types as well as the NcML types &lt;br /&gt;
** Attributes can be of the special &amp;quot;OtherXML&amp;quot; type for injecting arbitrary XML into a DDX response&lt;br /&gt;
* Data Manipulation&lt;br /&gt;
** Addition of new data variables (scalars or arrays of basic types as well as structures) &lt;br /&gt;
** Variables may be removed from the wrapped dataset&lt;br /&gt;
** Allows the creation of &amp;quot;pure virtual&amp;quot; datasets which do not wrap another dataset&lt;br /&gt;
* Aggregations: JoinNew, JoinExisting Union [[#Aggregation Tutorials]]&lt;br /&gt;
** JoinNew Aggregation ([[NCML_Module_Aggregation_JoinNew]])&lt;br /&gt;
*** Allows multiple datasets to be &amp;quot;joined&amp;quot; by creating a new outer dimension for the aggregated variable&lt;br /&gt;
*** Aggregation member datasets can be listed explicitly with explicit coordinates for the new dimension for each member&lt;br /&gt;
*** Scan: Aggregations can be specified &amp;quot;automatically&amp;quot; by scanning a directory for files matching certain criteria, such as a suffix or regular expression.&lt;br /&gt;
*** Metadata may be added to the new coordinate variable for the new dimension&lt;br /&gt;
** JoinExisting Aggregation ([[NCML_Module_Aggregation_JoinExisting]])&lt;br /&gt;
*** Currently requires the author to specify the &#039;&#039;ncoords&#039;&#039; attribute.&lt;br /&gt;
*** Scan may also be used with &#039;&#039;ncoords&#039;&#039; attribute for uniform sized granules&lt;br /&gt;
*** Only allows join dimension to be aggregated from granules and not overridden in NcML&lt;br /&gt;
** Union Aggregation ([[NCML_Module_Aggregation_Union]])&lt;br /&gt;
*** Merges all member datasets into one by taking the first named instance of variables and metadata from the members&lt;br /&gt;
*** Useful for combining two or more datasets with different variables into a single set&lt;br /&gt;
&lt;br /&gt;
== Installation from Source ==&lt;br /&gt;
For information on how to build and install the NcML Data Module, please see the INSTALL file that came with the source distribution.&lt;br /&gt;
&lt;br /&gt;
= Installation Overview =&lt;br /&gt;
&lt;br /&gt;
The NcML Module requires a working Hyrax 1.6 installation.  It is a module&lt;br /&gt;
that is dynamically loaded into the Hyrax BES (Back End Server) to&lt;br /&gt;
allow it to handle NcML files.  &lt;br /&gt;
&lt;br /&gt;
Please see the file INSTALL for full build and install instructions as&lt;br /&gt;
well as requirements.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; After installation, you MUST restart Hyrax by restarting the BES and&lt;br /&gt;
OLFS so the NcML Module is loaded!&lt;br /&gt;
&lt;br /&gt;
== Requirement: International Components for Unicode (ICU) Library == &lt;br /&gt;
&lt;br /&gt;
The most important external requirement is an installation of the International Components for Unicode (ICU) version 3.6 or higher (tested up to 4.2.1).   The source distributions (as well as some binaries) may be found at the site: http://site.icu-project.org/download&lt;br /&gt;
&lt;br /&gt;
If you are using Linux RPM&#039;s to run Hyrax, you can get an RPM for ICU as well.  Search for the RPM named &amp;quot;libicu&amp;quot; using a package manager or yum, e.g.   If you are compiling the module from source, you will also need the RPM &amp;quot;libicu-devel&amp;quot; to get the headers installed.  &lt;br /&gt;
&lt;br /&gt;
If you install in the default locations, the ncml_module should find the libraries and headers.  Otherwise, please consult the INSTALL file for more information about installing ICU to a non-standard location.&lt;br /&gt;
&lt;br /&gt;
== Testing Installation ==&lt;br /&gt;
&lt;br /&gt;
Test data is provided to see if the installation was successful.  The file sample_virtual_dataset.ncml is a dataset purely created in NcML and doesn&#039;t contain an underlying dataset.  &lt;br /&gt;
You may also view fnoc1_improved.ncml to test adding attributes to an existing netCDF dataset (fnoc1.nc), but this requires the netCDF data handler to be&lt;br /&gt;
installed first!  Several other examples installed also use the HDF4 and HDF5 handlers.&lt;br /&gt;
&lt;br /&gt;
= Functionality =&lt;br /&gt;
&lt;br /&gt;
This version of the NcML Module implements a subset of NcML 2.2&lt;br /&gt;
functionality.  The reader is directed to http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/ for more information on NcML.&lt;br /&gt;
&lt;br /&gt;
Our module can currently:&lt;br /&gt;
&lt;br /&gt;
*Refer only to files being served locally (not remotely)&lt;br /&gt;
*Add, modify, and remove attribute metadata to a dataset&lt;br /&gt;
*Create a purely virtual dataset using just NcML and no underlying dataset&lt;br /&gt;
*Create new scalar variables of any simple NcML type or simple DAP type&lt;br /&gt;
*Create new Structure variables (which can contain new child variables)&lt;br /&gt;
*Create new N-dimensional arrays of simple types (NcML or DAP)&lt;br /&gt;
*Remove existing variables from a wrapped dataset&lt;br /&gt;
*Rename existing variables in a wrapped dataset&lt;br /&gt;
*Name dimensions as a mnemonic for specifying Array shapes&lt;br /&gt;
*Perform union aggregations on multiple datasets, virtual or wrapped or both&lt;br /&gt;
*Perform joinNew aggregations to merge a variable across multiple datasets by creating a new outer dimension&lt;br /&gt;
*Specify aggregation member datasets by scanning directories for files matching certain criteria&lt;br /&gt;
&lt;br /&gt;
We describe each supported NcML element in detail below.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;netcdf&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;netcdf&amp;gt; element is used to define a dataset, either a wrapped dataset that is to be modified, a pure virtual dataset, or a member dataset of an aggregation.  The &amp;lt;netcdf&amp;gt; element is assumed to be the topmost node, or as a child of an aggregation element.&lt;br /&gt;
&lt;br /&gt;
=== Local vs. Remote Datasets ===&lt;br /&gt;
&lt;br /&gt;
We assume that the location attribute (&#039;&#039;netcdf@location&#039;&#039;) refers to the full path (with respect to the BES data root directory) of a &#039;&#039;&#039;&#039;&#039;local&#039;&#039;&#039;&#039;&#039; dataset (served by the same Hyrax server).  The current version of the module cannot be used to modify remote datasets.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;netcdf@location&#039;&#039; is the empty string (or unspecified, as empty is the default), the dataset is a pure virtual dataset, fully specified within the NcML file itself.  Attributes and variables may be fully described and accessed with constraints just as normal datasets in this manner.  The installed sample datafile &amp;quot;sample_virtual_dataset.ncml&amp;quot; is an example test case for this functionality.&lt;br /&gt;
&lt;br /&gt;
=== Unsupported Attributes ===&lt;br /&gt;
&lt;br /&gt;
The current version does not support the following attributes of &amp;lt;netcdf&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
*enhance&lt;br /&gt;
*addRecords&lt;br /&gt;
*fmrcDefinition (will be supported when FMRC aggregation is added)&lt;br /&gt;
*ncoords (will be supported when joinExisting is added)&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;readMetadata&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;readMetadata/&amp;gt; element is the default, so is effectively not needed.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;explicit&amp;gt; element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;explicit/&amp;gt; element simply clears all attribute tables in the referred to netcdf@location before applying the rest of the &lt;br /&gt;
NcML transformations to the metadata.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;dimension&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;dimension&amp;gt; element has limited functionality in this release since the DAP2 doesn&#039;t support dimensions as more than mnemonics at this time.  The limitations are:&lt;br /&gt;
&lt;br /&gt;
* We only parse the &#039;&#039;dimension@name&#039;&#039; and &#039;&#039;dimension@length&#039;&#039; attributes.  &lt;br /&gt;
* Dimensions can only be specified as a direct child of a &amp;lt;netcdf&amp;gt; element prior to any reference to them&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt; &lt;br /&gt;
  &amp;lt;dimension name=&amp;quot;station&amp;quot; length=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;dimension name=&amp;quot;samples&amp;quot; length=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;!-- Some variable elements refer to the dimensions here --&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The dimension element sets up a mapping from the &#039;&#039;name&#039;&#039; to the unsigned integer &#039;&#039;length&#039;&#039; and can be used in a &#039;&#039;variable@shape&#039;&#039; to specify a length for an array dimension (see the section on &amp;lt;variable&amp;gt; below).  The dimension map is cleared when &amp;lt;/netcdf&amp;gt; is encountered (though this doesn&#039;t matter currently since we allow only one right now, but it will matter for aggregation, potentially).  We also do not support &amp;lt;group&amp;gt;, which is the only other legal place in NcML 2.2 for a dimension element.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* If the name and length are not both specified.&lt;br /&gt;
* If the dimension name already exists in the current scope&lt;br /&gt;
* If the length is not an unsigned integer&lt;br /&gt;
* If any of the other attributes specified in NcML 2.2 are used.  We do not handle them, so we consider them errors now.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;variable&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;variable&amp;gt; element is used to:&lt;br /&gt;
&lt;br /&gt;
* Provide lexical scope for a contained &amp;lt;attribute&amp;gt; or &amp;lt;variable&amp;gt; element&lt;br /&gt;
* Rename existing variables &lt;br /&gt;
* Add new scalar variables of simple types&lt;br /&gt;
* Add new Structure variables&lt;br /&gt;
* Add new N-dimensional Array&#039;s of simple types&lt;br /&gt;
* Specify the coordinate variable for the new dimension in a joinNew aggregation &lt;br /&gt;
&lt;br /&gt;
We describe each in turn in more detail.&lt;br /&gt;
&lt;br /&gt;
=== Specifying Lexical Scope with &amp;lt;variable type=&amp;quot;&amp;quot;&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Consider the following example:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;variable name=&amp;quot;u&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Metadata&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;This is metadata!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code assumes that a variable named &amp;quot;u&amp;quot; exists (of any type since we do not specify) and provides the lexical scope for the&lt;br /&gt;
attribute &amp;quot;Metadata&amp;quot; which will be added or modified within the attribute table for the variable &amp;quot;u&amp;quot; (it&#039;s qualified name would be &amp;quot;u.Metadata&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
==== Nested DAP Structure and Grid Scopes ====&lt;br /&gt;
&lt;br /&gt;
Scoping variable elements may be nested if the containing variable is a Structure (this includes the special case of Grid)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;DATA_GRANULE&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;PlanetaryGrid&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;variable name=&amp;quot;percipitate&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;inches&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This adds a &amp;quot;unit&amp;quot; attribute to the variable &amp;quot;percipitate&amp;quot; within the nested Structure&#039;s &lt;br /&gt;
(&amp;quot;DATA_GRANULE.PlanetaryGrid.percipitate&amp;quot; as fully qualified name).  &lt;br /&gt;
Note that we &#039;&#039;&#039;must&#039;&#039;&#039; refer to the type explicitly as a &amp;quot;Structure&amp;quot; so the parser knows&lt;br /&gt;
to traverse the tree.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; the variable might be of type Grid, but the type &amp;quot;Structure&amp;quot; must be used in the NcML to traverse it.&lt;br /&gt;
&lt;br /&gt;
==== Adding Multiple Attributes to the Same Variable ====&lt;br /&gt;
&lt;br /&gt;
Once the variable&#039;s scope is set by the opening &amp;lt;variable&amp;gt; element, more than one attribute can be specified within it.  This will make the NcML more readable and also will make the parsing more efficient since the variable will only need to be looked up once.&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_1&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Hello&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_2&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;World!&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
should be preferred over:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_1&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Hello&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_2&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;World!&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
although they produce the same result.  Any number of attributes can be specified before the variable is closed.&lt;br /&gt;
&lt;br /&gt;
=== Renaming Existing Variables ===&lt;br /&gt;
&lt;br /&gt;
The attribute &#039;&#039;variable@orgName&#039;&#039; is used to rename an existing variable. &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;NewName&amp;quot; orgName=&amp;quot;OldName&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing variable at the current scope named &amp;quot;OldName&amp;quot; to &amp;quot;NewName&amp;quot;.  After this point in the NcML file (such as in constraints specified for the DAP request), the variable is known by &amp;quot;NewName&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note that the type is not required here --- the variable is assumed to exist and its existing type is used.  It is not possible to change the type of an existing variable at this time!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:  &lt;br /&gt;
* If a variable with &#039;&#039;variable@orgName&#039;&#039; doesn&#039;t exist in the current scope&lt;br /&gt;
* If the new name &#039;&#039;variable@name&#039;&#039; is already taken in the current scope&lt;br /&gt;
* If a new variable is created but does not have exactly one values element&lt;br /&gt;
&lt;br /&gt;
=== Adding a New Scalar Variable ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;variable&amp;gt; element can be used to create a new scalar variable of a simple type (i.e. an atomic NcML type such as &amp;quot;int&amp;quot; or &amp;quot;float&amp;quot;, or any DAP atomic type, such as &amp;quot;UInt32&amp;quot; or &amp;quot;URL&amp;quot;) by specifying an empty &#039;&#039;variable@shape&#039;&#039; (which is the default), a simple type for &#039;&#039;variable@type&#039;&#039;, and a contained &amp;lt;values&amp;gt; element with the one value of correct type. &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;TheAnswerToLifeTheUniverseAndEverything&amp;quot; type=&amp;quot;double&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;SolvedBy&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;Deep Thought&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;values&amp;gt;42.000&amp;lt;/values&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create a new variable named &amp;quot;TheAnswerToLifeTheUniverseAndEverything&amp;quot; at the current scope.  It has no shape so will be a scalar of type &amp;quot;double&amp;quot; and will have the value 42.0.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* It is a parse error to not specify a &amp;lt;values&amp;gt; element with exactly one proper value of the variable type.&lt;br /&gt;
* It is a parse error to specify a malformed or out of bounds value for the data type&lt;br /&gt;
&lt;br /&gt;
=== Adding a New Structure Variable ===&lt;br /&gt;
&lt;br /&gt;
A new Structure variable can be specified at the global scope or within another Structure.  It is illegal for an array to have type structure, so the shape must be empty.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;MyNewStructure&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;MetaData&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;This is metadata!&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;ContainedScalar1&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&amp;lt;values&amp;gt;I live in a new structure!&amp;lt;/values&amp;gt;&amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;ContainedInt1&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;&amp;lt;values&amp;gt;42&amp;lt;/values&amp;gt;&amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
specifies a new structure called &amp;quot;MyNewStructure&amp;quot; which contains two scalar variable fields &amp;quot;ContainedScalar1&amp;quot; and &amp;quot;ContainedInt1&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
Nested structures are allowed as well.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Error&#039;&#039;&#039;: &lt;br /&gt;
* If another variable or attribute exists at the current scope with the new name.  &lt;br /&gt;
* If a &amp;lt;values&amp;gt; element is specified as a direct child of a new Structure --- structures cannot contain values, only attributes and other variables.&lt;br /&gt;
&lt;br /&gt;
=== Adding a New N-dimensional Array ===&lt;br /&gt;
&lt;br /&gt;
An N-dimensional array of a simple type may be created virtually as well by specifying a non-empty &#039;&#039;variable@shape&#039;&#039;.  The shape contains the array dimensions in left-to-right order of slowest varying dimension first.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;FloatArray&amp;quot; type=&amp;quot;float&amp;quot; shape=&amp;quot;2 5&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;!-- values specified in row major order (leftmost dimension in shape varies slowest) &lt;br /&gt;
	Any whitespace is a valid separator by default, so we can use newlines to pretty print 2D matrices.&lt;br /&gt;
	--&amp;gt;&lt;br /&gt;
      &amp;lt;values&amp;gt;&lt;br /&gt;
	0.1 0.2 0.3 0.4 0.5&lt;br /&gt;
	1.1 1.1 1.3 1.4 1.5&lt;br /&gt;
      &amp;lt;/values&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will specify a 2x5 dimension array of float values called &amp;quot;FloatArray&amp;quot;.  The &amp;lt;values&amp;gt; element must contain 2x5=10 values in row major order (slowest varying dimension first).  Since whitespace is the default separator, we use a newline to show the dimension boundary for the values, which is easy to see for a 2D matrix such as this.&lt;br /&gt;
&lt;br /&gt;
A dimension name may also be used to refer mnemonically to a length.  The DAP response will use this mnemonic in its output, but it is not currently used for shared dimensions, only as a mnemonic.   See the section on the &amp;lt;dimension&amp;gt; element for more information.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt;&lt;br /&gt;
 &amp;lt;dimension name=&amp;quot;station&amp;quot; length=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;dimension name=&amp;quot;sample&amp;quot; length=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;FloatArray&amp;quot; type=&amp;quot;float&amp;quot; shape=&amp;quot;station sample&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;values&amp;gt;&lt;br /&gt;
	0.1 0.2 0.3 0.4 0.5&lt;br /&gt;
	1.1 1.1 1.3 1.4 1.5&lt;br /&gt;
      &amp;lt;/values&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will produce the same 2x5 array, but will incorporate the dimension mnemonics into the response.  For example, here&#039;s the DDS response:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
     Float32 FloatArray[station = 2][samples = 5];&lt;br /&gt;
} sample_virtual_dataset.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;values&amp;gt; element respects the &#039;&#039;values@separator&#039;&#039; attribute if whitespace isn&#039;t correct.  This is very useful for arrays of strings with whitespace, for example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;StringArray&amp;quot; type=&amp;quot;string&amp;quot; shape=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;values separator=&amp;quot;*&amp;quot;&amp;gt;String 1*String 2*String 3&amp;lt;/values&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
creates a length 3 array of string StringArray = {&amp;quot;String 1&amp;quot;, &amp;quot;String 2&amp;quot;, &amp;quot;String 3&amp;quot;}.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:  &lt;br /&gt;
* It is an error to specify the incorrect number of values&lt;br /&gt;
* It is an error if any value is malformed or out of range for the data type.&lt;br /&gt;
* It is an error to specify a named dimension which does not exist in the current &amp;lt;netcdf&amp;gt; scope.&lt;br /&gt;
* It is an error to specify an Array whose flattened size (product of dimensions) is &amp;gt; 2^31-1.&lt;br /&gt;
&lt;br /&gt;
=== Specifying the new coordinate variable for a joinNew aggregation ===&lt;br /&gt;
&lt;br /&gt;
In the special case of a joinNew aggregation, the new coordinate variable may be specified with the &amp;lt;variable&amp;gt; element.  The new coordinate variable is &#039;&#039;defined&#039;&#039; to have the same name as the new dimension.  This allows for several things:&lt;br /&gt;
&lt;br /&gt;
*Explicit specification of the variable type and coordinates for the new dimension&lt;br /&gt;
*Specification of the metadata for the new coordinate variable &lt;br /&gt;
&lt;br /&gt;
In the first case, the author can specify explicitly the type of the new coordinate variable and the actual values for each dataset.  In this case, the variable &#039;&#039;must&#039;&#039; be specified &#039;&#039;after&#039;&#039; the aggregation element in the file so the new dimension&#039;s size (number of member datasets) may be known and error checking performed.  Metadata can also be added to the variable here.&lt;br /&gt;
&lt;br /&gt;
In the second case, the author may just specify the variable name, which allows one to specify the metadata for a coordinate variable that is automatically generated by the aggregation itself.  This is the only allowable case for a variable element to &#039;&#039;not&#039;&#039; contain a values element!  Coordinate variables are generated automatically in two cases:&lt;br /&gt;
&lt;br /&gt;
*The author has specified an explicit list of member datasets, with or without explicit coordVal attributes.  &lt;br /&gt;
*The author has used a &amp;lt;scan&amp;gt; element to specify the member datasets via a directory scan&lt;br /&gt;
&lt;br /&gt;
In this case, the &amp;lt;variable&amp;gt; element may come before or after the &amp;lt;aggregation&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*If an explicit variable is declared for the new coordinate variable:&lt;br /&gt;
** And it contains explicit values, the number of values must be equal to the number of member datasets in the aggregation.&lt;br /&gt;
** It must be specifed &#039;&#039;after&#039;&#039; the &amp;lt;aggregation&amp;gt; element&lt;br /&gt;
&lt;br /&gt;
* If a numeric coordVal is used to specify the first member dataset&#039;s coordinate, then &#039;&#039;all&#039;&#039; datasets must contain a numerical coordinate.&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variable (variableAgg) is not found in &#039;&#039;all&#039;&#039; member datasets.&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variable is not of the same type in &#039;&#039;all&#039;&#039; member datasets.  Coercion is &#039;&#039;not&#039;&#039; performed!&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variables in all member datasets do not have the same shape&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if an explicit coordinate variable is specified with a shape that is &#039;&#039;not&#039;&#039; the same as the new dimension name (and the variable name itself).&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;values&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;values&amp;gt; element can only be used in the context of a &#039;&#039;&#039;new&#039;&#039;&#039; variable of scalar or array type.  We cannot change the values for existing variables in this version of the handler. &lt;br /&gt;
The characters content of a &amp;lt;values&amp;gt; element is considered to be a separated list of value tokens valid for the type of the variable of the parent element.  The number of specified tokens in the content &#039;&#039;must&#039;&#039; equal the product of the dimensions of the enclosing &#039;&#039;variable@shape&#039;&#039;, or be one value for a scalar.  It is an error to &#039;&#039;not&#039;&#039; specify a &amp;lt;values&amp;gt; element for a declared new variable as well.  &lt;br /&gt;
&lt;br /&gt;
=== Changing the Separator Tokens === &lt;br /&gt;
&lt;br /&gt;
The author may specify values@separator to change the default value token separator from the default whitespace.  This is very useful for specifying arrays of strings with whitespace in them, or if data in CSV form is being pasted in.  &lt;br /&gt;
&lt;br /&gt;
=== Autogeneration of Uniform Arrays ===&lt;br /&gt;
&lt;br /&gt;
We also can parse &#039;&#039;values@start&#039;&#039; and &#039;&#039;values@increment&#039;&#039; INSTEAD OF tokens in the content.  This will &amp;quot;autogenerate&amp;quot; a uniform array of values of the given product of dimensions length for the containing variable.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Evens&amp;quot; type=&amp;quot;int&amp;quot; shape=&amp;quot;100&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;values start=&amp;quot;0&amp;quot; increment=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will specify an array of the first 100 even numbers (including 0).  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* If the incorrect number of tokens are specified for the containing variable&#039;s shape&lt;br /&gt;
* If any value token cannot be parsed as a valid value for the containing variable&#039;s type&lt;br /&gt;
* If content is specified in addition to start and increment&lt;br /&gt;
* If only one of start or increment is specified&lt;br /&gt;
* If the values element is placed anywhere except within a NEW variable.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;attribute&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
As an overview, whenever the parser encounters an &amp;lt;attribute&amp;gt; with a non-existing name (at the current scope),&lt;br /&gt;
it creates a new one, whether a container or atomic attribute (see below).  If the attribute exists,&lt;br /&gt;
its value and/or type is modified to those specified in the &amp;lt;attribute&amp;gt; element.  If an attribute&lt;br /&gt;
structure (container) exists, it is used to define a nested lexical scope for child attributes.  &lt;br /&gt;
&lt;br /&gt;
Attributes may be scalar (one value) or one dimensional arrays.  Arrays are specified by using whitespace (default) to separate the different values.  The attribute@separator may also be set in order to specify a different separator, such as CSV format or to specify a non-whitespace separator so strings with whitespace are not tokenized.  We will give examples of creating array attributes below.&lt;br /&gt;
&lt;br /&gt;
=== Adding New Attributes or Modifying an Existing Attribute ===&lt;br /&gt;
&lt;br /&gt;
If a specified attribute with the attribute@name does not exist at the current lexical scope, &lt;br /&gt;
a new one is created with the given type and value.  For example, assume &amp;quot;new_metadata&amp;quot; doesn&#039;t&lt;br /&gt;
exist at the current parse scope.  Then:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;new_metadata&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;This is a new entry!&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create the attribute at that scope.  Note that value can be specified in the content of the &lt;br /&gt;
element as well.  This is identical to the above:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;new_metadata&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;This is a new entry!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the attribute@name already exists at the scope, it is modified to contain the specified type and value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Arrays ====&lt;br /&gt;
&lt;br /&gt;
As in NcML, for numerical types an array can be specified by separating the tokens by whitespace (default) or be&lt;br /&gt;
specifying the token separator with attribute@separator.  For example,&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;myArray&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 2 3&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;myArray&amp;quot; type=&amp;quot;int&amp;quot; separator=&amp;quot;,&amp;quot;&amp;gt;1,2,3&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
both specify the same array of three integers named &amp;quot;myArray&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
TODO Add more information on splitting with a separator!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Structures (Containers) ====&lt;br /&gt;
&lt;br /&gt;
We use attribute@type=&amp;quot;Structure&amp;quot; to define a new (or existing) attribute container.   So if we&lt;br /&gt;
wanted to add a new attribute structure, we&#039;d use something like this: &lt;br /&gt;
&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;MySamples&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Location&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Station 1&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Samples&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 4 6&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assuming &amp;quot;MySamples&amp;quot; doesn&#039;t already exist, an attribute container will be created at the current scope&lt;br /&gt;
and the &amp;quot;Location&amp;quot; and &amp;quot;Samples&amp;quot; attributes will be added to it.&lt;br /&gt;
&lt;br /&gt;
Note that we can create nested attribute structures to arbitrary depth this way as well.&lt;br /&gt;
&lt;br /&gt;
If the attribute container with the given name already exists at the current scope, &lt;br /&gt;
then the attribute@type=&amp;quot;Structure&amp;quot; form is used to define&lt;br /&gt;
the lexical scope for the container.  In other words, child &amp;lt;attribute&amp;gt; elements will&lt;br /&gt;
be processed within the scope of the container.   For example, in the above example, if&lt;br /&gt;
&amp;quot;MySamples&amp;quot; already exists, then the &amp;quot;Location&amp;quot; and &amp;quot;Samples&amp;quot; will be processed within the&lt;br /&gt;
existing container (they may or may not already exist as well).&lt;br /&gt;
&lt;br /&gt;
==== Renaming an Existing Attribute or Attribute Container ====&lt;br /&gt;
&lt;br /&gt;
We also support the attribute@orgName attribute for renaming attributes.   &lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;NewName&amp;quot; orgName=&amp;quot;OldName&amp;quot; type=&amp;quot;string&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing attribute &amp;quot;OldName&amp;quot; to &amp;quot;NewName&amp;quot; while leaving its value alone.&lt;br /&gt;
If attribute@value is also specified, then the attribute is renamed &#039;&#039;and&#039;&#039; has its value modified.&lt;br /&gt;
&lt;br /&gt;
This works for renaming attribute containers as well:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;MyNewContainer&amp;quot; orgName=&amp;quot;MyOldContainer&amp;quot; type=&amp;quot;Structure&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing &amp;quot;MyOldContainer&amp;quot; to &amp;quot;MyNewContainer&amp;quot;.  Note that any children&lt;br /&gt;
of this container will remain in it.&lt;br /&gt;
&lt;br /&gt;
=== DAP &#039;&#039;OtherXML&#039;&#039; Extension ===&lt;br /&gt;
&lt;br /&gt;
The module now allows specification of attributes of the new DAP type &amp;quot;OtherXML&amp;quot;.  This allows the NCML file author to inject arbitrary well-formed XML into an attribute for clients that want XML metadata rather than just string or url.  Internally, the attribute is still a string (and in a DAP DAS response will be quoted inside one string).  However, since it is XML, the NCMLParser still parses it and checks it for well-formedness (but NOT against schemas).  This extension allows the NCMLParser to parse the arbitrary XML within the given attribute without causing errors, since it can be any XML.  &lt;br /&gt;
&lt;br /&gt;
The injected XML is most useful in the DDX response, where it shows up directly in the response as XML.  XSLT and other clients can then parse it.&lt;br /&gt;
&lt;br /&gt;
==== Errors ====&lt;br /&gt;
&lt;br /&gt;
*The XML &#039;&#039;&#039;must&#039;&#039;&#039; be in the content of the &amp;lt;attribute type=&amp;quot;OtherXML&amp;quot;&amp;gt; element.  It is a parser error for &#039;&#039;attribute@value&#039;&#039; to be set if &#039;&#039;attribute@type&#039;&#039; is &amp;quot;OtherXML&amp;quot;.  &lt;br /&gt;
*The XML must also be well-formed since it is parsed.  A parse error will be thrown if the OtherXML is malformed.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of the use of this special case.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf xmlns=&amp;quot;http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2&amp;quot; location=&amp;quot;/coverage/200803061600_HFRadar_USEGC_6km_rtv_SIO.nc&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;someName&amp;quot; type=&amp;quot;OtherXML&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;Domain xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot; &lt;br /&gt;
                xmlns:ows=&amp;quot;http://www.opengis.net/ows/1.1&amp;quot;&lt;br /&gt;
                xmlns:gml=&amp;quot;http://www.opengis.net/gml/3.2&amp;quot;&lt;br /&gt;
                &amp;gt;&lt;br /&gt;
            &amp;lt;SpatialDomain&amp;gt;&lt;br /&gt;
                &amp;lt;ows:BoundingBox crs=&amp;quot;urn:ogc:def:crs:EPSG::4326&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;ows:LowerCorner&amp;gt;-97.8839 21.736&amp;lt;/ows:LowerCorner&amp;gt;&lt;br /&gt;
                    &amp;lt;ows:UpperCorner&amp;gt;-57.2312 46.4944&amp;lt;/ows:UpperCorner&amp;gt;&lt;br /&gt;
                &amp;lt;/ows:BoundingBox&amp;gt;&lt;br /&gt;
            &amp;lt;/SpatialDomain&amp;gt;&lt;br /&gt;
            &amp;lt;TemporalDomain&amp;gt;&lt;br /&gt;
                &amp;lt;gml:timePosition&amp;gt;2008-03-27T16:00:00.000Z&amp;lt;/gml:timePosition&amp;gt;&lt;br /&gt;
            &amp;lt;/TemporalDomain&amp;gt;&lt;br /&gt;
        &amp;lt;/Domain&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedCRS xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;urn:ogc:def:crs:EPSG::4326&amp;lt;/SupportedCRS&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedFormat xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;netcdf-cf1.0&amp;lt;/SupportedFormat&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedFormat xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;dap2.0&amp;lt;/SupportedFormat&amp;gt;&lt;br /&gt;
    &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039; Put the DDX response for the above in here!&lt;br /&gt;
&lt;br /&gt;
====Namespace Closure====&lt;br /&gt;
&lt;br /&gt;
Furthermore, the parser will make the chunk of OtherXML &amp;quot;namespace closed&amp;quot;.  This means any namespaces specified in parent NCML elements of the OtherXML tree will be &amp;quot;brought down&amp;quot; and added to the &#039;&#039;root&#039;&#039; OtherXML elements so that the subtree may be pulled out and added to the DDX and still have its namespaces.  The algorithm doesn&#039;t just bring used prefixes, but brings &#039;&#039;all&#039;&#039; of the lexically scoped closest namespaces in all ancestors.  In other words, it adds unique namespaces (as determined by prefix) in order from the root of the OtherXML tree as it traverses to the root of the NCML document.  &lt;br /&gt;
&lt;br /&gt;
Namespace closure is a syntactic sugar that simplifies the author&#039;s task since they can specify the namespaces just once at the top of the NCML file and expect that when the subtree of XML is added to the DDX that these namespaces will come along with that subtree of XML.  Otherwise they have to explicitly add the namespaces to each attributes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039; Add an example!&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;remove&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;remove&amp;gt; element can remove attributes and variables.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;attribute name=&amp;quot;NC_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;remove name=&amp;quot;base_time&amp;quot; type=&amp;quot;attribute&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will remove the attribute named &amp;quot;base_time&amp;quot; in the attribute structure named &amp;quot;NC_GLOBAL&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Note that this works for attribute containers as well!  We could recursively remove the &#039;&#039;entire&#039;&#039;&lt;br /&gt;
attribute container (i.e. it and all its children) with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;remove name=&amp;quot;NC_GLOBAL&amp;quot; type=&amp;quot;attribute&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It also can be used to remove variables from existing datasets:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
  &amp;lt;remove name=&amp;quot;SomeExistingVariable&amp;quot; type=&amp;quot;variable&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This also recurses on variables of type Structure --- the entire structure including all of its children are removed from the dataset&#039;s response.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* It is a parse error if the given attribute or variable doesn&#039;t exist in the current scope&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;aggregation&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
Aggregation involves combining multiple datasets (&amp;lt;netcdf&amp;gt;) into a virtual &amp;quot;single&amp;quot; dataset in various ways.  For a tutorial on aggregation in NcML 2.2, the reader is referred to the Unidata page: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Aggregation.html&lt;br /&gt;
&lt;br /&gt;
NcML 2.2 supports multiple types of aggregation: union, joinNew, joinExisting, and fmrc (forecast model run collection).  &lt;br /&gt;
&lt;br /&gt;
The current version of the NcML module supports two of these aggregations:&lt;br /&gt;
&lt;br /&gt;
*Union [[NCML_Module_Aggregation_Union]]&lt;br /&gt;
*JoinNew [[NCML_Module_Aggregation_JoinNew]]&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;union&#039;&#039; aggregation specifies that the first instance of a variable or attribute (by name) that is found in the ordered list of datasets will be the one in the output aggregation.   This is useful for combining two dataset files, each which may contain a single variable, into a composite dataset with both variables.&lt;br /&gt;
&lt;br /&gt;
A JoinNew aggregation joins a variable which exists in multiple datasets (usually samples of a datum over time) into a new variable containing the data from &#039;&#039;all&#039;&#039; member datasets by creating a new outer dimension.  The &#039;&#039;i&#039;&#039;th component in the new outer dimension is the variable&#039;s data from the &#039;&#039;i&#039;&#039;th member dataset.  It also adds a new coordinate variable of whose name is the new dimension&#039;s name and whose shape (length) is the new dimension as well.  This new coordinate variable may be explicitly given by the author or may be autogenerated in one of several ways.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;scan&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The scan element can be used within an aggregation context to allow a directory to be searched in various ways in order to specify the members of an aggregation.  This allows a static NcML file to refer to an aggregation which may change over time, such as where a new data file is generated each day.&lt;br /&gt;
&lt;br /&gt;
We describe usage of the &amp;lt;scan&amp;gt; element in detail in the joinNew aggregation tutorial at [[NCML_Module_Aggregation_JoinNew]].&lt;br /&gt;
&lt;br /&gt;
= Errors =&lt;br /&gt;
&lt;br /&gt;
There are three types of error messages that may be returned:&lt;br /&gt;
&lt;br /&gt;
* Internal Error&lt;br /&gt;
* Resource Not Found Error&lt;br /&gt;
* Parse Error&lt;br /&gt;
&lt;br /&gt;
== Internal Errors ==&lt;br /&gt;
&#039;&#039;&#039;Internal errors&#039;&#039;&#039; should be reported to support@opendap.org as they are likely bugs.&lt;br /&gt;
&lt;br /&gt;
== Resource Not Found Errors ==&lt;br /&gt;
&lt;br /&gt;
If the netcdf@location specifies a non-existent local dataset (one that is not being served by&lt;br /&gt;
the same Hyrax server), it will specify the resource was not found.   This may also be returned&lt;br /&gt;
if a handler for the specified dataset is not currently loaded in the BES.  Users should test that the&lt;br /&gt;
dataset to be wrapped already exists and can be viewed on the running server before writing NcML &lt;br /&gt;
to add metadata.  It&#039;s also an error to refer to remote datasets (at this time).&lt;br /&gt;
&lt;br /&gt;
== Parse Errors ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse errors&#039;&#039;&#039; are user errors in the NcML file.  These could be malformed XML, malformed NcML, &lt;br /&gt;
unimplemented features of NcML, or could be errors in referring to the wrapped dataset.  &lt;br /&gt;
&lt;br /&gt;
The error message should specify &lt;br /&gt;
the error condition as well as the &amp;quot;current scope&amp;quot; as a fully qualified DAP name within the &lt;br /&gt;
loaded dataset.  This should be enough information to correct the parse error as new NcML&lt;br /&gt;
files are created.&lt;br /&gt;
&lt;br /&gt;
The parser will generate parse errors in various &lt;br /&gt;
situations where it expects to find certain structure in the underlying dataset.  Some examples:&lt;br /&gt;
&lt;br /&gt;
* A variable of the given name was not found at the current scope&lt;br /&gt;
* attribute@orgName was specified, but the attribute cannot be found at current scope.&lt;br /&gt;
* attribute@orgName was specified, but the new name is already used at current scope.&lt;br /&gt;
* remove specified a non-existing attribute name&lt;br /&gt;
&lt;br /&gt;
= Grid Metadata Tutorial =&lt;br /&gt;
&lt;br /&gt;
Please see the page [[Grid_Metadata_Tutorial]] for an example of adding metadata to the various parts of a DAP Grid variable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Aggregation Tutorials =&lt;br /&gt;
&lt;br /&gt;
The NcML module may also be used to aggregate multiple datasets into one virtual dataset.  We currently support two of the NcML aggregtions:&lt;br /&gt;
&lt;br /&gt;
*Union [[NCML_Module_Aggregation_Union]]:  combine multiple datasets into one by merging variables together, selecting the first of each unique name.&lt;br /&gt;
*JoinNew [[NCML_Module_Aggregation_JoinNew]]: combine variables across multiple datasets by creating a new outer dimension and coordinate variable for each of the sample datasets.&lt;br /&gt;
&lt;br /&gt;
Please see the sections for a tutorial on the various uses of these aggregations.&lt;br /&gt;
&lt;br /&gt;
= Additions/Changes to NcML 2.2 =&lt;br /&gt;
&lt;br /&gt;
This section will keep track of changes to the NcML 2.2 schema.  Eventually these&lt;br /&gt;
will be rolled into a new schema.&lt;br /&gt;
&lt;br /&gt;
== Attribute Structures (Containers) ==&lt;br /&gt;
This module also adds functionality beyond the current NcML 2.2 schema&lt;br /&gt;
--- it can handle nested &amp;lt;attribute&amp;gt; elements in order to make&lt;br /&gt;
attribute structures.  This is done by using the &amp;lt;attribute&lt;br /&gt;
type=&amp;quot;Structure&amp;quot;&amp;gt; form, for example:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;MySamples&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Location&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Station 1&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Samples&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 4 6&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;MyContainer&amp;quot; describes an attribute structure with two attribute fields,&lt;br /&gt;
a string &amp;quot;Location&amp;quot; and an array of int&#039;s called &amp;quot;Samples&amp;quot;.  &lt;br /&gt;
Note that an attribute structure of this form can&lt;br /&gt;
only contain other &amp;lt;attribute&amp;gt; elements and NOT a value.&lt;br /&gt;
&lt;br /&gt;
If the container does not already exist, it will be created at the scope it is declared, which could&lt;br /&gt;
be:&lt;br /&gt;
&lt;br /&gt;
* Global (top of dataset)&lt;br /&gt;
* Within a variable&#039;s attribute table&lt;br /&gt;
* Within another attribute container&lt;br /&gt;
&lt;br /&gt;
If an attribute container of the given name already exists at the lexical scope, it is traversed &lt;br /&gt;
in order to define the scope for the nested (children) attributes it contains.&lt;br /&gt;
&lt;br /&gt;
== Unspecified Variable Type Matching for Lexical Scope ==&lt;br /&gt;
&lt;br /&gt;
We also allow the type attribute of a variable element (variable@type) to be the empty string &lt;br /&gt;
(or unspecified) when using existing variables to define the lexical scope of an &amp;lt;attribute&amp;gt; &lt;br /&gt;
transformation.  In the schema, variable@type is (normally) required.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DAP 2 Types ==&lt;br /&gt;
&lt;br /&gt;
Additionally, we allow DAP2 atomic types (such as UInt32, URL) in addition to the NcML types.  &lt;br /&gt;
The NcML types are mapped onto the closest DAP2 type internally.&lt;br /&gt;
&lt;br /&gt;
== DAP OtherXML Attribute Type ==&lt;br /&gt;
&lt;br /&gt;
We also allow attributes to be of the new DAP type &amp;quot;OtherXML&amp;quot; for injecting arbitrary XML into an attribute as content rather than trying to form a string.  This allows the parser to check well-formedness.&lt;br /&gt;
&lt;br /&gt;
== Forward Declaration of Dimensions ==&lt;br /&gt;
&lt;br /&gt;
Since we use a SAX parser for efficiency, we require the &amp;lt;dimension&amp;gt; elements to come &#039;&#039;before&#039;&#039; their use in a &#039;&#039;variable@shape&#039;&#039;.  One way to change the schema to allow this is to force the dimension elements to be specified in a sequence after explicit and metadata choice and before all other elements.&lt;br /&gt;
&lt;br /&gt;
== Aggregation Element Location and Processing Order Differences ==&lt;br /&gt;
&lt;br /&gt;
NcML specifies that if a dataset (&amp;lt;netcdf&amp;gt; element) specifies an aggregation element, the aggregation element is always processed first, regardless of its ordering within the &amp;lt;netcdf&amp;gt; element.  Our parser, since it is SAX and not DOM, modifies this behavior in that order matters in some cases:&lt;br /&gt;
&lt;br /&gt;
* Metadata (&amp;lt;attribute&amp;gt;) elements specified &#039;&#039;prior&#039;&#039; to an aggregation &amp;quot;shadow&amp;quot; the aggregation versions.  This is be useful for &amp;quot;overriding&amp;quot; an attribute or variable in a union aggregation, where the first found will take precedence. &lt;br /&gt;
* JoinNew: If the new coordinate variable&#039;s data is to be set explicitly by specifying the new dimension&#039;s shape (either with explicit data or the autogenerated data using values@start and values@increment attributes), the &amp;lt;variable&amp;gt; &#039;&#039;must&#039;&#039; come after the aggregation since the size of the dimension is unknown until the aggregation element is processed.&lt;br /&gt;
&lt;br /&gt;
= Backward Compatibility Issues =&lt;br /&gt;
&lt;br /&gt;
Due to the way shared dimensions were implemented in the NetCDF, HDF4, and HDF5 handlers, the DAS responses did not follow the DAP2 specification.  The NcML module, on the other hand, generates DAP2 compliant DAS for these datasets, which means that wrapping some datasets in NcML will generate a DAS with a different structure.  This is important for the NcML author since it changes the names of attributes and variables.  In order for the module to find the correct scope for adding metadata, for example, the DAP2 DAS must be used.  &lt;br /&gt;
&lt;br /&gt;
In general, what this means is that an empty &amp;quot;passthrough&amp;quot; NcML file should be the starting point for authoring an NcML file.  This file would just specify a dataset and nothing else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;/data/ncml/myNetcdf.nc&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The author would then request the DAS response for the NCML file and use that as the starting point for modifications to the original dataset. &lt;br /&gt;
&lt;br /&gt;
More explicit examples are given below.&lt;br /&gt;
&lt;br /&gt;
== NetCDF ==&lt;br /&gt;
&lt;br /&gt;
The NetCDF handler represents some NC datasets as a DAP 2 Grid, but the returned DAS is not consistent with the DAP 2 spec for the attribute hierarchy for such a Grid.  The map vector attributes are placed as siblings of the grid attributes rather than within the grid lexical scope.  For example, here&#039;s the NetCDF Handler DDS for a given file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Int16 cldc[time = 456][lat = 21][lon = 360];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 456];&lt;br /&gt;
        Float32 lat[lat = 21];&lt;br /&gt;
        Float32 lon[lon = 360];&lt;br /&gt;
    } cldc;&lt;br /&gt;
} cldc.mean.nc;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
showing the Grid.  Here&#039;s the DAS the NetCDF handler generates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    lat {&lt;br /&gt;
        String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
        String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
        Float32 actual_range 10.00000000, -10.00000000;&lt;br /&gt;
    }&lt;br /&gt;
    lon {&lt;br /&gt;
        String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
        String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
        Float32 actual_range 0.5000000000, 359.5000000;&lt;br /&gt;
    }&lt;br /&gt;
    time {&lt;br /&gt;
        String units &amp;quot;days since 1-1-1 00:00:0.0&amp;quot;;&lt;br /&gt;
        String long_name &amp;quot;Time&amp;quot;;&lt;br /&gt;
        String delta_t &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
        String avg_period &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
        Float64 actual_range 715511.00000000000, 729360.00000000000;&lt;br /&gt;
    }&lt;br /&gt;
    cldc {&lt;br /&gt;
        Float32 valid_range 0.000000000, 8.000000000;&lt;br /&gt;
        Float32 actual_range 0.000000000, 8.000000000;&lt;br /&gt;
        String units &amp;quot;okta&amp;quot;;&lt;br /&gt;
        Int16 precision 1;&lt;br /&gt;
        Int16 missing_value 32766;&lt;br /&gt;
        Int16 _FillValue 32766;&lt;br /&gt;
        String long_name &amp;quot;Cloudiness Monthly Mean at Surface&amp;quot;;&lt;br /&gt;
        String dataset &amp;quot;COADS 1-degree Equatorial Enhanced\\012AI&amp;quot;;&lt;br /&gt;
        String var_desc &amp;quot;Cloudiness\\012C&amp;quot;;&lt;br /&gt;
        String level_desc &amp;quot;Surface\\0120&amp;quot;;&lt;br /&gt;
        String statistic &amp;quot;Mean\\012M&amp;quot;;&lt;br /&gt;
        String parent_stat &amp;quot;Individual Obs\\012I&amp;quot;;&lt;br /&gt;
        Float32 add_offset 3276.500000;&lt;br /&gt;
        Float32 scale_factor 0.1000000015;&lt;br /&gt;
    }&lt;br /&gt;
    NC_GLOBAL {&lt;br /&gt;
        String title &amp;quot;COADS 1-degree Equatorial Enhanced&amp;quot;;&lt;br /&gt;
        String history &amp;quot;&amp;quot;;&lt;br /&gt;
        String Conventions &amp;quot;COARDS&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    DODS_EXTRA {&lt;br /&gt;
        String Unlimited_Dimension &amp;quot;time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the map vector attributes are in the &amp;quot;dataset&amp;quot; scope.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the DAS that the NcML Module produces from the correctly formed DDX:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    NC_GLOBAL {&lt;br /&gt;
        String title &amp;quot;COADS 1-degree Equatorial Enhanced&amp;quot;;&lt;br /&gt;
        String history &amp;quot;&amp;quot;;&lt;br /&gt;
        String Conventions &amp;quot;COARDS&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    DODS_EXTRA {&lt;br /&gt;
        String Unlimited_Dimension &amp;quot;time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    cldc {&lt;br /&gt;
        Float32 valid_range 0.000000000, 8.000000000;&lt;br /&gt;
        Float32 actual_range 0.000000000, 8.000000000;&lt;br /&gt;
        String units &amp;quot;okta&amp;quot;;&lt;br /&gt;
        Int16 precision 1;&lt;br /&gt;
        Int16 missing_value 32766;&lt;br /&gt;
        Int16 _FillValue 32766;&lt;br /&gt;
        String long_name &amp;quot;Cloudiness Monthly Mean at Surface&amp;quot;;&lt;br /&gt;
        String dataset &amp;quot;COADS 1-degree Equatorial Enhanced\\012AI&amp;quot;;&lt;br /&gt;
        String var_desc &amp;quot;Cloudiness\\012C&amp;quot;;&lt;br /&gt;
        String level_desc &amp;quot;Surface\\0120&amp;quot;;&lt;br /&gt;
        String statistic &amp;quot;Mean\\012M&amp;quot;;&lt;br /&gt;
        String parent_stat &amp;quot;Individual Obs\\012I&amp;quot;;&lt;br /&gt;
        Float32 add_offset 3276.500000;&lt;br /&gt;
        Float32 scale_factor 0.1000000015;&lt;br /&gt;
        cldc {&lt;br /&gt;
        }&lt;br /&gt;
        time {&lt;br /&gt;
            String units &amp;quot;days since 1-1-1 00:00:0.0&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;Time&amp;quot;;&lt;br /&gt;
            String delta_t &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
            String avg_period &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
            Float64 actual_range 715511.00000000000, 729360.00000000000;&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
            Float32 actual_range 10.00000000, -10.00000000;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
            Float32 actual_range 0.5000000000, 359.5000000;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here the Grid Structure &amp;quot;cldc&amp;quot;  and its contained data array (of the same name &amp;quot;cldc&amp;quot;) and map vectors have their own attribute containers as DAP 2 specifies.&lt;br /&gt;
&lt;br /&gt;
What this means for the author of an NcML file adding metadata to a NetCDF dataset that returns a Grid is that they should generate a &amp;quot;passthrough&amp;quot; file and get the DAS and then specify modifications based on that structure.  &lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example passthrough:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/cldc.mean.nc&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For example, to add an attribute to the map vector &amp;quot;lat&amp;quot; in the above, we&#039;d need the following NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/cldc.mean.nc&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;!-- Traverse into the Grid as a Structure --&amp;gt;&lt;br /&gt;
  &amp;lt;variable name=&amp;quot;cldc&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Traverse into the &amp;quot;lat&amp;quot; map vector (Array) --&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lat&amp;quot;&amp;gt; &lt;br /&gt;
      &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;I am a new attribute in the Grid map vector named lat!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lon&amp;quot;&amp;gt; &lt;br /&gt;
      &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;I am a new attribute in the Grid map vector named lon!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This clearly shows that the structure of the Grid must be used in the NcML:  the attribute being added is technically &amp;quot;cldc.lat.Description&amp;quot; in a fully qualified name.  The parser would return an error if it was attempted as &amp;quot;lat.Description&amp;quot; as the NetCDF DAS for the original file would have led one to believe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== HDF4/HDF5 ==&lt;br /&gt;
&lt;br /&gt;
Similarly to the NetCDF case, the Hyrax HDF4 Module produces DAS responses that do not respect the DAP2 specification.  If an NcML file is used to &amp;quot;wrap&amp;quot; an HDF4 dataset, the&lt;br /&gt;
correct DAP2 DAS response will be generated, however. &lt;br /&gt;
&lt;br /&gt;
This is important for those writing NcML for HDF4 data since the&lt;br /&gt;
lexical scope for attributes relies on the correct DAS form --- to&lt;br /&gt;
handle this, the user should start with a &amp;quot;passthrough&amp;quot; NcML file (see the above NetCDF example) and&lt;br /&gt;
use the DAS from that as the starting point for knowing the structure&lt;br /&gt;
the NcML handler expects to see in the NcML file.  Alternatively, the DDX has the &lt;br /&gt;
proper attribute structure as well (the DAS is generated from it).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Known Bugs =&lt;br /&gt;
&lt;br /&gt;
There are no known bugs currently.&lt;br /&gt;
&lt;br /&gt;
= Planned Future Enhancements =&lt;br /&gt;
&lt;br /&gt;
Planned enhancements for future versions of the module include:&lt;br /&gt;
&lt;br /&gt;
* New NcML Aggregations&lt;br /&gt;
** JoinExisting&lt;br /&gt;
*** Joins a variable across multiple datasets by appending the data for a given dimension from each dataset &lt;br /&gt;
*** Will also allow directory scans for specifying the aggregation&lt;br /&gt;
** Forecast Model Run Collection (FMRC)&lt;br /&gt;
*** Special case of JoinNew for forecast data with two time variables&lt;br /&gt;
*** See: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/FmrcAggregation.html&lt;br /&gt;
&lt;br /&gt;
= Copyright =&lt;br /&gt;
&lt;br /&gt;
This software is copyrighted under the GNU Lesser GPL.  Please see the&lt;br /&gt;
files COPYING and COPYRIGHT that came with this distribution.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=BES_-_Modules_-_NcML_Module&amp;diff=5753</id>
		<title>BES - Modules - NcML Module</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=BES_-_Modules_-_NcML_Module&amp;diff=5753"/>
		<updated>2010-07-09T17:17:00Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
[[Category:NCML]]&lt;br /&gt;
[[Category:BES Modules|NCML Module]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Welcome to the OPeNDAP NcML Data Handler Module v1.0.3 for Hyrax 1.6!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[Updated for NcML Module v1.0.3 for Hyrax 1.6.1 Release --   9 July 2010]&lt;br /&gt;
&lt;br /&gt;
This module may be added to a Hyrax 1.6 server to extend its data&lt;br /&gt;
serving capability to NcML 2.2 files (see&lt;br /&gt;
http://www.unidata.ucar.edu/software/netcdf/ncml/).  NcML provides support for modifying other datasets in various ways, such as adding metadata and data and aggregating multiple datasets in several ways.&lt;br /&gt;
&lt;br /&gt;
We refer the reader to the Unidata NcML tutorial: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Tutorial.html which will give the basics of using NcML.  We then give a reference manual for the various elements and their attributes.  Additionally we have provided a more extensive tutorial on NcML aggregation.  Please see [[#Aggregation Tutorials]].&lt;br /&gt;
&lt;br /&gt;
Since the DAP Grid is a common case, we will also give a simple example for adding metadata to the various parts of a Grid dataset using NcML.  Please see [[Grid_Metadata_Tutorial]].&lt;br /&gt;
&lt;br /&gt;
==Features==         &lt;br /&gt;
   &lt;br /&gt;
This version currently implements a subset of NcML 2.2&lt;br /&gt;
functionality, along with some OPeNDAP extensions:&lt;br /&gt;
&lt;br /&gt;
* Metadata Manipulation&lt;br /&gt;
** Addition, Removal, and Modification of attributes to other datasets (NetCDF, HDF4, HD5, etc.) served by the same Hyrax 1.6 server&lt;br /&gt;
** Extends NcML 2.2 to allow for common nested &amp;quot;attribute containers&amp;quot; &lt;br /&gt;
** Attributes can be DAP2 types as well as the NcML types &lt;br /&gt;
** Attributes can be of the special &amp;quot;OtherXML&amp;quot; type for injecting arbitrary XML into a DDX response&lt;br /&gt;
* Data Manipulation&lt;br /&gt;
** Addition of new data variables (scalars or arrays of basic types as well as structures) &lt;br /&gt;
** Variables may be removed from the wrapped dataset&lt;br /&gt;
** Allows the creation of &amp;quot;pure virtual&amp;quot; datasets which do not wrap another dataset&lt;br /&gt;
* Aggregations: JoinNew and Union [[#Aggregation Tutorials]]&lt;br /&gt;
** JoinNew Aggregation ([[NCML_Module_Aggregation_JoinNew]])&lt;br /&gt;
*** Allows multiple datasets to be &amp;quot;joined&amp;quot; by creating a new outer dimension for the aggregated variable&lt;br /&gt;
*** Aggregation member datasets can be listed explicitly with explicit coordinates for the new dimension for each member&lt;br /&gt;
*** Scan: Aggregations can be specified &amp;quot;automatically&amp;quot; by scanning a directory for files matching certain criteria, such as a suffix or regular expression.&lt;br /&gt;
*** Metadata may be added to the new coordinate variable for the new dimension&lt;br /&gt;
** Union Aggregation ([[NCML_Module_Aggregation_Union]])&lt;br /&gt;
*** Merges all member datasets into one by taking the first named instance of variables and metadata from the members&lt;br /&gt;
*** Useful for combining two or more datasets with different variables into a single set&lt;br /&gt;
&lt;br /&gt;
== Installation from Source ==&lt;br /&gt;
For information on how to build and install the NcML Data Module, please see the INSTALL file that came with the source distribution.&lt;br /&gt;
&lt;br /&gt;
= Installation Overview =&lt;br /&gt;
&lt;br /&gt;
The NcML Module requires a working Hyrax 1.6 installation.  It is a module&lt;br /&gt;
that is dynamically loaded into the Hyrax BES (Back End Server) to&lt;br /&gt;
allow it to handle NcML files.  &lt;br /&gt;
&lt;br /&gt;
Please see the file INSTALL for full build and install instructions as&lt;br /&gt;
well as requirements.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; After installation, you MUST restart Hyrax by restarting the BES and&lt;br /&gt;
OLFS so the NcML Module is loaded!&lt;br /&gt;
&lt;br /&gt;
== Requirement: International Components for Unicode (ICU) Library == &lt;br /&gt;
&lt;br /&gt;
The most important external requirement is an installation of the International Components for Unicode (ICU) version 3.6 or higher (tested up to 4.2.1).   The source distributions (as well as some binaries) may be found at the site: http://site.icu-project.org/download&lt;br /&gt;
&lt;br /&gt;
If you are using Linux RPM&#039;s to run Hyrax, you can get an RPM for ICU as well.  Search for the RPM named &amp;quot;libicu&amp;quot; using a package manager or yum, e.g.   If you are compiling the module from source, you will also need the RPM &amp;quot;libicu-devel&amp;quot; to get the headers installed.  &lt;br /&gt;
&lt;br /&gt;
If you install in the default locations, the ncml_module should find the libraries and headers.  Otherwise, please consult the INSTALL file for more information about installing ICU to a non-standard location.&lt;br /&gt;
&lt;br /&gt;
== Testing Installation ==&lt;br /&gt;
&lt;br /&gt;
Test data is provided to see if the installation was successful.  The file sample_virtual_dataset.ncml is a dataset purely created in NcML and doesn&#039;t contain an underlying dataset.  &lt;br /&gt;
You may also view fnoc1_improved.ncml to test adding attributes to an existing netCDF dataset (fnoc1.nc), but this requires the netCDF data handler to be&lt;br /&gt;
installed first!  Several other examples installed also use the HDF4 and HDF5 handlers.&lt;br /&gt;
&lt;br /&gt;
= Functionality =&lt;br /&gt;
&lt;br /&gt;
This version of the NcML Module implements a subset of NcML 2.2&lt;br /&gt;
functionality.  The reader is directed to http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/ for more information on NcML.&lt;br /&gt;
&lt;br /&gt;
Our module can currently:&lt;br /&gt;
&lt;br /&gt;
*Refer only to files being served locally (not remotely)&lt;br /&gt;
*Add, modify, and remove attribute metadata to a dataset&lt;br /&gt;
*Create a purely virtual dataset using just NcML and no underlying dataset&lt;br /&gt;
*Create new scalar variables of any simple NcML type or simple DAP type&lt;br /&gt;
*Create new Structure variables (which can contain new child variables)&lt;br /&gt;
*Create new N-dimensional arrays of simple types (NcML or DAP)&lt;br /&gt;
*Remove existing variables from a wrapped dataset&lt;br /&gt;
*Rename existing variables in a wrapped dataset&lt;br /&gt;
*Name dimensions as a mnemonic for specifying Array shapes&lt;br /&gt;
*Perform union aggregations on multiple datasets, virtual or wrapped or both&lt;br /&gt;
*Perform joinNew aggregations to merge a variable across multiple datasets by creating a new outer dimension&lt;br /&gt;
*Specify aggregation member datasets by scanning directories for files matching certain criteria&lt;br /&gt;
&lt;br /&gt;
We describe each supported NcML element in detail below.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;netcdf&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;netcdf&amp;gt; element is used to define a dataset, either a wrapped dataset that is to be modified, a pure virtual dataset, or a member dataset of an aggregation.  The &amp;lt;netcdf&amp;gt; element is assumed to be the topmost node, or as a child of an aggregation element.&lt;br /&gt;
&lt;br /&gt;
=== Local vs. Remote Datasets ===&lt;br /&gt;
&lt;br /&gt;
We assume that the location attribute (&#039;&#039;netcdf@location&#039;&#039;) refers to the full path (with respect to the BES data root directory) of a &#039;&#039;&#039;&#039;&#039;local&#039;&#039;&#039;&#039;&#039; dataset (served by the same Hyrax server).  The current version of the module cannot be used to modify remote datasets.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;netcdf@location&#039;&#039; is the empty string (or unspecified, as empty is the default), the dataset is a pure virtual dataset, fully specified within the NcML file itself.  Attributes and variables may be fully described and accessed with constraints just as normal datasets in this manner.  The installed sample datafile &amp;quot;sample_virtual_dataset.ncml&amp;quot; is an example test case for this functionality.&lt;br /&gt;
&lt;br /&gt;
=== Unsupported Attributes ===&lt;br /&gt;
&lt;br /&gt;
The current version does not support the following attributes of &amp;lt;netcdf&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
*enhance&lt;br /&gt;
*addRecords&lt;br /&gt;
*fmrcDefinition (will be supported when FMRC aggregation is added)&lt;br /&gt;
*ncoords (will be supported when joinExisting is added)&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;readMetadata&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;readMetadata/&amp;gt; element is the default, so is effectively not needed.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;explicit&amp;gt; element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;explicit/&amp;gt; element simply clears all attribute tables in the referred to netcdf@location before applying the rest of the &lt;br /&gt;
NcML transformations to the metadata.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;dimension&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;dimension&amp;gt; element has limited functionality in this release since the DAP2 doesn&#039;t support dimensions as more than mnemonics at this time.  The limitations are:&lt;br /&gt;
&lt;br /&gt;
* We only parse the &#039;&#039;dimension@name&#039;&#039; and &#039;&#039;dimension@length&#039;&#039; attributes.  &lt;br /&gt;
* Dimensions can only be specified as a direct child of a &amp;lt;netcdf&amp;gt; element prior to any reference to them&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt; &lt;br /&gt;
  &amp;lt;dimension name=&amp;quot;station&amp;quot; length=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;dimension name=&amp;quot;samples&amp;quot; length=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;!-- Some variable elements refer to the dimensions here --&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The dimension element sets up a mapping from the &#039;&#039;name&#039;&#039; to the unsigned integer &#039;&#039;length&#039;&#039; and can be used in a &#039;&#039;variable@shape&#039;&#039; to specify a length for an array dimension (see the section on &amp;lt;variable&amp;gt; below).  The dimension map is cleared when &amp;lt;/netcdf&amp;gt; is encountered (though this doesn&#039;t matter currently since we allow only one right now, but it will matter for aggregation, potentially).  We also do not support &amp;lt;group&amp;gt;, which is the only other legal place in NcML 2.2 for a dimension element.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* If the name and length are not both specified.&lt;br /&gt;
* If the dimension name already exists in the current scope&lt;br /&gt;
* If the length is not an unsigned integer&lt;br /&gt;
* If any of the other attributes specified in NcML 2.2 are used.  We do not handle them, so we consider them errors now.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;variable&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;variable&amp;gt; element is used to:&lt;br /&gt;
&lt;br /&gt;
* Provide lexical scope for a contained &amp;lt;attribute&amp;gt; or &amp;lt;variable&amp;gt; element&lt;br /&gt;
* Rename existing variables &lt;br /&gt;
* Add new scalar variables of simple types&lt;br /&gt;
* Add new Structure variables&lt;br /&gt;
* Add new N-dimensional Array&#039;s of simple types&lt;br /&gt;
* Specify the coordinate variable for the new dimension in a joinNew aggregation &lt;br /&gt;
&lt;br /&gt;
We describe each in turn in more detail.&lt;br /&gt;
&lt;br /&gt;
=== Specifying Lexical Scope with &amp;lt;variable type=&amp;quot;&amp;quot;&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Consider the following example:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;variable name=&amp;quot;u&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Metadata&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;This is metadata!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code assumes that a variable named &amp;quot;u&amp;quot; exists (of any type since we do not specify) and provides the lexical scope for the&lt;br /&gt;
attribute &amp;quot;Metadata&amp;quot; which will be added or modified within the attribute table for the variable &amp;quot;u&amp;quot; (it&#039;s qualified name would be &amp;quot;u.Metadata&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
==== Nested DAP Structure and Grid Scopes ====&lt;br /&gt;
&lt;br /&gt;
Scoping variable elements may be nested if the containing variable is a Structure (this includes the special case of Grid)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;DATA_GRANULE&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;PlanetaryGrid&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;variable name=&amp;quot;percipitate&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;inches&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This adds a &amp;quot;unit&amp;quot; attribute to the variable &amp;quot;percipitate&amp;quot; within the nested Structure&#039;s &lt;br /&gt;
(&amp;quot;DATA_GRANULE.PlanetaryGrid.percipitate&amp;quot; as fully qualified name).  &lt;br /&gt;
Note that we &#039;&#039;&#039;must&#039;&#039;&#039; refer to the type explicitly as a &amp;quot;Structure&amp;quot; so the parser knows&lt;br /&gt;
to traverse the tree.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; the variable might be of type Grid, but the type &amp;quot;Structure&amp;quot; must be used in the NcML to traverse it.&lt;br /&gt;
&lt;br /&gt;
==== Adding Multiple Attributes to the Same Variable ====&lt;br /&gt;
&lt;br /&gt;
Once the variable&#039;s scope is set by the opening &amp;lt;variable&amp;gt; element, more than one attribute can be specified within it.  This will make the NcML more readable and also will make the parsing more efficient since the variable will only need to be looked up once.&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_1&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Hello&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_2&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;World!&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
should be preferred over:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_1&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Hello&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_2&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;World!&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
although they produce the same result.  Any number of attributes can be specified before the variable is closed.&lt;br /&gt;
&lt;br /&gt;
=== Renaming Existing Variables ===&lt;br /&gt;
&lt;br /&gt;
The attribute &#039;&#039;variable@orgName&#039;&#039; is used to rename an existing variable. &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;NewName&amp;quot; orgName=&amp;quot;OldName&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing variable at the current scope named &amp;quot;OldName&amp;quot; to &amp;quot;NewName&amp;quot;.  After this point in the NcML file (such as in constraints specified for the DAP request), the variable is known by &amp;quot;NewName&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note that the type is not required here --- the variable is assumed to exist and its existing type is used.  It is not possible to change the type of an existing variable at this time!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:  &lt;br /&gt;
* If a variable with &#039;&#039;variable@orgName&#039;&#039; doesn&#039;t exist in the current scope&lt;br /&gt;
* If the new name &#039;&#039;variable@name&#039;&#039; is already taken in the current scope&lt;br /&gt;
* If a new variable is created but does not have exactly one values element&lt;br /&gt;
&lt;br /&gt;
=== Adding a New Scalar Variable ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;variable&amp;gt; element can be used to create a new scalar variable of a simple type (i.e. an atomic NcML type such as &amp;quot;int&amp;quot; or &amp;quot;float&amp;quot;, or any DAP atomic type, such as &amp;quot;UInt32&amp;quot; or &amp;quot;URL&amp;quot;) by specifying an empty &#039;&#039;variable@shape&#039;&#039; (which is the default), a simple type for &#039;&#039;variable@type&#039;&#039;, and a contained &amp;lt;values&amp;gt; element with the one value of correct type. &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;TheAnswerToLifeTheUniverseAndEverything&amp;quot; type=&amp;quot;double&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;SolvedBy&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;Deep Thought&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;values&amp;gt;42.000&amp;lt;/values&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create a new variable named &amp;quot;TheAnswerToLifeTheUniverseAndEverything&amp;quot; at the current scope.  It has no shape so will be a scalar of type &amp;quot;double&amp;quot; and will have the value 42.0.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* It is a parse error to not specify a &amp;lt;values&amp;gt; element with exactly one proper value of the variable type.&lt;br /&gt;
* It is a parse error to specify a malformed or out of bounds value for the data type&lt;br /&gt;
&lt;br /&gt;
=== Adding a New Structure Variable ===&lt;br /&gt;
&lt;br /&gt;
A new Structure variable can be specified at the global scope or within another Structure.  It is illegal for an array to have type structure, so the shape must be empty.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;MyNewStructure&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;MetaData&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;This is metadata!&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;ContainedScalar1&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&amp;lt;values&amp;gt;I live in a new structure!&amp;lt;/values&amp;gt;&amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;ContainedInt1&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;&amp;lt;values&amp;gt;42&amp;lt;/values&amp;gt;&amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
specifies a new structure called &amp;quot;MyNewStructure&amp;quot; which contains two scalar variable fields &amp;quot;ContainedScalar1&amp;quot; and &amp;quot;ContainedInt1&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
Nested structures are allowed as well.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Error&#039;&#039;&#039;: &lt;br /&gt;
* If another variable or attribute exists at the current scope with the new name.  &lt;br /&gt;
* If a &amp;lt;values&amp;gt; element is specified as a direct child of a new Structure --- structures cannot contain values, only attributes and other variables.&lt;br /&gt;
&lt;br /&gt;
=== Adding a New N-dimensional Array ===&lt;br /&gt;
&lt;br /&gt;
An N-dimensional array of a simple type may be created virtually as well by specifying a non-empty &#039;&#039;variable@shape&#039;&#039;.  The shape contains the array dimensions in left-to-right order of slowest varying dimension first.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;FloatArray&amp;quot; type=&amp;quot;float&amp;quot; shape=&amp;quot;2 5&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;!-- values specified in row major order (leftmost dimension in shape varies slowest) &lt;br /&gt;
	Any whitespace is a valid separator by default, so we can use newlines to pretty print 2D matrices.&lt;br /&gt;
	--&amp;gt;&lt;br /&gt;
      &amp;lt;values&amp;gt;&lt;br /&gt;
	0.1 0.2 0.3 0.4 0.5&lt;br /&gt;
	1.1 1.1 1.3 1.4 1.5&lt;br /&gt;
      &amp;lt;/values&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will specify a 2x5 dimension array of float values called &amp;quot;FloatArray&amp;quot;.  The &amp;lt;values&amp;gt; element must contain 2x5=10 values in row major order (slowest varying dimension first).  Since whitespace is the default separator, we use a newline to show the dimension boundary for the values, which is easy to see for a 2D matrix such as this.&lt;br /&gt;
&lt;br /&gt;
A dimension name may also be used to refer mnemonically to a length.  The DAP response will use this mnemonic in its output, but it is not currently used for shared dimensions, only as a mnemonic.   See the section on the &amp;lt;dimension&amp;gt; element for more information.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt;&lt;br /&gt;
 &amp;lt;dimension name=&amp;quot;station&amp;quot; length=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;dimension name=&amp;quot;sample&amp;quot; length=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;FloatArray&amp;quot; type=&amp;quot;float&amp;quot; shape=&amp;quot;station sample&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;values&amp;gt;&lt;br /&gt;
	0.1 0.2 0.3 0.4 0.5&lt;br /&gt;
	1.1 1.1 1.3 1.4 1.5&lt;br /&gt;
      &amp;lt;/values&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will produce the same 2x5 array, but will incorporate the dimension mnemonics into the response.  For example, here&#039;s the DDS response:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
     Float32 FloatArray[station = 2][samples = 5];&lt;br /&gt;
} sample_virtual_dataset.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;values&amp;gt; element respects the &#039;&#039;values@separator&#039;&#039; attribute if whitespace isn&#039;t correct.  This is very useful for arrays of strings with whitespace, for example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;StringArray&amp;quot; type=&amp;quot;string&amp;quot; shape=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;values separator=&amp;quot;*&amp;quot;&amp;gt;String 1*String 2*String 3&amp;lt;/values&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
creates a length 3 array of string StringArray = {&amp;quot;String 1&amp;quot;, &amp;quot;String 2&amp;quot;, &amp;quot;String 3&amp;quot;}.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:  &lt;br /&gt;
* It is an error to specify the incorrect number of values&lt;br /&gt;
* It is an error if any value is malformed or out of range for the data type.&lt;br /&gt;
* It is an error to specify a named dimension which does not exist in the current &amp;lt;netcdf&amp;gt; scope.&lt;br /&gt;
* It is an error to specify an Array whose flattened size (product of dimensions) is &amp;gt; 2^31-1.&lt;br /&gt;
&lt;br /&gt;
=== Specifying the new coordinate variable for a joinNew aggregation ===&lt;br /&gt;
&lt;br /&gt;
In the special case of a joinNew aggregation, the new coordinate variable may be specified with the &amp;lt;variable&amp;gt; element.  The new coordinate variable is &#039;&#039;defined&#039;&#039; to have the same name as the new dimension.  This allows for several things:&lt;br /&gt;
&lt;br /&gt;
*Explicit specification of the variable type and coordinates for the new dimension&lt;br /&gt;
*Specification of the metadata for the new coordinate variable &lt;br /&gt;
&lt;br /&gt;
In the first case, the author can specify explicitly the type of the new coordinate variable and the actual values for each dataset.  In this case, the variable &#039;&#039;must&#039;&#039; be specified &#039;&#039;after&#039;&#039; the aggregation element in the file so the new dimension&#039;s size (number of member datasets) may be known and error checking performed.  Metadata can also be added to the variable here.&lt;br /&gt;
&lt;br /&gt;
In the second case, the author may just specify the variable name, which allows one to specify the metadata for a coordinate variable that is automatically generated by the aggregation itself.  This is the only allowable case for a variable element to &#039;&#039;not&#039;&#039; contain a values element!  Coordinate variables are generated automatically in two cases:&lt;br /&gt;
&lt;br /&gt;
*The author has specified an explicit list of member datasets, with or without explicit coordVal attributes.  &lt;br /&gt;
*The author has used a &amp;lt;scan&amp;gt; element to specify the member datasets via a directory scan&lt;br /&gt;
&lt;br /&gt;
In this case, the &amp;lt;variable&amp;gt; element may come before or after the &amp;lt;aggregation&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*If an explicit variable is declared for the new coordinate variable:&lt;br /&gt;
** And it contains explicit values, the number of values must be equal to the number of member datasets in the aggregation.&lt;br /&gt;
** It must be specifed &#039;&#039;after&#039;&#039; the &amp;lt;aggregation&amp;gt; element&lt;br /&gt;
&lt;br /&gt;
* If a numeric coordVal is used to specify the first member dataset&#039;s coordinate, then &#039;&#039;all&#039;&#039; datasets must contain a numerical coordinate.&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variable (variableAgg) is not found in &#039;&#039;all&#039;&#039; member datasets.&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variable is not of the same type in &#039;&#039;all&#039;&#039; member datasets.  Coercion is &#039;&#039;not&#039;&#039; performed!&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variables in all member datasets do not have the same shape&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if an explicit coordinate variable is specified with a shape that is &#039;&#039;not&#039;&#039; the same as the new dimension name (and the variable name itself).&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;values&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;values&amp;gt; element can only be used in the context of a &#039;&#039;&#039;new&#039;&#039;&#039; variable of scalar or array type.  We cannot change the values for existing variables in this version of the handler. &lt;br /&gt;
The characters content of a &amp;lt;values&amp;gt; element is considered to be a separated list of value tokens valid for the type of the variable of the parent element.  The number of specified tokens in the content &#039;&#039;must&#039;&#039; equal the product of the dimensions of the enclosing &#039;&#039;variable@shape&#039;&#039;, or be one value for a scalar.  It is an error to &#039;&#039;not&#039;&#039; specify a &amp;lt;values&amp;gt; element for a declared new variable as well.  &lt;br /&gt;
&lt;br /&gt;
=== Changing the Separator Tokens === &lt;br /&gt;
&lt;br /&gt;
The author may specify values@separator to change the default value token separator from the default whitespace.  This is very useful for specifying arrays of strings with whitespace in them, or if data in CSV form is being pasted in.  &lt;br /&gt;
&lt;br /&gt;
=== Autogeneration of Uniform Arrays ===&lt;br /&gt;
&lt;br /&gt;
We also can parse &#039;&#039;values@start&#039;&#039; and &#039;&#039;values@increment&#039;&#039; INSTEAD OF tokens in the content.  This will &amp;quot;autogenerate&amp;quot; a uniform array of values of the given product of dimensions length for the containing variable.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Evens&amp;quot; type=&amp;quot;int&amp;quot; shape=&amp;quot;100&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;values start=&amp;quot;0&amp;quot; increment=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will specify an array of the first 100 even numbers (including 0).  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* If the incorrect number of tokens are specified for the containing variable&#039;s shape&lt;br /&gt;
* If any value token cannot be parsed as a valid value for the containing variable&#039;s type&lt;br /&gt;
* If content is specified in addition to start and increment&lt;br /&gt;
* If only one of start or increment is specified&lt;br /&gt;
* If the values element is placed anywhere except within a NEW variable.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;attribute&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
As an overview, whenever the parser encounters an &amp;lt;attribute&amp;gt; with a non-existing name (at the current scope),&lt;br /&gt;
it creates a new one, whether a container or atomic attribute (see below).  If the attribute exists,&lt;br /&gt;
its value and/or type is modified to those specified in the &amp;lt;attribute&amp;gt; element.  If an attribute&lt;br /&gt;
structure (container) exists, it is used to define a nested lexical scope for child attributes.  &lt;br /&gt;
&lt;br /&gt;
Attributes may be scalar (one value) or one dimensional arrays.  Arrays are specified by using whitespace (default) to separate the different values.  The attribute@separator may also be set in order to specify a different separator, such as CSV format or to specify a non-whitespace separator so strings with whitespace are not tokenized.  We will give examples of creating array attributes below.&lt;br /&gt;
&lt;br /&gt;
=== Adding New Attributes or Modifying an Existing Attribute ===&lt;br /&gt;
&lt;br /&gt;
If a specified attribute with the attribute@name does not exist at the current lexical scope, &lt;br /&gt;
a new one is created with the given type and value.  For example, assume &amp;quot;new_metadata&amp;quot; doesn&#039;t&lt;br /&gt;
exist at the current parse scope.  Then:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;new_metadata&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;This is a new entry!&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create the attribute at that scope.  Note that value can be specified in the content of the &lt;br /&gt;
element as well.  This is identical to the above:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;new_metadata&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;This is a new entry!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the attribute@name already exists at the scope, it is modified to contain the specified type and value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Arrays ====&lt;br /&gt;
&lt;br /&gt;
As in NcML, for numerical types an array can be specified by separating the tokens by whitespace (default) or be&lt;br /&gt;
specifying the token separator with attribute@separator.  For example,&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;myArray&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 2 3&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;myArray&amp;quot; type=&amp;quot;int&amp;quot; separator=&amp;quot;,&amp;quot;&amp;gt;1,2,3&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
both specify the same array of three integers named &amp;quot;myArray&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
TODO Add more information on splitting with a separator!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Structures (Containers) ====&lt;br /&gt;
&lt;br /&gt;
We use attribute@type=&amp;quot;Structure&amp;quot; to define a new (or existing) attribute container.   So if we&lt;br /&gt;
wanted to add a new attribute structure, we&#039;d use something like this: &lt;br /&gt;
&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;MySamples&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Location&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Station 1&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Samples&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 4 6&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assuming &amp;quot;MySamples&amp;quot; doesn&#039;t already exist, an attribute container will be created at the current scope&lt;br /&gt;
and the &amp;quot;Location&amp;quot; and &amp;quot;Samples&amp;quot; attributes will be added to it.&lt;br /&gt;
&lt;br /&gt;
Note that we can create nested attribute structures to arbitrary depth this way as well.&lt;br /&gt;
&lt;br /&gt;
If the attribute container with the given name already exists at the current scope, &lt;br /&gt;
then the attribute@type=&amp;quot;Structure&amp;quot; form is used to define&lt;br /&gt;
the lexical scope for the container.  In other words, child &amp;lt;attribute&amp;gt; elements will&lt;br /&gt;
be processed within the scope of the container.   For example, in the above example, if&lt;br /&gt;
&amp;quot;MySamples&amp;quot; already exists, then the &amp;quot;Location&amp;quot; and &amp;quot;Samples&amp;quot; will be processed within the&lt;br /&gt;
existing container (they may or may not already exist as well).&lt;br /&gt;
&lt;br /&gt;
==== Renaming an Existing Attribute or Attribute Container ====&lt;br /&gt;
&lt;br /&gt;
We also support the attribute@orgName attribute for renaming attributes.   &lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;NewName&amp;quot; orgName=&amp;quot;OldName&amp;quot; type=&amp;quot;string&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing attribute &amp;quot;OldName&amp;quot; to &amp;quot;NewName&amp;quot; while leaving its value alone.&lt;br /&gt;
If attribute@value is also specified, then the attribute is renamed &#039;&#039;and&#039;&#039; has its value modified.&lt;br /&gt;
&lt;br /&gt;
This works for renaming attribute containers as well:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;MyNewContainer&amp;quot; orgName=&amp;quot;MyOldContainer&amp;quot; type=&amp;quot;Structure&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing &amp;quot;MyOldContainer&amp;quot; to &amp;quot;MyNewContainer&amp;quot;.  Note that any children&lt;br /&gt;
of this container will remain in it.&lt;br /&gt;
&lt;br /&gt;
=== DAP &#039;&#039;OtherXML&#039;&#039; Extension ===&lt;br /&gt;
&lt;br /&gt;
The module now allows specification of attributes of the new DAP type &amp;quot;OtherXML&amp;quot;.  This allows the NCML file author to inject arbitrary well-formed XML into an attribute for clients that want XML metadata rather than just string or url.  Internally, the attribute is still a string (and in a DAP DAS response will be quoted inside one string).  However, since it is XML, the NCMLParser still parses it and checks it for well-formedness (but NOT against schemas).  This extension allows the NCMLParser to parse the arbitrary XML within the given attribute without causing errors, since it can be any XML.  &lt;br /&gt;
&lt;br /&gt;
The injected XML is most useful in the DDX response, where it shows up directly in the response as XML.  XSLT and other clients can then parse it.&lt;br /&gt;
&lt;br /&gt;
==== Errors ====&lt;br /&gt;
&lt;br /&gt;
*The XML &#039;&#039;&#039;must&#039;&#039;&#039; be in the content of the &amp;lt;attribute type=&amp;quot;OtherXML&amp;quot;&amp;gt; element.  It is a parser error for &#039;&#039;attribute@value&#039;&#039; to be set if &#039;&#039;attribute@type&#039;&#039; is &amp;quot;OtherXML&amp;quot;.  &lt;br /&gt;
*The XML must also be well-formed since it is parsed.  A parse error will be thrown if the OtherXML is malformed.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of the use of this special case.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf xmlns=&amp;quot;http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2&amp;quot; location=&amp;quot;/coverage/200803061600_HFRadar_USEGC_6km_rtv_SIO.nc&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;someName&amp;quot; type=&amp;quot;OtherXML&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;Domain xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot; &lt;br /&gt;
                xmlns:ows=&amp;quot;http://www.opengis.net/ows/1.1&amp;quot;&lt;br /&gt;
                xmlns:gml=&amp;quot;http://www.opengis.net/gml/3.2&amp;quot;&lt;br /&gt;
                &amp;gt;&lt;br /&gt;
            &amp;lt;SpatialDomain&amp;gt;&lt;br /&gt;
                &amp;lt;ows:BoundingBox crs=&amp;quot;urn:ogc:def:crs:EPSG::4326&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;ows:LowerCorner&amp;gt;-97.8839 21.736&amp;lt;/ows:LowerCorner&amp;gt;&lt;br /&gt;
                    &amp;lt;ows:UpperCorner&amp;gt;-57.2312 46.4944&amp;lt;/ows:UpperCorner&amp;gt;&lt;br /&gt;
                &amp;lt;/ows:BoundingBox&amp;gt;&lt;br /&gt;
            &amp;lt;/SpatialDomain&amp;gt;&lt;br /&gt;
            &amp;lt;TemporalDomain&amp;gt;&lt;br /&gt;
                &amp;lt;gml:timePosition&amp;gt;2008-03-27T16:00:00.000Z&amp;lt;/gml:timePosition&amp;gt;&lt;br /&gt;
            &amp;lt;/TemporalDomain&amp;gt;&lt;br /&gt;
        &amp;lt;/Domain&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedCRS xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;urn:ogc:def:crs:EPSG::4326&amp;lt;/SupportedCRS&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedFormat xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;netcdf-cf1.0&amp;lt;/SupportedFormat&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedFormat xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;dap2.0&amp;lt;/SupportedFormat&amp;gt;&lt;br /&gt;
    &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039; Put the DDX response for the above in here!&lt;br /&gt;
&lt;br /&gt;
====Namespace Closure====&lt;br /&gt;
&lt;br /&gt;
Furthermore, the parser will make the chunk of OtherXML &amp;quot;namespace closed&amp;quot;.  This means any namespaces specified in parent NCML elements of the OtherXML tree will be &amp;quot;brought down&amp;quot; and added to the &#039;&#039;root&#039;&#039; OtherXML elements so that the subtree may be pulled out and added to the DDX and still have its namespaces.  The algorithm doesn&#039;t just bring used prefixes, but brings &#039;&#039;all&#039;&#039; of the lexically scoped closest namespaces in all ancestors.  In other words, it adds unique namespaces (as determined by prefix) in order from the root of the OtherXML tree as it traverses to the root of the NCML document.  &lt;br /&gt;
&lt;br /&gt;
Namespace closure is a syntactic sugar that simplifies the author&#039;s task since they can specify the namespaces just once at the top of the NCML file and expect that when the subtree of XML is added to the DDX that these namespaces will come along with that subtree of XML.  Otherwise they have to explicitly add the namespaces to each attributes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039; Add an example!&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;remove&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;remove&amp;gt; element can remove attributes and variables.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;attribute name=&amp;quot;NC_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;remove name=&amp;quot;base_time&amp;quot; type=&amp;quot;attribute&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will remove the attribute named &amp;quot;base_time&amp;quot; in the attribute structure named &amp;quot;NC_GLOBAL&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Note that this works for attribute containers as well!  We could recursively remove the &#039;&#039;entire&#039;&#039;&lt;br /&gt;
attribute container (i.e. it and all its children) with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;remove name=&amp;quot;NC_GLOBAL&amp;quot; type=&amp;quot;attribute&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It also can be used to remove variables from existing datasets:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
  &amp;lt;remove name=&amp;quot;SomeExistingVariable&amp;quot; type=&amp;quot;variable&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This also recurses on variables of type Structure --- the entire structure including all of its children are removed from the dataset&#039;s response.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* It is a parse error if the given attribute or variable doesn&#039;t exist in the current scope&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;aggregation&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
Aggregation involves combining multiple datasets (&amp;lt;netcdf&amp;gt;) into a virtual &amp;quot;single&amp;quot; dataset in various ways.  For a tutorial on aggregation in NcML 2.2, the reader is referred to the Unidata page: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Aggregation.html&lt;br /&gt;
&lt;br /&gt;
NcML 2.2 supports multiple types of aggregation: union, joinNew, joinExisting, and fmrc (forecast model run collection).  &lt;br /&gt;
&lt;br /&gt;
The current version of the NcML module supports two of these aggregations:&lt;br /&gt;
&lt;br /&gt;
*Union [[NCML_Module_Aggregation_Union]]&lt;br /&gt;
*JoinNew [[NCML_Module_Aggregation_JoinNew]]&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;union&#039;&#039; aggregation specifies that the first instance of a variable or attribute (by name) that is found in the ordered list of datasets will be the one in the output aggregation.   This is useful for combining two dataset files, each which may contain a single variable, into a composite dataset with both variables.&lt;br /&gt;
&lt;br /&gt;
A JoinNew aggregation joins a variable which exists in multiple datasets (usually samples of a datum over time) into a new variable containing the data from &#039;&#039;all&#039;&#039; member datasets by creating a new outer dimension.  The &#039;&#039;i&#039;&#039;th component in the new outer dimension is the variable&#039;s data from the &#039;&#039;i&#039;&#039;th member dataset.  It also adds a new coordinate variable of whose name is the new dimension&#039;s name and whose shape (length) is the new dimension as well.  This new coordinate variable may be explicitly given by the author or may be autogenerated in one of several ways.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;scan&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The scan element can be used within an aggregation context to allow a directory to be searched in various ways in order to specify the members of an aggregation.  This allows a static NcML file to refer to an aggregation which may change over time, such as where a new data file is generated each day.&lt;br /&gt;
&lt;br /&gt;
We describe usage of the &amp;lt;scan&amp;gt; element in detail in the joinNew aggregation tutorial at [[NCML_Module_Aggregation_JoinNew]].&lt;br /&gt;
&lt;br /&gt;
= Errors =&lt;br /&gt;
&lt;br /&gt;
There are three types of error messages that may be returned:&lt;br /&gt;
&lt;br /&gt;
* Internal Error&lt;br /&gt;
* Resource Not Found Error&lt;br /&gt;
* Parse Error&lt;br /&gt;
&lt;br /&gt;
== Internal Errors ==&lt;br /&gt;
&#039;&#039;&#039;Internal errors&#039;&#039;&#039; should be reported to support@opendap.org as they are likely bugs.&lt;br /&gt;
&lt;br /&gt;
== Resource Not Found Errors ==&lt;br /&gt;
&lt;br /&gt;
If the netcdf@location specifies a non-existent local dataset (one that is not being served by&lt;br /&gt;
the same Hyrax server), it will specify the resource was not found.   This may also be returned&lt;br /&gt;
if a handler for the specified dataset is not currently loaded in the BES.  Users should test that the&lt;br /&gt;
dataset to be wrapped already exists and can be viewed on the running server before writing NcML &lt;br /&gt;
to add metadata.  It&#039;s also an error to refer to remote datasets (at this time).&lt;br /&gt;
&lt;br /&gt;
== Parse Errors ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse errors&#039;&#039;&#039; are user errors in the NcML file.  These could be malformed XML, malformed NcML, &lt;br /&gt;
unimplemented features of NcML, or could be errors in referring to the wrapped dataset.  &lt;br /&gt;
&lt;br /&gt;
The error message should specify &lt;br /&gt;
the error condition as well as the &amp;quot;current scope&amp;quot; as a fully qualified DAP name within the &lt;br /&gt;
loaded dataset.  This should be enough information to correct the parse error as new NcML&lt;br /&gt;
files are created.&lt;br /&gt;
&lt;br /&gt;
The parser will generate parse errors in various &lt;br /&gt;
situations where it expects to find certain structure in the underlying dataset.  Some examples:&lt;br /&gt;
&lt;br /&gt;
* A variable of the given name was not found at the current scope&lt;br /&gt;
* attribute@orgName was specified, but the attribute cannot be found at current scope.&lt;br /&gt;
* attribute@orgName was specified, but the new name is already used at current scope.&lt;br /&gt;
* remove specified a non-existing attribute name&lt;br /&gt;
&lt;br /&gt;
= Grid Metadata Tutorial =&lt;br /&gt;
&lt;br /&gt;
Please see the page [[Grid_Metadata_Tutorial]] for an example of adding metadata to the various parts of a DAP Grid variable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Aggregation Tutorials =&lt;br /&gt;
&lt;br /&gt;
The NcML module may also be used to aggregate multiple datasets into one virtual dataset.  We currently support two of the NcML aggregtions:&lt;br /&gt;
&lt;br /&gt;
*Union [[NCML_Module_Aggregation_Union]]:  combine multiple datasets into one by merging variables together, selecting the first of each unique name.&lt;br /&gt;
*JoinNew [[NCML_Module_Aggregation_JoinNew]]: combine variables across multiple datasets by creating a new outer dimension and coordinate variable for each of the sample datasets.&lt;br /&gt;
&lt;br /&gt;
Please see the sections for a tutorial on the various uses of these aggregations.&lt;br /&gt;
&lt;br /&gt;
= Additions/Changes to NcML 2.2 =&lt;br /&gt;
&lt;br /&gt;
This section will keep track of changes to the NcML 2.2 schema.  Eventually these&lt;br /&gt;
will be rolled into a new schema.&lt;br /&gt;
&lt;br /&gt;
== Attribute Structures (Containers) ==&lt;br /&gt;
This module also adds functionality beyond the current NcML 2.2 schema&lt;br /&gt;
--- it can handle nested &amp;lt;attribute&amp;gt; elements in order to make&lt;br /&gt;
attribute structures.  This is done by using the &amp;lt;attribute&lt;br /&gt;
type=&amp;quot;Structure&amp;quot;&amp;gt; form, for example:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;MySamples&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Location&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Station 1&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Samples&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 4 6&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;MyContainer&amp;quot; describes an attribute structure with two attribute fields,&lt;br /&gt;
a string &amp;quot;Location&amp;quot; and an array of int&#039;s called &amp;quot;Samples&amp;quot;.  &lt;br /&gt;
Note that an attribute structure of this form can&lt;br /&gt;
only contain other &amp;lt;attribute&amp;gt; elements and NOT a value.&lt;br /&gt;
&lt;br /&gt;
If the container does not already exist, it will be created at the scope it is declared, which could&lt;br /&gt;
be:&lt;br /&gt;
&lt;br /&gt;
* Global (top of dataset)&lt;br /&gt;
* Within a variable&#039;s attribute table&lt;br /&gt;
* Within another attribute container&lt;br /&gt;
&lt;br /&gt;
If an attribute container of the given name already exists at the lexical scope, it is traversed &lt;br /&gt;
in order to define the scope for the nested (children) attributes it contains.&lt;br /&gt;
&lt;br /&gt;
== Unspecified Variable Type Matching for Lexical Scope ==&lt;br /&gt;
&lt;br /&gt;
We also allow the type attribute of a variable element (variable@type) to be the empty string &lt;br /&gt;
(or unspecified) when using existing variables to define the lexical scope of an &amp;lt;attribute&amp;gt; &lt;br /&gt;
transformation.  In the schema, variable@type is (normally) required.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DAP 2 Types ==&lt;br /&gt;
&lt;br /&gt;
Additionally, we allow DAP2 atomic types (such as UInt32, URL) in addition to the NcML types.  &lt;br /&gt;
The NcML types are mapped onto the closest DAP2 type internally.&lt;br /&gt;
&lt;br /&gt;
== DAP OtherXML Attribute Type ==&lt;br /&gt;
&lt;br /&gt;
We also allow attributes to be of the new DAP type &amp;quot;OtherXML&amp;quot; for injecting arbitrary XML into an attribute as content rather than trying to form a string.  This allows the parser to check well-formedness.&lt;br /&gt;
&lt;br /&gt;
== Forward Declaration of Dimensions ==&lt;br /&gt;
&lt;br /&gt;
Since we use a SAX parser for efficiency, we require the &amp;lt;dimension&amp;gt; elements to come &#039;&#039;before&#039;&#039; their use in a &#039;&#039;variable@shape&#039;&#039;.  One way to change the schema to allow this is to force the dimension elements to be specified in a sequence after explicit and metadata choice and before all other elements.&lt;br /&gt;
&lt;br /&gt;
== Aggregation Element Location and Processing Order Differences ==&lt;br /&gt;
&lt;br /&gt;
NcML specifies that if a dataset (&amp;lt;netcdf&amp;gt; element) specifies an aggregation element, the aggregation element is always processed first, regardless of its ordering within the &amp;lt;netcdf&amp;gt; element.  Our parser, since it is SAX and not DOM, modifies this behavior in that order matters in some cases:&lt;br /&gt;
&lt;br /&gt;
* Metadata (&amp;lt;attribute&amp;gt;) elements specified &#039;&#039;prior&#039;&#039; to an aggregation &amp;quot;shadow&amp;quot; the aggregation versions.  This is be useful for &amp;quot;overriding&amp;quot; an attribute or variable in a union aggregation, where the first found will take precedence. &lt;br /&gt;
* JoinNew: If the new coordinate variable&#039;s data is to be set explicitly by specifying the new dimension&#039;s shape (either with explicit data or the autogenerated data using values@start and values@increment attributes), the &amp;lt;variable&amp;gt; &#039;&#039;must&#039;&#039; come after the aggregation since the size of the dimension is unknown until the aggregation element is processed.&lt;br /&gt;
&lt;br /&gt;
= Backward Compatibility Issues =&lt;br /&gt;
&lt;br /&gt;
Due to the way shared dimensions were implemented in the NetCDF, HDF4, and HDF5 handlers, the DAS responses did not follow the DAP2 specification.  The NcML module, on the other hand, generates DAP2 compliant DAS for these datasets, which means that wrapping some datasets in NcML will generate a DAS with a different structure.  This is important for the NcML author since it changes the names of attributes and variables.  In order for the module to find the correct scope for adding metadata, for example, the DAP2 DAS must be used.  &lt;br /&gt;
&lt;br /&gt;
In general, what this means is that an empty &amp;quot;passthrough&amp;quot; NcML file should be the starting point for authoring an NcML file.  This file would just specify a dataset and nothing else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;/data/ncml/myNetcdf.nc&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The author would then request the DAS response for the NCML file and use that as the starting point for modifications to the original dataset. &lt;br /&gt;
&lt;br /&gt;
More explicit examples are given below.&lt;br /&gt;
&lt;br /&gt;
== NetCDF ==&lt;br /&gt;
&lt;br /&gt;
The NetCDF handler represents some NC datasets as a DAP 2 Grid, but the returned DAS is not consistent with the DAP 2 spec for the attribute hierarchy for such a Grid.  The map vector attributes are placed as siblings of the grid attributes rather than within the grid lexical scope.  For example, here&#039;s the NetCDF Handler DDS for a given file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Int16 cldc[time = 456][lat = 21][lon = 360];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 456];&lt;br /&gt;
        Float32 lat[lat = 21];&lt;br /&gt;
        Float32 lon[lon = 360];&lt;br /&gt;
    } cldc;&lt;br /&gt;
} cldc.mean.nc;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
showing the Grid.  Here&#039;s the DAS the NetCDF handler generates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    lat {&lt;br /&gt;
        String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
        String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
        Float32 actual_range 10.00000000, -10.00000000;&lt;br /&gt;
    }&lt;br /&gt;
    lon {&lt;br /&gt;
        String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
        String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
        Float32 actual_range 0.5000000000, 359.5000000;&lt;br /&gt;
    }&lt;br /&gt;
    time {&lt;br /&gt;
        String units &amp;quot;days since 1-1-1 00:00:0.0&amp;quot;;&lt;br /&gt;
        String long_name &amp;quot;Time&amp;quot;;&lt;br /&gt;
        String delta_t &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
        String avg_period &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
        Float64 actual_range 715511.00000000000, 729360.00000000000;&lt;br /&gt;
    }&lt;br /&gt;
    cldc {&lt;br /&gt;
        Float32 valid_range 0.000000000, 8.000000000;&lt;br /&gt;
        Float32 actual_range 0.000000000, 8.000000000;&lt;br /&gt;
        String units &amp;quot;okta&amp;quot;;&lt;br /&gt;
        Int16 precision 1;&lt;br /&gt;
        Int16 missing_value 32766;&lt;br /&gt;
        Int16 _FillValue 32766;&lt;br /&gt;
        String long_name &amp;quot;Cloudiness Monthly Mean at Surface&amp;quot;;&lt;br /&gt;
        String dataset &amp;quot;COADS 1-degree Equatorial Enhanced\\012AI&amp;quot;;&lt;br /&gt;
        String var_desc &amp;quot;Cloudiness\\012C&amp;quot;;&lt;br /&gt;
        String level_desc &amp;quot;Surface\\0120&amp;quot;;&lt;br /&gt;
        String statistic &amp;quot;Mean\\012M&amp;quot;;&lt;br /&gt;
        String parent_stat &amp;quot;Individual Obs\\012I&amp;quot;;&lt;br /&gt;
        Float32 add_offset 3276.500000;&lt;br /&gt;
        Float32 scale_factor 0.1000000015;&lt;br /&gt;
    }&lt;br /&gt;
    NC_GLOBAL {&lt;br /&gt;
        String title &amp;quot;COADS 1-degree Equatorial Enhanced&amp;quot;;&lt;br /&gt;
        String history &amp;quot;&amp;quot;;&lt;br /&gt;
        String Conventions &amp;quot;COARDS&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    DODS_EXTRA {&lt;br /&gt;
        String Unlimited_Dimension &amp;quot;time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the map vector attributes are in the &amp;quot;dataset&amp;quot; scope.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the DAS that the NcML Module produces from the correctly formed DDX:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    NC_GLOBAL {&lt;br /&gt;
        String title &amp;quot;COADS 1-degree Equatorial Enhanced&amp;quot;;&lt;br /&gt;
        String history &amp;quot;&amp;quot;;&lt;br /&gt;
        String Conventions &amp;quot;COARDS&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    DODS_EXTRA {&lt;br /&gt;
        String Unlimited_Dimension &amp;quot;time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    cldc {&lt;br /&gt;
        Float32 valid_range 0.000000000, 8.000000000;&lt;br /&gt;
        Float32 actual_range 0.000000000, 8.000000000;&lt;br /&gt;
        String units &amp;quot;okta&amp;quot;;&lt;br /&gt;
        Int16 precision 1;&lt;br /&gt;
        Int16 missing_value 32766;&lt;br /&gt;
        Int16 _FillValue 32766;&lt;br /&gt;
        String long_name &amp;quot;Cloudiness Monthly Mean at Surface&amp;quot;;&lt;br /&gt;
        String dataset &amp;quot;COADS 1-degree Equatorial Enhanced\\012AI&amp;quot;;&lt;br /&gt;
        String var_desc &amp;quot;Cloudiness\\012C&amp;quot;;&lt;br /&gt;
        String level_desc &amp;quot;Surface\\0120&amp;quot;;&lt;br /&gt;
        String statistic &amp;quot;Mean\\012M&amp;quot;;&lt;br /&gt;
        String parent_stat &amp;quot;Individual Obs\\012I&amp;quot;;&lt;br /&gt;
        Float32 add_offset 3276.500000;&lt;br /&gt;
        Float32 scale_factor 0.1000000015;&lt;br /&gt;
        cldc {&lt;br /&gt;
        }&lt;br /&gt;
        time {&lt;br /&gt;
            String units &amp;quot;days since 1-1-1 00:00:0.0&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;Time&amp;quot;;&lt;br /&gt;
            String delta_t &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
            String avg_period &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
            Float64 actual_range 715511.00000000000, 729360.00000000000;&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
            Float32 actual_range 10.00000000, -10.00000000;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
            Float32 actual_range 0.5000000000, 359.5000000;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here the Grid Structure &amp;quot;cldc&amp;quot;  and its contained data array (of the same name &amp;quot;cldc&amp;quot;) and map vectors have their own attribute containers as DAP 2 specifies.&lt;br /&gt;
&lt;br /&gt;
What this means for the author of an NcML file adding metadata to a NetCDF dataset that returns a Grid is that they should generate a &amp;quot;passthrough&amp;quot; file and get the DAS and then specify modifications based on that structure.  &lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example passthrough:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/cldc.mean.nc&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For example, to add an attribute to the map vector &amp;quot;lat&amp;quot; in the above, we&#039;d need the following NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/cldc.mean.nc&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;!-- Traverse into the Grid as a Structure --&amp;gt;&lt;br /&gt;
  &amp;lt;variable name=&amp;quot;cldc&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Traverse into the &amp;quot;lat&amp;quot; map vector (Array) --&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lat&amp;quot;&amp;gt; &lt;br /&gt;
      &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;I am a new attribute in the Grid map vector named lat!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lon&amp;quot;&amp;gt; &lt;br /&gt;
      &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;I am a new attribute in the Grid map vector named lon!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This clearly shows that the structure of the Grid must be used in the NcML:  the attribute being added is technically &amp;quot;cldc.lat.Description&amp;quot; in a fully qualified name.  The parser would return an error if it was attempted as &amp;quot;lat.Description&amp;quot; as the NetCDF DAS for the original file would have led one to believe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== HDF4/HDF5 ==&lt;br /&gt;
&lt;br /&gt;
Similarly to the NetCDF case, the Hyrax HDF4 Module produces DAS responses that do not respect the DAP2 specification.  If an NcML file is used to &amp;quot;wrap&amp;quot; an HDF4 dataset, the&lt;br /&gt;
correct DAP2 DAS response will be generated, however. &lt;br /&gt;
&lt;br /&gt;
This is important for those writing NcML for HDF4 data since the&lt;br /&gt;
lexical scope for attributes relies on the correct DAS form --- to&lt;br /&gt;
handle this, the user should start with a &amp;quot;passthrough&amp;quot; NcML file (see the above NetCDF example) and&lt;br /&gt;
use the DAS from that as the starting point for knowing the structure&lt;br /&gt;
the NcML handler expects to see in the NcML file.  Alternatively, the DDX has the &lt;br /&gt;
proper attribute structure as well (the DAS is generated from it).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Known Bugs =&lt;br /&gt;
&lt;br /&gt;
There are no known bugs currently.&lt;br /&gt;
&lt;br /&gt;
= Planned Future Enhancements =&lt;br /&gt;
&lt;br /&gt;
Planned enhancements for future versions of the module include:&lt;br /&gt;
&lt;br /&gt;
* New NcML Aggregations&lt;br /&gt;
** JoinExisting&lt;br /&gt;
*** Joins a variable across multiple datasets by appending the data for a given dimension from each dataset &lt;br /&gt;
*** Will also allow directory scans for specifying the aggregation&lt;br /&gt;
** Forecast Model Run Collection (FMRC)&lt;br /&gt;
*** Special case of JoinNew for forecast data with two time variables&lt;br /&gt;
*** See: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/FmrcAggregation.html&lt;br /&gt;
&lt;br /&gt;
= Copyright =&lt;br /&gt;
&lt;br /&gt;
This software is copyrighted under the GNU Lesser GPL.  Please see the&lt;br /&gt;
files COPYING and COPYRIGHT that came with this distribution.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=BES_-_Modules_-_NcML_Module&amp;diff=5752</id>
		<title>BES - Modules - NcML Module</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=BES_-_Modules_-_NcML_Module&amp;diff=5752"/>
		<updated>2010-06-29T18:44:21Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
[[Category:NCML]]&lt;br /&gt;
[[Category:BES Modules|NCML Module]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Welcome to the OPeNDAP NcML Data Handler Module v1.0.2 for Hyrax 1.6!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[Updated for NcML Module v1.0.2 for Hyrax 1.6.1 Release --   29 June 2010]&lt;br /&gt;
&lt;br /&gt;
This module may be added to a Hyrax 1.6 server to extend its data&lt;br /&gt;
serving capability to NcML 2.2 files (see&lt;br /&gt;
http://www.unidata.ucar.edu/software/netcdf/ncml/).  NcML provides support for modifying other datasets in various ways, such as adding metadata and data and aggregating multiple datasets in several ways.&lt;br /&gt;
&lt;br /&gt;
We refer the reader to the Unidata NcML tutorial: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Tutorial.html which will give the basics of using NcML.  We then give a reference manual for the various elements and their attributes.  Additionally we have provided a more extensive tutorial on NcML aggregation.  Please see [[#Aggregation Tutorials]].&lt;br /&gt;
&lt;br /&gt;
Since the DAP Grid is a common case, we will also give a simple example for adding metadata to the various parts of a Grid dataset using NcML.  Please see [[Grid_Metadata_Tutorial]].&lt;br /&gt;
&lt;br /&gt;
==Features==         &lt;br /&gt;
   &lt;br /&gt;
This current version (v1.0.2) currently implements a subset of NcML 2.2&lt;br /&gt;
functionality, along with some OPeNDAP extensions:&lt;br /&gt;
&lt;br /&gt;
* Metadata Manipulation&lt;br /&gt;
** Addition, Removal, and Modification of attributes to other datasets (NetCDF, HDF4, HD5, etc.) served by the same Hyrax 1.6 server&lt;br /&gt;
** Extends NcML 2.2 to allow for common nested &amp;quot;attribute containers&amp;quot; &lt;br /&gt;
** Attributes can be DAP2 types as well as the NcML types &lt;br /&gt;
** Attributes can be of the special &amp;quot;OtherXML&amp;quot; type for injecting arbitrary XML into a DDX response&lt;br /&gt;
* Data Manipulation&lt;br /&gt;
** Addition of new data variables (scalars or arrays of basic types as well as structures) &lt;br /&gt;
** Variables may be removed from the wrapped dataset&lt;br /&gt;
** Allows the creation of &amp;quot;pure virtual&amp;quot; datasets which do not wrap another dataset&lt;br /&gt;
* Aggregations: JoinNew and Union [[#Aggregation Tutorials]]&lt;br /&gt;
** JoinNew Aggregation ([[NCML_Module_Aggregation_JoinNew]])&lt;br /&gt;
*** Allows multiple datasets to be &amp;quot;joined&amp;quot; by creating a new outer dimension for the aggregated variable&lt;br /&gt;
*** Aggregation member datasets can be listed explicitly with explicit coordinates for the new dimension for each member&lt;br /&gt;
*** Scan: Aggregations can be specified &amp;quot;automatically&amp;quot; by scanning a directory for files matching certain criteria, such as a suffix or regular expression.&lt;br /&gt;
*** Metadata may be added to the new coordinate variable for the new dimension&lt;br /&gt;
** Union Aggregation ([[NCML_Module_Aggregation_Union]])&lt;br /&gt;
*** Merges all member datasets into one by taking the first named instance of variables and metadata from the members&lt;br /&gt;
*** Useful for combining two or more datasets with different variables into a single set&lt;br /&gt;
&lt;br /&gt;
== Installation from Source ==&lt;br /&gt;
For information on how to build and install the NcML Data Module, please see the INSTALL file that came with the source distribution.&lt;br /&gt;
&lt;br /&gt;
= Installation Overview =&lt;br /&gt;
&lt;br /&gt;
The NcML Module requires a working Hyrax 1.6 installation.  It is a module&lt;br /&gt;
that is dynamically loaded into the Hyrax BES (Back End Server) to&lt;br /&gt;
allow it to handle NcML files.  &lt;br /&gt;
&lt;br /&gt;
Please see the file INSTALL for full build and install instructions as&lt;br /&gt;
well as requirements.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; After installation, you MUST restart Hyrax by restarting the BES and&lt;br /&gt;
OLFS so the NcML Module is loaded!&lt;br /&gt;
&lt;br /&gt;
== Requirement: International Components for Unicode (ICU) Library == &lt;br /&gt;
&lt;br /&gt;
The most important external requirement is an installation of the International Components for Unicode (ICU) version 3.6 or higher (tested up to 4.2.1).   The source distributions (as well as some binaries) may be found at the site: http://site.icu-project.org/download&lt;br /&gt;
&lt;br /&gt;
If you are using Linux RPM&#039;s to run Hyrax, you can get an RPM for ICU as well.  Search for the RPM named &amp;quot;libicu&amp;quot; using a package manager or yum, e.g.   If you are compiling the module from source, you will also need the RPM &amp;quot;libicu-devel&amp;quot; to get the headers installed.  &lt;br /&gt;
&lt;br /&gt;
If you install in the default locations, the ncml_module should find the libraries and headers.  Otherwise, please consult the INSTALL file for more information about installing ICU to a non-standard location.&lt;br /&gt;
&lt;br /&gt;
== Testing Installation ==&lt;br /&gt;
&lt;br /&gt;
Test data is provided to see if the installation was successful.  The file sample_virtual_dataset.ncml is a dataset purely created in NcML and doesn&#039;t contain an underlying dataset.  &lt;br /&gt;
You may also view fnoc1_improved.ncml to test adding attributes to an existing netCDF dataset (fnoc1.nc), but this requires the netCDF data handler to be&lt;br /&gt;
installed first!  Several other examples installed also use the HDF4 and HDF5 handlers.&lt;br /&gt;
&lt;br /&gt;
= Functionality =&lt;br /&gt;
&lt;br /&gt;
This version of the NcML Module implements a subset of NcML 2.2&lt;br /&gt;
functionality.  The reader is directed to http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/ for more information on NcML.&lt;br /&gt;
&lt;br /&gt;
Our module can currently:&lt;br /&gt;
&lt;br /&gt;
*Refer only to files being served locally (not remotely)&lt;br /&gt;
*Add, modify, and remove attribute metadata to a dataset&lt;br /&gt;
*Create a purely virtual dataset using just NcML and no underlying dataset&lt;br /&gt;
*Create new scalar variables of any simple NcML type or simple DAP type&lt;br /&gt;
*Create new Structure variables (which can contain new child variables)&lt;br /&gt;
*Create new N-dimensional arrays of simple types (NcML or DAP)&lt;br /&gt;
*Remove existing variables from a wrapped dataset&lt;br /&gt;
*Rename existing variables in a wrapped dataset&lt;br /&gt;
*Name dimensions as a mnemonic for specifying Array shapes&lt;br /&gt;
*Perform union aggregations on multiple datasets, virtual or wrapped or both&lt;br /&gt;
*Perform joinNew aggregations to merge a variable across multiple datasets by creating a new outer dimension&lt;br /&gt;
*Specify aggregation member datasets by scanning directories for files matching certain criteria&lt;br /&gt;
&lt;br /&gt;
We describe each supported NcML element in detail below.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;netcdf&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;netcdf&amp;gt; element is used to define a dataset, either a wrapped dataset that is to be modified, a pure virtual dataset, or a member dataset of an aggregation.  The &amp;lt;netcdf&amp;gt; element is assumed to be the topmost node, or as a child of an aggregation element.&lt;br /&gt;
&lt;br /&gt;
=== Local vs. Remote Datasets ===&lt;br /&gt;
&lt;br /&gt;
We assume that the location attribute (&#039;&#039;netcdf@location&#039;&#039;) refers to the full path (with respect to the BES data root directory) of a &#039;&#039;&#039;&#039;&#039;local&#039;&#039;&#039;&#039;&#039; dataset (served by the same Hyrax server).  The current version of the module cannot be used to modify remote datasets.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;netcdf@location&#039;&#039; is the empty string (or unspecified, as empty is the default), the dataset is a pure virtual dataset, fully specified within the NcML file itself.  Attributes and variables may be fully described and accessed with constraints just as normal datasets in this manner.  The installed sample datafile &amp;quot;sample_virtual_dataset.ncml&amp;quot; is an example test case for this functionality.&lt;br /&gt;
&lt;br /&gt;
=== Unsupported Attributes ===&lt;br /&gt;
&lt;br /&gt;
The current version does not support the following attributes of &amp;lt;netcdf&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
*enhance&lt;br /&gt;
*addRecords&lt;br /&gt;
*fmrcDefinition (will be supported when FMRC aggregation is added)&lt;br /&gt;
*ncoords (will be supported when joinExisting is added)&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;readMetadata&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;readMetadata/&amp;gt; element is the default, so is effectively not needed.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;explicit&amp;gt; element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;explicit/&amp;gt; element simply clears all attribute tables in the referred to netcdf@location before applying the rest of the &lt;br /&gt;
NcML transformations to the metadata.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;dimension&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;dimension&amp;gt; element has limited functionality in this release since the DAP2 doesn&#039;t support dimensions as more than mnemonics at this time.  The limitations are:&lt;br /&gt;
&lt;br /&gt;
* We only parse the &#039;&#039;dimension@name&#039;&#039; and &#039;&#039;dimension@length&#039;&#039; attributes.  &lt;br /&gt;
* Dimensions can only be specified as a direct child of a &amp;lt;netcdf&amp;gt; element prior to any reference to them&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt; &lt;br /&gt;
  &amp;lt;dimension name=&amp;quot;station&amp;quot; length=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;dimension name=&amp;quot;samples&amp;quot; length=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;!-- Some variable elements refer to the dimensions here --&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The dimension element sets up a mapping from the &#039;&#039;name&#039;&#039; to the unsigned integer &#039;&#039;length&#039;&#039; and can be used in a &#039;&#039;variable@shape&#039;&#039; to specify a length for an array dimension (see the section on &amp;lt;variable&amp;gt; below).  The dimension map is cleared when &amp;lt;/netcdf&amp;gt; is encountered (though this doesn&#039;t matter currently since we allow only one right now, but it will matter for aggregation, potentially).  We also do not support &amp;lt;group&amp;gt;, which is the only other legal place in NcML 2.2 for a dimension element.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* If the name and length are not both specified.&lt;br /&gt;
* If the dimension name already exists in the current scope&lt;br /&gt;
* If the length is not an unsigned integer&lt;br /&gt;
* If any of the other attributes specified in NcML 2.2 are used.  We do not handle them, so we consider them errors now.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;variable&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;variable&amp;gt; element is used to:&lt;br /&gt;
&lt;br /&gt;
* Provide lexical scope for a contained &amp;lt;attribute&amp;gt; or &amp;lt;variable&amp;gt; element&lt;br /&gt;
* Rename existing variables &lt;br /&gt;
* Add new scalar variables of simple types&lt;br /&gt;
* Add new Structure variables&lt;br /&gt;
* Add new N-dimensional Array&#039;s of simple types&lt;br /&gt;
* Specify the coordinate variable for the new dimension in a joinNew aggregation &lt;br /&gt;
&lt;br /&gt;
We describe each in turn in more detail.&lt;br /&gt;
&lt;br /&gt;
=== Specifying Lexical Scope with &amp;lt;variable type=&amp;quot;&amp;quot;&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Consider the following example:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;variable name=&amp;quot;u&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Metadata&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;This is metadata!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code assumes that a variable named &amp;quot;u&amp;quot; exists (of any type since we do not specify) and provides the lexical scope for the&lt;br /&gt;
attribute &amp;quot;Metadata&amp;quot; which will be added or modified within the attribute table for the variable &amp;quot;u&amp;quot; (it&#039;s qualified name would be &amp;quot;u.Metadata&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
==== Nested DAP Structure and Grid Scopes ====&lt;br /&gt;
&lt;br /&gt;
Scoping variable elements may be nested if the containing variable is a Structure (this includes the special case of Grid)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;DATA_GRANULE&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;PlanetaryGrid&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;variable name=&amp;quot;percipitate&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;inches&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This adds a &amp;quot;unit&amp;quot; attribute to the variable &amp;quot;percipitate&amp;quot; within the nested Structure&#039;s &lt;br /&gt;
(&amp;quot;DATA_GRANULE.PlanetaryGrid.percipitate&amp;quot; as fully qualified name).  &lt;br /&gt;
Note that we &#039;&#039;&#039;must&#039;&#039;&#039; refer to the type explicitly as a &amp;quot;Structure&amp;quot; so the parser knows&lt;br /&gt;
to traverse the tree.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; the variable might be of type Grid, but the type &amp;quot;Structure&amp;quot; must be used in the NcML to traverse it.&lt;br /&gt;
&lt;br /&gt;
==== Adding Multiple Attributes to the Same Variable ====&lt;br /&gt;
&lt;br /&gt;
Once the variable&#039;s scope is set by the opening &amp;lt;variable&amp;gt; element, more than one attribute can be specified within it.  This will make the NcML more readable and also will make the parsing more efficient since the variable will only need to be looked up once.&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_1&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Hello&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_2&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;World!&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
should be preferred over:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_1&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Hello&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_2&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;World!&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
although they produce the same result.  Any number of attributes can be specified before the variable is closed.&lt;br /&gt;
&lt;br /&gt;
=== Renaming Existing Variables ===&lt;br /&gt;
&lt;br /&gt;
The attribute &#039;&#039;variable@orgName&#039;&#039; is used to rename an existing variable. &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;NewName&amp;quot; orgName=&amp;quot;OldName&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing variable at the current scope named &amp;quot;OldName&amp;quot; to &amp;quot;NewName&amp;quot;.  After this point in the NcML file (such as in constraints specified for the DAP request), the variable is known by &amp;quot;NewName&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note that the type is not required here --- the variable is assumed to exist and its existing type is used.  It is not possible to change the type of an existing variable at this time!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:  &lt;br /&gt;
* If a variable with &#039;&#039;variable@orgName&#039;&#039; doesn&#039;t exist in the current scope&lt;br /&gt;
* If the new name &#039;&#039;variable@name&#039;&#039; is already taken in the current scope&lt;br /&gt;
* If a new variable is created but does not have exactly one values element&lt;br /&gt;
&lt;br /&gt;
=== Adding a New Scalar Variable ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;variable&amp;gt; element can be used to create a new scalar variable of a simple type (i.e. an atomic NcML type such as &amp;quot;int&amp;quot; or &amp;quot;float&amp;quot;, or any DAP atomic type, such as &amp;quot;UInt32&amp;quot; or &amp;quot;URL&amp;quot;) by specifying an empty &#039;&#039;variable@shape&#039;&#039; (which is the default), a simple type for &#039;&#039;variable@type&#039;&#039;, and a contained &amp;lt;values&amp;gt; element with the one value of correct type. &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;TheAnswerToLifeTheUniverseAndEverything&amp;quot; type=&amp;quot;double&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;SolvedBy&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;Deep Thought&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;values&amp;gt;42.000&amp;lt;/values&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create a new variable named &amp;quot;TheAnswerToLifeTheUniverseAndEverything&amp;quot; at the current scope.  It has no shape so will be a scalar of type &amp;quot;double&amp;quot; and will have the value 42.0.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* It is a parse error to not specify a &amp;lt;values&amp;gt; element with exactly one proper value of the variable type.&lt;br /&gt;
* It is a parse error to specify a malformed or out of bounds value for the data type&lt;br /&gt;
&lt;br /&gt;
=== Adding a New Structure Variable ===&lt;br /&gt;
&lt;br /&gt;
A new Structure variable can be specified at the global scope or within another Structure.  It is illegal for an array to have type structure, so the shape must be empty.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;MyNewStructure&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;MetaData&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;This is metadata!&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;ContainedScalar1&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&amp;lt;values&amp;gt;I live in a new structure!&amp;lt;/values&amp;gt;&amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;ContainedInt1&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;&amp;lt;values&amp;gt;42&amp;lt;/values&amp;gt;&amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
specifies a new structure called &amp;quot;MyNewStructure&amp;quot; which contains two scalar variable fields &amp;quot;ContainedScalar1&amp;quot; and &amp;quot;ContainedInt1&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
Nested structures are allowed as well.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Error&#039;&#039;&#039;: &lt;br /&gt;
* If another variable or attribute exists at the current scope with the new name.  &lt;br /&gt;
* If a &amp;lt;values&amp;gt; element is specified as a direct child of a new Structure --- structures cannot contain values, only attributes and other variables.&lt;br /&gt;
&lt;br /&gt;
=== Adding a New N-dimensional Array ===&lt;br /&gt;
&lt;br /&gt;
An N-dimensional array of a simple type may be created virtually as well by specifying a non-empty &#039;&#039;variable@shape&#039;&#039;.  The shape contains the array dimensions in left-to-right order of slowest varying dimension first.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;FloatArray&amp;quot; type=&amp;quot;float&amp;quot; shape=&amp;quot;2 5&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;!-- values specified in row major order (leftmost dimension in shape varies slowest) &lt;br /&gt;
	Any whitespace is a valid separator by default, so we can use newlines to pretty print 2D matrices.&lt;br /&gt;
	--&amp;gt;&lt;br /&gt;
      &amp;lt;values&amp;gt;&lt;br /&gt;
	0.1 0.2 0.3 0.4 0.5&lt;br /&gt;
	1.1 1.1 1.3 1.4 1.5&lt;br /&gt;
      &amp;lt;/values&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will specify a 2x5 dimension array of float values called &amp;quot;FloatArray&amp;quot;.  The &amp;lt;values&amp;gt; element must contain 2x5=10 values in row major order (slowest varying dimension first).  Since whitespace is the default separator, we use a newline to show the dimension boundary for the values, which is easy to see for a 2D matrix such as this.&lt;br /&gt;
&lt;br /&gt;
A dimension name may also be used to refer mnemonically to a length.  The DAP response will use this mnemonic in its output, but it is not currently used for shared dimensions, only as a mnemonic.   See the section on the &amp;lt;dimension&amp;gt; element for more information.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt;&lt;br /&gt;
 &amp;lt;dimension name=&amp;quot;station&amp;quot; length=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;dimension name=&amp;quot;sample&amp;quot; length=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;FloatArray&amp;quot; type=&amp;quot;float&amp;quot; shape=&amp;quot;station sample&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;values&amp;gt;&lt;br /&gt;
	0.1 0.2 0.3 0.4 0.5&lt;br /&gt;
	1.1 1.1 1.3 1.4 1.5&lt;br /&gt;
      &amp;lt;/values&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will produce the same 2x5 array, but will incorporate the dimension mnemonics into the response.  For example, here&#039;s the DDS response:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
     Float32 FloatArray[station = 2][samples = 5];&lt;br /&gt;
} sample_virtual_dataset.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;values&amp;gt; element respects the &#039;&#039;values@separator&#039;&#039; attribute if whitespace isn&#039;t correct.  This is very useful for arrays of strings with whitespace, for example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;StringArray&amp;quot; type=&amp;quot;string&amp;quot; shape=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;values separator=&amp;quot;*&amp;quot;&amp;gt;String 1*String 2*String 3&amp;lt;/values&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
creates a length 3 array of string StringArray = {&amp;quot;String 1&amp;quot;, &amp;quot;String 2&amp;quot;, &amp;quot;String 3&amp;quot;}.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:  &lt;br /&gt;
* It is an error to specify the incorrect number of values&lt;br /&gt;
* It is an error if any value is malformed or out of range for the data type.&lt;br /&gt;
* It is an error to specify a named dimension which does not exist in the current &amp;lt;netcdf&amp;gt; scope.&lt;br /&gt;
* It is an error to specify an Array whose flattened size (product of dimensions) is &amp;gt; 2^31-1.&lt;br /&gt;
&lt;br /&gt;
=== Specifying the new coordinate variable for a joinNew aggregation ===&lt;br /&gt;
&lt;br /&gt;
In the special case of a joinNew aggregation, the new coordinate variable may be specified with the &amp;lt;variable&amp;gt; element.  The new coordinate variable is &#039;&#039;defined&#039;&#039; to have the same name as the new dimension.  This allows for several things:&lt;br /&gt;
&lt;br /&gt;
*Explicit specification of the variable type and coordinates for the new dimension&lt;br /&gt;
*Specification of the metadata for the new coordinate variable &lt;br /&gt;
&lt;br /&gt;
In the first case, the author can specify explicitly the type of the new coordinate variable and the actual values for each dataset.  In this case, the variable &#039;&#039;must&#039;&#039; be specified &#039;&#039;after&#039;&#039; the aggregation element in the file so the new dimension&#039;s size (number of member datasets) may be known and error checking performed.  Metadata can also be added to the variable here.&lt;br /&gt;
&lt;br /&gt;
In the second case, the author may just specify the variable name, which allows one to specify the metadata for a coordinate variable that is automatically generated by the aggregation itself.  This is the only allowable case for a variable element to &#039;&#039;not&#039;&#039; contain a values element!  Coordinate variables are generated automatically in two cases:&lt;br /&gt;
&lt;br /&gt;
*The author has specified an explicit list of member datasets, with or without explicit coordVal attributes.  &lt;br /&gt;
*The author has used a &amp;lt;scan&amp;gt; element to specify the member datasets via a directory scan&lt;br /&gt;
&lt;br /&gt;
In this case, the &amp;lt;variable&amp;gt; element may come before or after the &amp;lt;aggregation&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*If an explicit variable is declared for the new coordinate variable:&lt;br /&gt;
** And it contains explicit values, the number of values must be equal to the number of member datasets in the aggregation.&lt;br /&gt;
** It must be specifed &#039;&#039;after&#039;&#039; the &amp;lt;aggregation&amp;gt; element&lt;br /&gt;
&lt;br /&gt;
* If a numeric coordVal is used to specify the first member dataset&#039;s coordinate, then &#039;&#039;all&#039;&#039; datasets must contain a numerical coordinate.&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variable (variableAgg) is not found in &#039;&#039;all&#039;&#039; member datasets.&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variable is not of the same type in &#039;&#039;all&#039;&#039; member datasets.  Coercion is &#039;&#039;not&#039;&#039; performed!&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variables in all member datasets do not have the same shape&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if an explicit coordinate variable is specified with a shape that is &#039;&#039;not&#039;&#039; the same as the new dimension name (and the variable name itself).&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;values&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;values&amp;gt; element can only be used in the context of a &#039;&#039;&#039;new&#039;&#039;&#039; variable of scalar or array type.  We cannot change the values for existing variables in this version of the handler. &lt;br /&gt;
The characters content of a &amp;lt;values&amp;gt; element is considered to be a separated list of value tokens valid for the type of the variable of the parent element.  The number of specified tokens in the content &#039;&#039;must&#039;&#039; equal the product of the dimensions of the enclosing &#039;&#039;variable@shape&#039;&#039;, or be one value for a scalar.  It is an error to &#039;&#039;not&#039;&#039; specify a &amp;lt;values&amp;gt; element for a declared new variable as well.  &lt;br /&gt;
&lt;br /&gt;
=== Changing the Separator Tokens === &lt;br /&gt;
&lt;br /&gt;
The author may specify values@separator to change the default value token separator from the default whitespace.  This is very useful for specifying arrays of strings with whitespace in them, or if data in CSV form is being pasted in.  &lt;br /&gt;
&lt;br /&gt;
=== Autogeneration of Uniform Arrays ===&lt;br /&gt;
&lt;br /&gt;
We also can parse &#039;&#039;values@start&#039;&#039; and &#039;&#039;values@increment&#039;&#039; INSTEAD OF tokens in the content.  This will &amp;quot;autogenerate&amp;quot; a uniform array of values of the given product of dimensions length for the containing variable.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Evens&amp;quot; type=&amp;quot;int&amp;quot; shape=&amp;quot;100&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;values start=&amp;quot;0&amp;quot; increment=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will specify an array of the first 100 even numbers (including 0).  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* If the incorrect number of tokens are specified for the containing variable&#039;s shape&lt;br /&gt;
* If any value token cannot be parsed as a valid value for the containing variable&#039;s type&lt;br /&gt;
* If content is specified in addition to start and increment&lt;br /&gt;
* If only one of start or increment is specified&lt;br /&gt;
* If the values element is placed anywhere except within a NEW variable.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;attribute&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
As an overview, whenever the parser encounters an &amp;lt;attribute&amp;gt; with a non-existing name (at the current scope),&lt;br /&gt;
it creates a new one, whether a container or atomic attribute (see below).  If the attribute exists,&lt;br /&gt;
its value and/or type is modified to those specified in the &amp;lt;attribute&amp;gt; element.  If an attribute&lt;br /&gt;
structure (container) exists, it is used to define a nested lexical scope for child attributes.  &lt;br /&gt;
&lt;br /&gt;
Attributes may be scalar (one value) or one dimensional arrays.  Arrays are specified by using whitespace (default) to separate the different values.  The attribute@separator may also be set in order to specify a different separator, such as CSV format or to specify a non-whitespace separator so strings with whitespace are not tokenized.  We will give examples of creating array attributes below.&lt;br /&gt;
&lt;br /&gt;
=== Adding New Attributes or Modifying an Existing Attribute ===&lt;br /&gt;
&lt;br /&gt;
If a specified attribute with the attribute@name does not exist at the current lexical scope, &lt;br /&gt;
a new one is created with the given type and value.  For example, assume &amp;quot;new_metadata&amp;quot; doesn&#039;t&lt;br /&gt;
exist at the current parse scope.  Then:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;new_metadata&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;This is a new entry!&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create the attribute at that scope.  Note that value can be specified in the content of the &lt;br /&gt;
element as well.  This is identical to the above:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;new_metadata&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;This is a new entry!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the attribute@name already exists at the scope, it is modified to contain the specified type and value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Arrays ====&lt;br /&gt;
&lt;br /&gt;
As in NcML, for numerical types an array can be specified by separating the tokens by whitespace (default) or be&lt;br /&gt;
specifying the token separator with attribute@separator.  For example,&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;myArray&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 2 3&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;myArray&amp;quot; type=&amp;quot;int&amp;quot; separator=&amp;quot;,&amp;quot;&amp;gt;1,2,3&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
both specify the same array of three integers named &amp;quot;myArray&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
TODO Add more information on splitting with a separator!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Structures (Containers) ====&lt;br /&gt;
&lt;br /&gt;
We use attribute@type=&amp;quot;Structure&amp;quot; to define a new (or existing) attribute container.   So if we&lt;br /&gt;
wanted to add a new attribute structure, we&#039;d use something like this: &lt;br /&gt;
&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;MySamples&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Location&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Station 1&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Samples&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 4 6&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assuming &amp;quot;MySamples&amp;quot; doesn&#039;t already exist, an attribute container will be created at the current scope&lt;br /&gt;
and the &amp;quot;Location&amp;quot; and &amp;quot;Samples&amp;quot; attributes will be added to it.&lt;br /&gt;
&lt;br /&gt;
Note that we can create nested attribute structures to arbitrary depth this way as well.&lt;br /&gt;
&lt;br /&gt;
If the attribute container with the given name already exists at the current scope, &lt;br /&gt;
then the attribute@type=&amp;quot;Structure&amp;quot; form is used to define&lt;br /&gt;
the lexical scope for the container.  In other words, child &amp;lt;attribute&amp;gt; elements will&lt;br /&gt;
be processed within the scope of the container.   For example, in the above example, if&lt;br /&gt;
&amp;quot;MySamples&amp;quot; already exists, then the &amp;quot;Location&amp;quot; and &amp;quot;Samples&amp;quot; will be processed within the&lt;br /&gt;
existing container (they may or may not already exist as well).&lt;br /&gt;
&lt;br /&gt;
==== Renaming an Existing Attribute or Attribute Container ====&lt;br /&gt;
&lt;br /&gt;
We also support the attribute@orgName attribute for renaming attributes.   &lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;NewName&amp;quot; orgName=&amp;quot;OldName&amp;quot; type=&amp;quot;string&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing attribute &amp;quot;OldName&amp;quot; to &amp;quot;NewName&amp;quot; while leaving its value alone.&lt;br /&gt;
If attribute@value is also specified, then the attribute is renamed &#039;&#039;and&#039;&#039; has its value modified.&lt;br /&gt;
&lt;br /&gt;
This works for renaming attribute containers as well:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;MyNewContainer&amp;quot; orgName=&amp;quot;MyOldContainer&amp;quot; type=&amp;quot;Structure&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing &amp;quot;MyOldContainer&amp;quot; to &amp;quot;MyNewContainer&amp;quot;.  Note that any children&lt;br /&gt;
of this container will remain in it.&lt;br /&gt;
&lt;br /&gt;
=== DAP &#039;&#039;OtherXML&#039;&#039; Extension ===&lt;br /&gt;
&lt;br /&gt;
The module now allows specification of attributes of the new DAP type &amp;quot;OtherXML&amp;quot;.  This allows the NCML file author to inject arbitrary well-formed XML into an attribute for clients that want XML metadata rather than just string or url.  Internally, the attribute is still a string (and in a DAP DAS response will be quoted inside one string).  However, since it is XML, the NCMLParser still parses it and checks it for well-formedness (but NOT against schemas).  This extension allows the NCMLParser to parse the arbitrary XML within the given attribute without causing errors, since it can be any XML.  &lt;br /&gt;
&lt;br /&gt;
The injected XML is most useful in the DDX response, where it shows up directly in the response as XML.  XSLT and other clients can then parse it.&lt;br /&gt;
&lt;br /&gt;
==== Errors ====&lt;br /&gt;
&lt;br /&gt;
*The XML &#039;&#039;&#039;must&#039;&#039;&#039; be in the content of the &amp;lt;attribute type=&amp;quot;OtherXML&amp;quot;&amp;gt; element.  It is a parser error for &#039;&#039;attribute@value&#039;&#039; to be set if &#039;&#039;attribute@type&#039;&#039; is &amp;quot;OtherXML&amp;quot;.  &lt;br /&gt;
*The XML must also be well-formed since it is parsed.  A parse error will be thrown if the OtherXML is malformed.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of the use of this special case.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf xmlns=&amp;quot;http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2&amp;quot; location=&amp;quot;/coverage/200803061600_HFRadar_USEGC_6km_rtv_SIO.nc&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;someName&amp;quot; type=&amp;quot;OtherXML&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;Domain xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot; &lt;br /&gt;
                xmlns:ows=&amp;quot;http://www.opengis.net/ows/1.1&amp;quot;&lt;br /&gt;
                xmlns:gml=&amp;quot;http://www.opengis.net/gml/3.2&amp;quot;&lt;br /&gt;
                &amp;gt;&lt;br /&gt;
            &amp;lt;SpatialDomain&amp;gt;&lt;br /&gt;
                &amp;lt;ows:BoundingBox crs=&amp;quot;urn:ogc:def:crs:EPSG::4326&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;ows:LowerCorner&amp;gt;-97.8839 21.736&amp;lt;/ows:LowerCorner&amp;gt;&lt;br /&gt;
                    &amp;lt;ows:UpperCorner&amp;gt;-57.2312 46.4944&amp;lt;/ows:UpperCorner&amp;gt;&lt;br /&gt;
                &amp;lt;/ows:BoundingBox&amp;gt;&lt;br /&gt;
            &amp;lt;/SpatialDomain&amp;gt;&lt;br /&gt;
            &amp;lt;TemporalDomain&amp;gt;&lt;br /&gt;
                &amp;lt;gml:timePosition&amp;gt;2008-03-27T16:00:00.000Z&amp;lt;/gml:timePosition&amp;gt;&lt;br /&gt;
            &amp;lt;/TemporalDomain&amp;gt;&lt;br /&gt;
        &amp;lt;/Domain&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedCRS xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;urn:ogc:def:crs:EPSG::4326&amp;lt;/SupportedCRS&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedFormat xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;netcdf-cf1.0&amp;lt;/SupportedFormat&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedFormat xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;dap2.0&amp;lt;/SupportedFormat&amp;gt;&lt;br /&gt;
    &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039; Put the DDX response for the above in here!&lt;br /&gt;
&lt;br /&gt;
====Namespace Closure====&lt;br /&gt;
&lt;br /&gt;
Furthermore, the parser will make the chunk of OtherXML &amp;quot;namespace closed&amp;quot;.  This means any namespaces specified in parent NCML elements of the OtherXML tree will be &amp;quot;brought down&amp;quot; and added to the &#039;&#039;root&#039;&#039; OtherXML elements so that the subtree may be pulled out and added to the DDX and still have its namespaces.  The algorithm doesn&#039;t just bring used prefixes, but brings &#039;&#039;all&#039;&#039; of the lexically scoped closest namespaces in all ancestors.  In other words, it adds unique namespaces (as determined by prefix) in order from the root of the OtherXML tree as it traverses to the root of the NCML document.  &lt;br /&gt;
&lt;br /&gt;
Namespace closure is a syntactic sugar that simplifies the author&#039;s task since they can specify the namespaces just once at the top of the NCML file and expect that when the subtree of XML is added to the DDX that these namespaces will come along with that subtree of XML.  Otherwise they have to explicitly add the namespaces to each attributes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039; Add an example!&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;remove&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;remove&amp;gt; element can remove attributes and variables.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;attribute name=&amp;quot;NC_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;remove name=&amp;quot;base_time&amp;quot; type=&amp;quot;attribute&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will remove the attribute named &amp;quot;base_time&amp;quot; in the attribute structure named &amp;quot;NC_GLOBAL&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Note that this works for attribute containers as well!  We could recursively remove the &#039;&#039;entire&#039;&#039;&lt;br /&gt;
attribute container (i.e. it and all its children) with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;remove name=&amp;quot;NC_GLOBAL&amp;quot; type=&amp;quot;attribute&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It also can be used to remove variables from existing datasets:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
  &amp;lt;remove name=&amp;quot;SomeExistingVariable&amp;quot; type=&amp;quot;variable&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This also recurses on variables of type Structure --- the entire structure including all of its children are removed from the dataset&#039;s response.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* It is a parse error if the given attribute or variable doesn&#039;t exist in the current scope&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;aggregation&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
Aggregation involves combining multiple datasets (&amp;lt;netcdf&amp;gt;) into a virtual &amp;quot;single&amp;quot; dataset in various ways.  For a tutorial on aggregation in NcML 2.2, the reader is referred to the Unidata page: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Aggregation.html&lt;br /&gt;
&lt;br /&gt;
NcML 2.2 supports multiple types of aggregation: union, joinNew, joinExisting, and fmrc (forecast model run collection).  &lt;br /&gt;
&lt;br /&gt;
The current version of the NcML module supports two of these aggregations:&lt;br /&gt;
&lt;br /&gt;
*Union [[NCML_Module_Aggregation_Union]]&lt;br /&gt;
*JoinNew [[NCML_Module_Aggregation_JoinNew]]&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;union&#039;&#039; aggregation specifies that the first instance of a variable or attribute (by name) that is found in the ordered list of datasets will be the one in the output aggregation.   This is useful for combining two dataset files, each which may contain a single variable, into a composite dataset with both variables.&lt;br /&gt;
&lt;br /&gt;
A JoinNew aggregation joins a variable which exists in multiple datasets (usually samples of a datum over time) into a new variable containing the data from &#039;&#039;all&#039;&#039; member datasets by creating a new outer dimension.  The &#039;&#039;i&#039;&#039;th component in the new outer dimension is the variable&#039;s data from the &#039;&#039;i&#039;&#039;th member dataset.  It also adds a new coordinate variable of whose name is the new dimension&#039;s name and whose shape (length) is the new dimension as well.  This new coordinate variable may be explicitly given by the author or may be autogenerated in one of several ways.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;scan&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The scan element can be used within an aggregation context to allow a directory to be searched in various ways in order to specify the members of an aggregation.  This allows a static NcML file to refer to an aggregation which may change over time, such as where a new data file is generated each day.&lt;br /&gt;
&lt;br /&gt;
We describe usage of the &amp;lt;scan&amp;gt; element in detail in the joinNew aggregation tutorial at [[NCML_Module_Aggregation_JoinNew]].&lt;br /&gt;
&lt;br /&gt;
= Errors =&lt;br /&gt;
&lt;br /&gt;
There are three types of error messages that may be returned:&lt;br /&gt;
&lt;br /&gt;
* Internal Error&lt;br /&gt;
* Resource Not Found Error&lt;br /&gt;
* Parse Error&lt;br /&gt;
&lt;br /&gt;
== Internal Errors ==&lt;br /&gt;
&#039;&#039;&#039;Internal errors&#039;&#039;&#039; should be reported to support@opendap.org as they are likely bugs.&lt;br /&gt;
&lt;br /&gt;
== Resource Not Found Errors ==&lt;br /&gt;
&lt;br /&gt;
If the netcdf@location specifies a non-existent local dataset (one that is not being served by&lt;br /&gt;
the same Hyrax server), it will specify the resource was not found.   This may also be returned&lt;br /&gt;
if a handler for the specified dataset is not currently loaded in the BES.  Users should test that the&lt;br /&gt;
dataset to be wrapped already exists and can be viewed on the running server before writing NcML &lt;br /&gt;
to add metadata.  It&#039;s also an error to refer to remote datasets (at this time).&lt;br /&gt;
&lt;br /&gt;
== Parse Errors ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse errors&#039;&#039;&#039; are user errors in the NcML file.  These could be malformed XML, malformed NcML, &lt;br /&gt;
unimplemented features of NcML, or could be errors in referring to the wrapped dataset.  &lt;br /&gt;
&lt;br /&gt;
The error message should specify &lt;br /&gt;
the error condition as well as the &amp;quot;current scope&amp;quot; as a fully qualified DAP name within the &lt;br /&gt;
loaded dataset.  This should be enough information to correct the parse error as new NcML&lt;br /&gt;
files are created.&lt;br /&gt;
&lt;br /&gt;
The parser will generate parse errors in various &lt;br /&gt;
situations where it expects to find certain structure in the underlying dataset.  Some examples:&lt;br /&gt;
&lt;br /&gt;
* A variable of the given name was not found at the current scope&lt;br /&gt;
* attribute@orgName was specified, but the attribute cannot be found at current scope.&lt;br /&gt;
* attribute@orgName was specified, but the new name is already used at current scope.&lt;br /&gt;
* remove specified a non-existing attribute name&lt;br /&gt;
&lt;br /&gt;
= Grid Metadata Tutorial =&lt;br /&gt;
&lt;br /&gt;
Please see the page [[Grid_Metadata_Tutorial]] for an example of adding metadata to the various parts of a DAP Grid variable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Aggregation Tutorials =&lt;br /&gt;
&lt;br /&gt;
The NcML module may also be used to aggregate multiple datasets into one virtual dataset.  We currently support two of the NcML aggregtions:&lt;br /&gt;
&lt;br /&gt;
*Union [[NCML_Module_Aggregation_Union]]:  combine multiple datasets into one by merging variables together, selecting the first of each unique name.&lt;br /&gt;
*JoinNew [[NCML_Module_Aggregation_JoinNew]]: combine variables across multiple datasets by creating a new outer dimension and coordinate variable for each of the sample datasets.&lt;br /&gt;
&lt;br /&gt;
Please see the sections for a tutorial on the various uses of these aggregations.&lt;br /&gt;
&lt;br /&gt;
= Additions/Changes to NcML 2.2 =&lt;br /&gt;
&lt;br /&gt;
This section will keep track of changes to the NcML 2.2 schema.  Eventually these&lt;br /&gt;
will be rolled into a new schema.&lt;br /&gt;
&lt;br /&gt;
== Attribute Structures (Containers) ==&lt;br /&gt;
This module also adds functionality beyond the current NcML 2.2 schema&lt;br /&gt;
--- it can handle nested &amp;lt;attribute&amp;gt; elements in order to make&lt;br /&gt;
attribute structures.  This is done by using the &amp;lt;attribute&lt;br /&gt;
type=&amp;quot;Structure&amp;quot;&amp;gt; form, for example:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;MySamples&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Location&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Station 1&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Samples&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 4 6&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;MyContainer&amp;quot; describes an attribute structure with two attribute fields,&lt;br /&gt;
a string &amp;quot;Location&amp;quot; and an array of int&#039;s called &amp;quot;Samples&amp;quot;.  &lt;br /&gt;
Note that an attribute structure of this form can&lt;br /&gt;
only contain other &amp;lt;attribute&amp;gt; elements and NOT a value.&lt;br /&gt;
&lt;br /&gt;
If the container does not already exist, it will be created at the scope it is declared, which could&lt;br /&gt;
be:&lt;br /&gt;
&lt;br /&gt;
* Global (top of dataset)&lt;br /&gt;
* Within a variable&#039;s attribute table&lt;br /&gt;
* Within another attribute container&lt;br /&gt;
&lt;br /&gt;
If an attribute container of the given name already exists at the lexical scope, it is traversed &lt;br /&gt;
in order to define the scope for the nested (children) attributes it contains.&lt;br /&gt;
&lt;br /&gt;
== Unspecified Variable Type Matching for Lexical Scope ==&lt;br /&gt;
&lt;br /&gt;
We also allow the type attribute of a variable element (variable@type) to be the empty string &lt;br /&gt;
(or unspecified) when using existing variables to define the lexical scope of an &amp;lt;attribute&amp;gt; &lt;br /&gt;
transformation.  In the schema, variable@type is (normally) required.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DAP 2 Types ==&lt;br /&gt;
&lt;br /&gt;
Additionally, we allow DAP2 atomic types (such as UInt32, URL) in addition to the NcML types.  &lt;br /&gt;
The NcML types are mapped onto the closest DAP2 type internally.&lt;br /&gt;
&lt;br /&gt;
== DAP OtherXML Attribute Type ==&lt;br /&gt;
&lt;br /&gt;
We also allow attributes to be of the new DAP type &amp;quot;OtherXML&amp;quot; for injecting arbitrary XML into an attribute as content rather than trying to form a string.  This allows the parser to check well-formedness.&lt;br /&gt;
&lt;br /&gt;
== Forward Declaration of Dimensions ==&lt;br /&gt;
&lt;br /&gt;
Since we use a SAX parser for efficiency, we require the &amp;lt;dimension&amp;gt; elements to come &#039;&#039;before&#039;&#039; their use in a &#039;&#039;variable@shape&#039;&#039;.  One way to change the schema to allow this is to force the dimension elements to be specified in a sequence after explicit and metadata choice and before all other elements.&lt;br /&gt;
&lt;br /&gt;
== Aggregation Element Location and Processing Order Differences ==&lt;br /&gt;
&lt;br /&gt;
NcML specifies that if a dataset (&amp;lt;netcdf&amp;gt; element) specifies an aggregation element, the aggregation element is always processed first, regardless of its ordering within the &amp;lt;netcdf&amp;gt; element.  Our parser, since it is SAX and not DOM, modifies this behavior in that order matters in some cases:&lt;br /&gt;
&lt;br /&gt;
* Metadata (&amp;lt;attribute&amp;gt;) elements specified &#039;&#039;prior&#039;&#039; to an aggregation &amp;quot;shadow&amp;quot; the aggregation versions.  This is be useful for &amp;quot;overriding&amp;quot; an attribute or variable in a union aggregation, where the first found will take precedence. &lt;br /&gt;
* JoinNew: If the new coordinate variable&#039;s data is to be set explicitly by specifying the new dimension&#039;s shape (either with explicit data or the autogenerated data using values@start and values@increment attributes), the &amp;lt;variable&amp;gt; &#039;&#039;must&#039;&#039; come after the aggregation since the size of the dimension is unknown until the aggregation element is processed.&lt;br /&gt;
&lt;br /&gt;
= Backward Compatibility Issues =&lt;br /&gt;
&lt;br /&gt;
Due to the way shared dimensions were implemented in the NetCDF, HDF4, and HDF5 handlers, the DAS responses did not follow the DAP2 specification.  The NcML module, on the other hand, generates DAP2 compliant DAS for these datasets, which means that wrapping some datasets in NcML will generate a DAS with a different structure.  This is important for the NcML author since it changes the names of attributes and variables.  In order for the module to find the correct scope for adding metadata, for example, the DAP2 DAS must be used.  &lt;br /&gt;
&lt;br /&gt;
In general, what this means is that an empty &amp;quot;passthrough&amp;quot; NcML file should be the starting point for authoring an NcML file.  This file would just specify a dataset and nothing else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;/data/ncml/myNetcdf.nc&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The author would then request the DAS response for the NCML file and use that as the starting point for modifications to the original dataset. &lt;br /&gt;
&lt;br /&gt;
More explicit examples are given below.&lt;br /&gt;
&lt;br /&gt;
== NetCDF ==&lt;br /&gt;
&lt;br /&gt;
The NetCDF handler represents some NC datasets as a DAP 2 Grid, but the returned DAS is not consistent with the DAP 2 spec for the attribute hierarchy for such a Grid.  The map vector attributes are placed as siblings of the grid attributes rather than within the grid lexical scope.  For example, here&#039;s the NetCDF Handler DDS for a given file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Int16 cldc[time = 456][lat = 21][lon = 360];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 456];&lt;br /&gt;
        Float32 lat[lat = 21];&lt;br /&gt;
        Float32 lon[lon = 360];&lt;br /&gt;
    } cldc;&lt;br /&gt;
} cldc.mean.nc;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
showing the Grid.  Here&#039;s the DAS the NetCDF handler generates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    lat {&lt;br /&gt;
        String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
        String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
        Float32 actual_range 10.00000000, -10.00000000;&lt;br /&gt;
    }&lt;br /&gt;
    lon {&lt;br /&gt;
        String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
        String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
        Float32 actual_range 0.5000000000, 359.5000000;&lt;br /&gt;
    }&lt;br /&gt;
    time {&lt;br /&gt;
        String units &amp;quot;days since 1-1-1 00:00:0.0&amp;quot;;&lt;br /&gt;
        String long_name &amp;quot;Time&amp;quot;;&lt;br /&gt;
        String delta_t &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
        String avg_period &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
        Float64 actual_range 715511.00000000000, 729360.00000000000;&lt;br /&gt;
    }&lt;br /&gt;
    cldc {&lt;br /&gt;
        Float32 valid_range 0.000000000, 8.000000000;&lt;br /&gt;
        Float32 actual_range 0.000000000, 8.000000000;&lt;br /&gt;
        String units &amp;quot;okta&amp;quot;;&lt;br /&gt;
        Int16 precision 1;&lt;br /&gt;
        Int16 missing_value 32766;&lt;br /&gt;
        Int16 _FillValue 32766;&lt;br /&gt;
        String long_name &amp;quot;Cloudiness Monthly Mean at Surface&amp;quot;;&lt;br /&gt;
        String dataset &amp;quot;COADS 1-degree Equatorial Enhanced\\012AI&amp;quot;;&lt;br /&gt;
        String var_desc &amp;quot;Cloudiness\\012C&amp;quot;;&lt;br /&gt;
        String level_desc &amp;quot;Surface\\0120&amp;quot;;&lt;br /&gt;
        String statistic &amp;quot;Mean\\012M&amp;quot;;&lt;br /&gt;
        String parent_stat &amp;quot;Individual Obs\\012I&amp;quot;;&lt;br /&gt;
        Float32 add_offset 3276.500000;&lt;br /&gt;
        Float32 scale_factor 0.1000000015;&lt;br /&gt;
    }&lt;br /&gt;
    NC_GLOBAL {&lt;br /&gt;
        String title &amp;quot;COADS 1-degree Equatorial Enhanced&amp;quot;;&lt;br /&gt;
        String history &amp;quot;&amp;quot;;&lt;br /&gt;
        String Conventions &amp;quot;COARDS&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    DODS_EXTRA {&lt;br /&gt;
        String Unlimited_Dimension &amp;quot;time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the map vector attributes are in the &amp;quot;dataset&amp;quot; scope.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the DAS that the NcML Module produces from the correctly formed DDX:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    NC_GLOBAL {&lt;br /&gt;
        String title &amp;quot;COADS 1-degree Equatorial Enhanced&amp;quot;;&lt;br /&gt;
        String history &amp;quot;&amp;quot;;&lt;br /&gt;
        String Conventions &amp;quot;COARDS&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    DODS_EXTRA {&lt;br /&gt;
        String Unlimited_Dimension &amp;quot;time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    cldc {&lt;br /&gt;
        Float32 valid_range 0.000000000, 8.000000000;&lt;br /&gt;
        Float32 actual_range 0.000000000, 8.000000000;&lt;br /&gt;
        String units &amp;quot;okta&amp;quot;;&lt;br /&gt;
        Int16 precision 1;&lt;br /&gt;
        Int16 missing_value 32766;&lt;br /&gt;
        Int16 _FillValue 32766;&lt;br /&gt;
        String long_name &amp;quot;Cloudiness Monthly Mean at Surface&amp;quot;;&lt;br /&gt;
        String dataset &amp;quot;COADS 1-degree Equatorial Enhanced\\012AI&amp;quot;;&lt;br /&gt;
        String var_desc &amp;quot;Cloudiness\\012C&amp;quot;;&lt;br /&gt;
        String level_desc &amp;quot;Surface\\0120&amp;quot;;&lt;br /&gt;
        String statistic &amp;quot;Mean\\012M&amp;quot;;&lt;br /&gt;
        String parent_stat &amp;quot;Individual Obs\\012I&amp;quot;;&lt;br /&gt;
        Float32 add_offset 3276.500000;&lt;br /&gt;
        Float32 scale_factor 0.1000000015;&lt;br /&gt;
        cldc {&lt;br /&gt;
        }&lt;br /&gt;
        time {&lt;br /&gt;
            String units &amp;quot;days since 1-1-1 00:00:0.0&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;Time&amp;quot;;&lt;br /&gt;
            String delta_t &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
            String avg_period &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
            Float64 actual_range 715511.00000000000, 729360.00000000000;&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
            Float32 actual_range 10.00000000, -10.00000000;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
            Float32 actual_range 0.5000000000, 359.5000000;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here the Grid Structure &amp;quot;cldc&amp;quot;  and its contained data array (of the same name &amp;quot;cldc&amp;quot;) and map vectors have their own attribute containers as DAP 2 specifies.&lt;br /&gt;
&lt;br /&gt;
What this means for the author of an NcML file adding metadata to a NetCDF dataset that returns a Grid is that they should generate a &amp;quot;passthrough&amp;quot; file and get the DAS and then specify modifications based on that structure.  &lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example passthrough:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/cldc.mean.nc&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For example, to add an attribute to the map vector &amp;quot;lat&amp;quot; in the above, we&#039;d need the following NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/cldc.mean.nc&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;!-- Traverse into the Grid as a Structure --&amp;gt;&lt;br /&gt;
  &amp;lt;variable name=&amp;quot;cldc&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Traverse into the &amp;quot;lat&amp;quot; map vector (Array) --&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lat&amp;quot;&amp;gt; &lt;br /&gt;
      &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;I am a new attribute in the Grid map vector named lat!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lon&amp;quot;&amp;gt; &lt;br /&gt;
      &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;I am a new attribute in the Grid map vector named lon!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This clearly shows that the structure of the Grid must be used in the NcML:  the attribute being added is technically &amp;quot;cldc.lat.Description&amp;quot; in a fully qualified name.  The parser would return an error if it was attempted as &amp;quot;lat.Description&amp;quot; as the NetCDF DAS for the original file would have led one to believe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== HDF4/HDF5 ==&lt;br /&gt;
&lt;br /&gt;
Similarly to the NetCDF case, the Hyrax HDF4 Module produces DAS responses that do not respect the DAP2 specification.  If an NcML file is used to &amp;quot;wrap&amp;quot; an HDF4 dataset, the&lt;br /&gt;
correct DAP2 DAS response will be generated, however. &lt;br /&gt;
&lt;br /&gt;
This is important for those writing NcML for HDF4 data since the&lt;br /&gt;
lexical scope for attributes relies on the correct DAS form --- to&lt;br /&gt;
handle this, the user should start with a &amp;quot;passthrough&amp;quot; NcML file (see the above NetCDF example) and&lt;br /&gt;
use the DAS from that as the starting point for knowing the structure&lt;br /&gt;
the NcML handler expects to see in the NcML file.  Alternatively, the DDX has the &lt;br /&gt;
proper attribute structure as well (the DAS is generated from it).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Known Bugs =&lt;br /&gt;
&lt;br /&gt;
There are no known bugs currently.&lt;br /&gt;
&lt;br /&gt;
= Planned Future Enhancements =&lt;br /&gt;
&lt;br /&gt;
Planned enhancements for future versions of the module include:&lt;br /&gt;
&lt;br /&gt;
* New NcML Aggregations&lt;br /&gt;
** JoinExisting&lt;br /&gt;
*** Joins a variable across multiple datasets by appending the data for a given dimension from each dataset &lt;br /&gt;
*** Will also allow directory scans for specifying the aggregation&lt;br /&gt;
** Forecast Model Run Collection (FMRC)&lt;br /&gt;
*** Special case of JoinNew for forecast data with two time variables&lt;br /&gt;
*** See: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/FmrcAggregation.html&lt;br /&gt;
&lt;br /&gt;
= Copyright =&lt;br /&gt;
&lt;br /&gt;
This software is copyrighted under the GNU Lesser GPL.  Please see the&lt;br /&gt;
files COPYING and COPYRIGHT that came with this distribution.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5649</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5649"/>
		<updated>2010-04-29T19:56:27Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Pointing the Workspace at Shrew Using Existing Makefiles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
You need to have a shrew project checked out and built in debug mode using the standard approach.  The first-time debug build is &#039;&#039;required&#039;&#039; after a fresh checkout in order to get autoconf and configure to run properly and set up the Makefile for all the projects.  Eclipse will then piggyback on these.   &lt;br /&gt;
&lt;br /&gt;
If you do not have this done already, please follow the steps in the next section &amp;quot;Setting Up a Debug Shrew Project&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===Setting Up a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.  For example, to get the fully trunk shrew:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn co http://scm.opendap.org/svn/trunk/shrew&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that shrew uses svn externals, so make sure you know which versions you are getting so when you commit you are commiting to the right place!&lt;br /&gt;
&lt;br /&gt;
To check the externals being used, get the property in the shrew directory you checked out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn propget svn:externals&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which for the trunk shrew returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aries@chinchilla$ svn propget svn:externals&lt;br /&gt;
^/trunk/libdap src/libdap&lt;br /&gt;
^/trunk/bes src/bes&lt;br /&gt;
^/trunk/dap-server src/modules/dap-server&lt;br /&gt;
^/trunk/freeform_handler src/modules/freeform_handler&lt;br /&gt;
^/trunk/fileout_netcdf src/modules/fileout_netcdf&lt;br /&gt;
^/trunk/netcdf_handler src/modules/netcdf_handler&lt;br /&gt;
^/trunk/hdf4_handler src/modules/hdf4_handler&lt;br /&gt;
^/trunk/hdf5_handler src/modules/hdf5_handler&lt;br /&gt;
^/trunk/ncml_module src/modules/ncml_module&lt;br /&gt;
^/trunk/wcs_gateway_module src/modules/wcs_gateway_module&lt;br /&gt;
^/trunk/wcs_module src/modules/wcs_module&lt;br /&gt;
^/trunk/olfs src/olfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES in Hyrax 1.6, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
as the shrew starting point as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
====Configuring a Debug Build====&lt;br /&gt;
&lt;br /&gt;
Since you likely plan to use the shrew project for debugging in Eclipse, you&#039;ll want to run the build_hyrax_debug script in order to make sure the configuration for all the subprojects is set up to perform debug builds (i.e. no optimization and full symbol tables).  That way Eclipse will be able to find breakpoints and let you view variables in a running debug.&lt;br /&gt;
&lt;br /&gt;
In a bash terminal in the top-level shrew directory, type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run autoconf on everything, then configure, then build it.  If there are any missing dependencies, make sure to get them until everything builds.  This will ensure that all the subprojects are configured properly so that the Eclipse Build command, which simply calls &#039;make&#039;, will succeed in compiling a debug version of the specified project.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shrew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: It is important that you have run autoconf and configure in the shrew directory tree before you start using Eclipse.  The simplest way to do this for a debug environment is to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in the top-level shrew directory as mentioned above. &lt;br /&gt;
&lt;br /&gt;
Now we will set up projects for the things we expect to use. In our case, we have a separate project for libdap, bes, and the ncml_module.  We have tried to create a top-level shrew project in the workspace, but due to the way the Makefile is set up and the manner in which Eclipse finds source files when debugging, having a shrew project plus a module project will cause headaches.   It&#039;s better to just create one per item you plan to debug.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: You cannot expect a breakpoint to work unless it is in a project in the workspace!  Eclipse is smart enough to find source matching the symbol table in the case of stepping (sometimes), but don&#039;t be surprised if a breakpoint you set in, say, the hdf4_handler, doesn&#039;t go off (though you expect it should) unless you explicitly add the hdf4_handler project using the section below on creating projects for modules.&lt;br /&gt;
&lt;br /&gt;
First, however, we need a new workspace to put everything into.&lt;br /&gt;
&lt;br /&gt;
==== Create a New Workspace====&lt;br /&gt;
First, create a new workspace if you have an existing one.  You can use:&lt;br /&gt;
&lt;br /&gt;
File &amp;gt; Switch Workspace &amp;gt; Other...&lt;br /&gt;
&lt;br /&gt;
and just create a new directory for the workspace to make the new one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====New Project for Libdap====&lt;br /&gt;
&lt;br /&gt;
If you plan to modify the BES or libdap, or even if you want to be able to set breakpoints and step through code for these in the debugger, you must make a project for each of these.  We&#039;ll use libdap as the example, but the bes can be done in the same way.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: it&#039;s important to get the settings right so that Eclipse doesn&#039;t overwrite your Makefile&#039;s!&lt;br /&gt;
&lt;br /&gt;
* Select File &amp;gt; New C++ Project&lt;br /&gt;
* Give it a name: &amp;quot;libdap&amp;quot; (this doesn&#039;t need to match the directory structure...  it could be &amp;quot;libdap trunk&amp;quot; or &amp;quot;libdap 1.6 release&amp;quot; etc.&lt;br /&gt;
* Uncheck &amp;quot;Use Default Location&amp;quot;&lt;br /&gt;
* Browse for the libdap directory and choose it.  This should be in $shrew/src/libdap (where $shrew is the top-level shrew dir).&lt;br /&gt;
* Under &amp;quot;Project Type...&amp;quot; select &amp;quot;Makefile Project&amp;quot;&lt;br /&gt;
* Make sure to select &amp;quot;Empty Project&amp;quot; under the &amp;quot;Makefile Project&amp;quot; treeview to tell Eclipse to use existing Makefile&#039;s.&lt;br /&gt;
* Tell it the toolchain to use if there&#039;s a choice: for Mac it&#039;s &amp;quot;MaxOSX GCC&amp;quot;.&lt;br /&gt;
* Select the &amp;quot;Finish&amp;quot; button.&lt;br /&gt;
&lt;br /&gt;
A new project should be in the project view.&lt;br /&gt;
&lt;br /&gt;
Now we need to tell it the make command since libdap must be installed for it to work in shrew.&lt;br /&gt;
&lt;br /&gt;
* Select the new libdap project.  &lt;br /&gt;
* Select &amp;quot;Project &amp;gt; Properties&amp;quot;&lt;br /&gt;
* Select the &amp;quot;C/C++ Build&amp;quot; in the treeview on the left&lt;br /&gt;
* Under &amp;quot;Builder&amp;quot; pane, the uncheck &amp;quot;Use default build command&amp;quot; (which is make).&lt;br /&gt;
* This ungrays the make command:  enter &amp;quot;make install&amp;quot; for the command.&lt;br /&gt;
&lt;br /&gt;
Now when you select the libdap project and then hit the Build command for it, it will compile and then install it into the shrew location properly.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== New Project for the BES ====&lt;br /&gt;
&lt;br /&gt;
Go through the same steps as for libdap, except just choose &amp;quot;bes&amp;quot; for the name and project location.  Also change its build command to &amp;quot;make install&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====New Project for a Module====&lt;br /&gt;
&lt;br /&gt;
In this section, we&#039;ll set up the subproject for a particular module you&#039;ll want to develop or debug.  I will use the ncml_module as the example since this is the one I normally develop and I have added some tools to the project to make setting up debugging files easier.&lt;br /&gt;
&lt;br /&gt;
Create the project just like the shrew project, using an Empty Project in the Makefile Project tab.  Set the location to be the subdirectory of the top-level shrew, e.g.&lt;br /&gt;
&lt;br /&gt;
src/modules/ncml_module&lt;br /&gt;
&lt;br /&gt;
This will create a separate project tab for the module.  If you click on this project and press the Build button (with the hammer icon), just that project will be built.&lt;br /&gt;
&lt;br /&gt;
===== Set the Include Path =====&lt;br /&gt;
&lt;br /&gt;
Setting the include path in the workspace will avoid the &amp;quot;can&#039;t find include&amp;quot; problems in the IDE.  The Makefile may have the includes, but Eclipse doesn&#039;t know where to find them.&lt;br /&gt;
&lt;br /&gt;
Under the Project -&amp;gt; Properties dialog (making sure to have the module project selected):&lt;br /&gt;
&lt;br /&gt;
* Click the &amp;quot;C/C++ General&amp;quot; tree to open it.&lt;br /&gt;
* Select &amp;quot;Paths and Symbols&amp;quot;&lt;br /&gt;
* On the &amp;quot;Includes&amp;quot; tab, add libdap and bes to C++ language include paths:&lt;br /&gt;
**Click &amp;quot;Add...&amp;quot;&lt;br /&gt;
**Select all checkmarks: &amp;quot;Add to all configurations&amp;quot;, &amp;quot;Add to all languages&amp;quot; and &amp;quot;Is a workspace path&amp;quot;.&lt;br /&gt;
**Hit the &amp;quot;Workspace...&amp;quot; button and browse to the &amp;quot;shrew/src/libdap&amp;quot; and add it.  It should show up as &amp;quot;/shrew/src/libdap&amp;quot; since we selected &amp;quot;is a workspace path&amp;quot;&lt;br /&gt;
**Do the same for the bes include dir.&lt;br /&gt;
&lt;br /&gt;
==Debugging a Module==&lt;br /&gt;
&lt;br /&gt;
In order to debug a given module, we need to set up a Debug configuration for it.  The way I do this for the ncml_module is by using the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; application and pointing it at the same generated &#039;&#039;bes.conf&#039;&#039; file that the Autotest testsuite uses (all the modules should have this structure at this point).  This makes sure the required modules get loaded, and in particular, the testsuite &#039;&#039;bes.conf&#039;&#039; points at the locally compiled module shared object  in the project &#039;&#039;.libs&#039;&#039; directory, so &#039;make install&#039; isn&#039;t required.  We will also need a BES XML command file to automatically run the command we want to debug.  For the ncml_module, this means we load a given NcML file and ask it for a particular response type (DAS, DDS, DDX, DODS) and perhaps with a constraint.  Then we need to make sure Eclipse knows where to find the dynamically loaded library.  Let&#039;s go through these steps one by one.&lt;br /&gt;
&lt;br /&gt;
===Create a New Debug Configuration===&lt;br /&gt;
&lt;br /&gt;
Go to:&lt;br /&gt;
&lt;br /&gt;
Run &amp;gt; Debug Configurations...&lt;br /&gt;
&lt;br /&gt;
When the dialog pops up, select the &amp;quot;C/C++ Application&amp;quot; entry and &amp;quot;New&amp;quot; to create a new configuration.  This should pop up the configuration options for the new Debug Configuration.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll want to make changes in several of the tabs.&lt;br /&gt;
&lt;br /&gt;
==== Main Tab: Select &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as the application to run====&lt;br /&gt;
&lt;br /&gt;
Now we want to set these options to run &#039;&#039;&#039;besstandalone&#039;&#039;&#039; with the arguments we want.  To do this:&lt;br /&gt;
&lt;br /&gt;
* Select the &amp;quot;Browse...&amp;quot; button under C/C++ Application.&lt;br /&gt;
* Go up from the module directory to the shrew directory and into its &amp;quot;bin&amp;quot; directory (this should exist if you did a successful build_hyrax_debug).&lt;br /&gt;
* Select the executable &#039;&#039;&#039;besstandalone&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The application path will then loom something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/bin/besstandalone&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Leave &amp;quot;Connect process input &amp;amp; output to a terminal&amp;quot; checked.  We want to see the output in the Console.&lt;br /&gt;
&lt;br /&gt;
Leave the configuration window open for the next changes.&lt;br /&gt;
&lt;br /&gt;
==== Arguments Tab ====&lt;br /&gt;
&lt;br /&gt;
Now select the &amp;quot;Arguments&amp;quot; tab.&lt;br /&gt;
&lt;br /&gt;
Under the Program Arguments text field, enter the arguments to give to &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as follows.  First, make sure the working directory is the module directory, i.e.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;${workspace_loc:ncml_module}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in our case.  &lt;br /&gt;
&lt;br /&gt;
Our testsuite directory in ncml_module is &amp;quot;tests&amp;quot;, so that&#039;s where our &#039;&#039;bes.conf&#039;&#039; lives.  Note that other modules use the directory &#039;&#039;bes-testsuite&#039;&#039; instead.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the arguments list we will use for the ncml_module:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;-c tests/bes.conf -d&amp;quot;cerr,ncml,ncml:2&amp;quot; -i tests/eclipse_debug.bescmd&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we:&lt;br /&gt;
&lt;br /&gt;
* Specify the bes.conf to use in the testsuite directory so that we load the locally compiled (uninstalled) module&lt;br /&gt;
* Turn on a few debug channels, here: &amp;quot;cerr&amp;quot;, &amp;quot;ncml&amp;quot; and &amp;quot;ncml:2&amp;quot; which the ncml_module uses for debug output.&lt;br /&gt;
* Tell &#039;&#039;&#039;besstandalone&#039;&#039;&#039; to use the file &amp;quot;tests/eclipse_debug.bescmd&amp;quot; as its input file.  &lt;br /&gt;
&lt;br /&gt;
Note that the &amp;quot;eclipse_debug.bescmd&amp;quot; file doesn&#039;t yet exist.  This is a file that we recreate for each test we want to do.  It can be made by hand, but the ncml_module has a script in tests called &amp;quot;generate_bescmd&amp;quot; that creates a BES XML command for a given ncml file and response type.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example eclipse_debug.bescmd for the DAS response for &amp;quot;/data/ncml/fnoc1_improved.ncml&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;request reqID=&amp;quot;some_unique_value&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;setContext name=&amp;quot;dap_format&amp;quot;&amp;gt;dap2&amp;lt;/setContext&amp;gt;&lt;br /&gt;
    &amp;lt;setContainer name=&amp;quot;c&amp;quot; space=&amp;quot;catalog&amp;quot;&amp;gt;/data/ncml/fnoc1_improved.ncml&amp;lt;/setContainer&amp;gt;&lt;br /&gt;
    &amp;lt;define name=&amp;quot;d&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;container name=&amp;quot;c&amp;quot;&amp;gt;&amp;lt;/container&amp;gt;&lt;br /&gt;
    &amp;lt;/define&amp;gt;&lt;br /&gt;
    &amp;lt;get type=&amp;quot;das&amp;quot; definition=&amp;quot;d&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/request&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you&#039;re using some other module, you probably want to copy this into a new file &#039;&#039;eclipse_debug.bescmd&#039;&#039; and modify it as your debug needs change, such as to test different responses.&lt;br /&gt;
&lt;br /&gt;
====Debugger Tab====&lt;br /&gt;
&lt;br /&gt;
Next, select the Debugger tab.&lt;br /&gt;
&lt;br /&gt;
* Decide whether to leave &amp;quot;Stop on startup at: main&amp;quot; selected or not.  I usually leave it selected for the first pass just to be sure I can get a breakpoint in the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; main() function in case there was a problem.  You can edit the configuration to deselect it later.&lt;br /&gt;
&lt;br /&gt;
* Under &amp;quot;Debugger Options&amp;quot;, select the &amp;quot;Shared Libraries&amp;quot; tab.&lt;br /&gt;
* Make sure &amp;quot;Load shared library symbols automatically&amp;quot; is selected since our modules are dynamically loaded.&lt;br /&gt;
* Under Directories, click the &amp;quot;Add...&amp;quot; button &lt;br /&gt;
* &amp;quot;Browse...&amp;quot; your way to select the &#039;&#039;.libs&#039;&#039; directory in the module directory.  In our case the full path ends up being: &amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/src/modules/ncml_module/.libs&amp;lt;/tt&amp;gt;.  This should match the module loaded in the bes.conf!&lt;br /&gt;
* Leave &amp;quot;Stop on shared library events&amp;quot; unchecked since this will break on every library that gets loaded otherwise.&lt;br /&gt;
&lt;br /&gt;
====Apply Changes====&lt;br /&gt;
&lt;br /&gt;
On the bottom of the configuration, click &amp;quot;Apply&amp;quot; to save the changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Test It====&lt;br /&gt;
&lt;br /&gt;
If you&#039;re still in the debug configuration window, you can click the Debug button (assuming you have created a valid &#039;&#039;eclipse_debug.bescmd&#039;&#039; file) to run the debugger.  If all worked out and you left Stop on startup at main selected, you will eventually get a breakpoint in the bes StandAloneApp.cc main() function!&lt;br /&gt;
&lt;br /&gt;
From now on, if you have the module selected in the project window, you can click the Debug button (the bug icon) (or use Run &amp;gt; Debug).&lt;br /&gt;
&lt;br /&gt;
You might also want to go to the top-level module initialize call and set a breakpoint to make sure you&#039;re module gets loaded properly and that you can stop on a breakpoint in it.  For the NcML Module, this is the file:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NCMLModule.cc&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
and the function &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;NCMLModule::initialize( const string &amp;amp;modname )&amp;lt;/tt&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5648</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5648"/>
		<updated>2010-04-29T19:26:14Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Pointing the Workspace at Shrew Using Existing Makefiles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
You need to have a shrew project checked out and built in debug mode using the standard approach.  The first-time debug build is &#039;&#039;required&#039;&#039; after a fresh checkout in order to get autoconf and configure to run properly and set up the Makefile for all the projects.  Eclipse will then piggyback on these.   &lt;br /&gt;
&lt;br /&gt;
If you do not have this done already, please follow the steps in the next section &amp;quot;Setting Up a Debug Shrew Project&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===Setting Up a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.  For example, to get the fully trunk shrew:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn co http://scm.opendap.org/svn/trunk/shrew&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that shrew uses svn externals, so make sure you know which versions you are getting so when you commit you are commiting to the right place!&lt;br /&gt;
&lt;br /&gt;
To check the externals being used, get the property in the shrew directory you checked out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn propget svn:externals&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which for the trunk shrew returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aries@chinchilla$ svn propget svn:externals&lt;br /&gt;
^/trunk/libdap src/libdap&lt;br /&gt;
^/trunk/bes src/bes&lt;br /&gt;
^/trunk/dap-server src/modules/dap-server&lt;br /&gt;
^/trunk/freeform_handler src/modules/freeform_handler&lt;br /&gt;
^/trunk/fileout_netcdf src/modules/fileout_netcdf&lt;br /&gt;
^/trunk/netcdf_handler src/modules/netcdf_handler&lt;br /&gt;
^/trunk/hdf4_handler src/modules/hdf4_handler&lt;br /&gt;
^/trunk/hdf5_handler src/modules/hdf5_handler&lt;br /&gt;
^/trunk/ncml_module src/modules/ncml_module&lt;br /&gt;
^/trunk/wcs_gateway_module src/modules/wcs_gateway_module&lt;br /&gt;
^/trunk/wcs_module src/modules/wcs_module&lt;br /&gt;
^/trunk/olfs src/olfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES in Hyrax 1.6, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
as the shrew starting point as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
====Configuring a Debug Build====&lt;br /&gt;
&lt;br /&gt;
Since you likely plan to use the shrew project for debugging in Eclipse, you&#039;ll want to run the build_hyrax_debug script in order to make sure the configuration for all the subprojects is set up to perform debug builds (i.e. no optimization and full symbol tables).  That way Eclipse will be able to find breakpoints and let you view variables in a running debug.&lt;br /&gt;
&lt;br /&gt;
In a bash terminal in the top-level shrew directory, type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run autoconf on everything, then configure, then build it.  If there are any missing dependencies, make sure to get them until everything builds.  This will ensure that all the subprojects are configured properly so that the Eclipse Build command, which simply calls &#039;make&#039;, will succeed in compiling a debug version of the specified project.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shrew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: It is important that you have run autoconf and configure in the shrew directory tree before you start using Eclipse.  The simplest way to do this for a debug environment is to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in the top-level shrew directory as mentioned above. &lt;br /&gt;
&lt;br /&gt;
Now we will set up projects for the things we expect to use. In our case, we have a separate project for libdap, bes, and the ncml_module.  We have tried to create a top-level shrew project in the workspace, but due to the way the Makefile is set up and the manner in which Eclipse finds source files when debugging, having a shrew project plus a module project will cause headaches.   It&#039;s better to just create one per item you plan to debug.&lt;br /&gt;
&lt;br /&gt;
First, however, we need a new workspace for the projects.&lt;br /&gt;
&lt;br /&gt;
==== Create a New Workspace====&lt;br /&gt;
First, create a new workspace if you have an existing one.  You can use:&lt;br /&gt;
&lt;br /&gt;
File &amp;gt; Switch Workspace &amp;gt; Other...&lt;br /&gt;
&lt;br /&gt;
and just create a new directory for the workspace to make the new one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====New Project for Libdap====&lt;br /&gt;
&lt;br /&gt;
If you plan to modify the BES or libdap, or even if you want to be able to set breakpoints and step through code for these in the debugger, you must make a project for each of these.  We&#039;ll use libdap as the example, but the bes can be done in the same way.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: it&#039;s important to get the settings right so that Eclipse doesn&#039;t overwrite your Makefile&#039;s!&lt;br /&gt;
&lt;br /&gt;
* Select File &amp;gt; New C++ Project&lt;br /&gt;
* Give it a name: &amp;quot;libdap&amp;quot; (this doesn&#039;t need to match the directory structure...  it could be &amp;quot;libdap trunk&amp;quot; or &amp;quot;libdap 1.6 release&amp;quot; etc.&lt;br /&gt;
* Uncheck &amp;quot;Use Default Location&amp;quot;&lt;br /&gt;
* Browse for the libdap directory and choose it.  This should be in $shrew/src/libdap (where $shrew is the top-level shrew dir).&lt;br /&gt;
* Under &amp;quot;Project Type...&amp;quot; select &amp;quot;Makefile Project&amp;quot;&lt;br /&gt;
* Make sure to select &amp;quot;Empty Project&amp;quot; under the &amp;quot;Makefile Project&amp;quot; treeview to tell Eclipse to use existing Makefile&#039;s.&lt;br /&gt;
* Tell it the toolchain to use if there&#039;s a choice: for Mac it&#039;s &amp;quot;MaxOSX GCC&amp;quot;.&lt;br /&gt;
* Select the &amp;quot;Finish&amp;quot; button.&lt;br /&gt;
&lt;br /&gt;
A new project should be in the project view.&lt;br /&gt;
&lt;br /&gt;
Now we need to tell it the make command since libdap must be installed for it to work in shrew.&lt;br /&gt;
&lt;br /&gt;
* Select the new libdap project.  &lt;br /&gt;
* Select &amp;quot;Project &amp;gt; Properties&amp;quot;&lt;br /&gt;
* Select the &amp;quot;C/C++ Build&amp;quot; in the treeview on the left&lt;br /&gt;
* Under &amp;quot;Builder&amp;quot; pane, the uncheck &amp;quot;Use default build command&amp;quot; (which is make).&lt;br /&gt;
* This ungrays the make command:  enter &amp;quot;make install&amp;quot; for the command.&lt;br /&gt;
&lt;br /&gt;
Now when you select the libdap project and then hit the Build command for it, it will compile and then install it into the shrew location properly.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== New Project for the BES ====&lt;br /&gt;
&lt;br /&gt;
Go through the same steps as for libdap, except just choose &amp;quot;bes&amp;quot; for the name and project location.  Also change its build command to &amp;quot;make install&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====New Project for a Module====&lt;br /&gt;
&lt;br /&gt;
In this section, we&#039;ll set up the subproject for a particular module you&#039;ll want to develop or debug.  I will use the ncml_module as the example since this is the one I normally develop and I have added some tools to the project to make setting up debugging files easier.&lt;br /&gt;
&lt;br /&gt;
Create the project just like the shrew project, using an Empty Project in the Makefile Project tab.  Set the location to be the subdirectory of the top-level shrew, e.g.&lt;br /&gt;
&lt;br /&gt;
src/modules/ncml_module&lt;br /&gt;
&lt;br /&gt;
This will create a separate project tab for the module.  If you click on this project and press the Build button (with the hammer icon), just that project will be built.&lt;br /&gt;
&lt;br /&gt;
===== Set the Include Path =====&lt;br /&gt;
&lt;br /&gt;
Setting the include path in the workspace will avoid the &amp;quot;can&#039;t find include&amp;quot; problems in the IDE.  The Makefile may have the includes, but Eclipse doesn&#039;t know where to find them.&lt;br /&gt;
&lt;br /&gt;
Under the Project -&amp;gt; Properties dialog (making sure to have the module project selected):&lt;br /&gt;
&lt;br /&gt;
* Click the &amp;quot;C/C++ General&amp;quot; tree to open it.&lt;br /&gt;
* Select &amp;quot;Paths and Symbols&amp;quot;&lt;br /&gt;
* On the &amp;quot;Includes&amp;quot; tab, add libdap and bes to C++ language include paths:&lt;br /&gt;
**Click &amp;quot;Add...&amp;quot;&lt;br /&gt;
**Select all checkmarks: &amp;quot;Add to all configurations&amp;quot;, &amp;quot;Add to all languages&amp;quot; and &amp;quot;Is a workspace path&amp;quot;.&lt;br /&gt;
**Hit the &amp;quot;Workspace...&amp;quot; button and browse to the &amp;quot;shrew/src/libdap&amp;quot; and add it.  It should show up as &amp;quot;/shrew/src/libdap&amp;quot; since we selected &amp;quot;is a workspace path&amp;quot;&lt;br /&gt;
**Do the same for the bes include dir.&lt;br /&gt;
&lt;br /&gt;
==Debugging a Module==&lt;br /&gt;
&lt;br /&gt;
In order to debug a given module, we need to set up a Debug configuration for it.  The way I do this for the ncml_module is by using the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; application and pointing it at the same generated &#039;&#039;bes.conf&#039;&#039; file that the Autotest testsuite uses (all the modules should have this structure at this point).  This makes sure the required modules get loaded, and in particular, the testsuite &#039;&#039;bes.conf&#039;&#039; points at the locally compiled module shared object  in the project &#039;&#039;.libs&#039;&#039; directory, so &#039;make install&#039; isn&#039;t required.  We will also need a BES XML command file to automatically run the command we want to debug.  For the ncml_module, this means we load a given NcML file and ask it for a particular response type (DAS, DDS, DDX, DODS) and perhaps with a constraint.  Then we need to make sure Eclipse knows where to find the dynamically loaded library.  Let&#039;s go through these steps one by one.&lt;br /&gt;
&lt;br /&gt;
===Create a New Debug Configuration===&lt;br /&gt;
&lt;br /&gt;
Go to:&lt;br /&gt;
&lt;br /&gt;
Run &amp;gt; Debug Configurations...&lt;br /&gt;
&lt;br /&gt;
When the dialog pops up, select the &amp;quot;C/C++ Application&amp;quot; entry and &amp;quot;New&amp;quot; to create a new configuration.  This should pop up the configuration options for the new Debug Configuration.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll want to make changes in several of the tabs.&lt;br /&gt;
&lt;br /&gt;
==== Main Tab: Select &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as the application to run====&lt;br /&gt;
&lt;br /&gt;
Now we want to set these options to run &#039;&#039;&#039;besstandalone&#039;&#039;&#039; with the arguments we want.  To do this:&lt;br /&gt;
&lt;br /&gt;
* Select the &amp;quot;Browse...&amp;quot; button under C/C++ Application.&lt;br /&gt;
* Go up from the module directory to the shrew directory and into its &amp;quot;bin&amp;quot; directory (this should exist if you did a successful build_hyrax_debug).&lt;br /&gt;
* Select the executable &#039;&#039;&#039;besstandalone&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The application path will then loom something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/bin/besstandalone&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Leave &amp;quot;Connect process input &amp;amp; output to a terminal&amp;quot; checked.  We want to see the output in the Console.&lt;br /&gt;
&lt;br /&gt;
Leave the configuration window open for the next changes.&lt;br /&gt;
&lt;br /&gt;
==== Arguments Tab ====&lt;br /&gt;
&lt;br /&gt;
Now select the &amp;quot;Arguments&amp;quot; tab.&lt;br /&gt;
&lt;br /&gt;
Under the Program Arguments text field, enter the arguments to give to &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as follows.  First, make sure the working directory is the module directory, i.e.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;${workspace_loc:ncml_module}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in our case.  &lt;br /&gt;
&lt;br /&gt;
Our testsuite directory in ncml_module is &amp;quot;tests&amp;quot;, so that&#039;s where our &#039;&#039;bes.conf&#039;&#039; lives.  Note that other modules use the directory &#039;&#039;bes-testsuite&#039;&#039; instead.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the arguments list we will use for the ncml_module:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;-c tests/bes.conf -d&amp;quot;cerr,ncml,ncml:2&amp;quot; -i tests/eclipse_debug.bescmd&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we:&lt;br /&gt;
&lt;br /&gt;
* Specify the bes.conf to use in the testsuite directory so that we load the locally compiled (uninstalled) module&lt;br /&gt;
* Turn on a few debug channels, here: &amp;quot;cerr&amp;quot;, &amp;quot;ncml&amp;quot; and &amp;quot;ncml:2&amp;quot; which the ncml_module uses for debug output.&lt;br /&gt;
* Tell &#039;&#039;&#039;besstandalone&#039;&#039;&#039; to use the file &amp;quot;tests/eclipse_debug.bescmd&amp;quot; as its input file.  &lt;br /&gt;
&lt;br /&gt;
Note that the &amp;quot;eclipse_debug.bescmd&amp;quot; file doesn&#039;t yet exist.  This is a file that we recreate for each test we want to do.  It can be made by hand, but the ncml_module has a script in tests called &amp;quot;generate_bescmd&amp;quot; that creates a BES XML command for a given ncml file and response type.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example eclipse_debug.bescmd for the DAS response for &amp;quot;/data/ncml/fnoc1_improved.ncml&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;request reqID=&amp;quot;some_unique_value&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;setContext name=&amp;quot;dap_format&amp;quot;&amp;gt;dap2&amp;lt;/setContext&amp;gt;&lt;br /&gt;
    &amp;lt;setContainer name=&amp;quot;c&amp;quot; space=&amp;quot;catalog&amp;quot;&amp;gt;/data/ncml/fnoc1_improved.ncml&amp;lt;/setContainer&amp;gt;&lt;br /&gt;
    &amp;lt;define name=&amp;quot;d&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;container name=&amp;quot;c&amp;quot;&amp;gt;&amp;lt;/container&amp;gt;&lt;br /&gt;
    &amp;lt;/define&amp;gt;&lt;br /&gt;
    &amp;lt;get type=&amp;quot;das&amp;quot; definition=&amp;quot;d&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/request&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you&#039;re using some other module, you probably want to copy this into a new file &#039;&#039;eclipse_debug.bescmd&#039;&#039; and modify it as your debug needs change, such as to test different responses.&lt;br /&gt;
&lt;br /&gt;
====Debugger Tab====&lt;br /&gt;
&lt;br /&gt;
Next, select the Debugger tab.&lt;br /&gt;
&lt;br /&gt;
* Decide whether to leave &amp;quot;Stop on startup at: main&amp;quot; selected or not.  I usually leave it selected for the first pass just to be sure I can get a breakpoint in the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; main() function in case there was a problem.  You can edit the configuration to deselect it later.&lt;br /&gt;
&lt;br /&gt;
* Under &amp;quot;Debugger Options&amp;quot;, select the &amp;quot;Shared Libraries&amp;quot; tab.&lt;br /&gt;
* Make sure &amp;quot;Load shared library symbols automatically&amp;quot; is selected since our modules are dynamically loaded.&lt;br /&gt;
* Under Directories, click the &amp;quot;Add...&amp;quot; button &lt;br /&gt;
* &amp;quot;Browse...&amp;quot; your way to select the &#039;&#039;.libs&#039;&#039; directory in the module directory.  In our case the full path ends up being: &amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/src/modules/ncml_module/.libs&amp;lt;/tt&amp;gt;.  This should match the module loaded in the bes.conf!&lt;br /&gt;
* Leave &amp;quot;Stop on shared library events&amp;quot; unchecked since this will break on every library that gets loaded otherwise.&lt;br /&gt;
&lt;br /&gt;
====Apply Changes====&lt;br /&gt;
&lt;br /&gt;
On the bottom of the configuration, click &amp;quot;Apply&amp;quot; to save the changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Test It====&lt;br /&gt;
&lt;br /&gt;
If you&#039;re still in the debug configuration window, you can click the Debug button (assuming you have created a valid &#039;&#039;eclipse_debug.bescmd&#039;&#039; file) to run the debugger.  If all worked out and you left Stop on startup at main selected, you will eventually get a breakpoint in the bes StandAloneApp.cc main() function!&lt;br /&gt;
&lt;br /&gt;
From now on, if you have the module selected in the project window, you can click the Debug button (the bug icon) (or use Run &amp;gt; Debug).&lt;br /&gt;
&lt;br /&gt;
You might also want to go to the top-level module initialize call and set a breakpoint to make sure you&#039;re module gets loaded properly and that you can stop on a breakpoint in it.  For the NcML Module, this is the file:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NCMLModule.cc&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
and the function &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;NCMLModule::initialize( const string &amp;amp;modname )&amp;lt;/tt&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5647</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5647"/>
		<updated>2010-04-29T19:08:16Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Pointing the Workspace at Shew Using Existing Makefiles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
You need to have a shrew project checked out and built in debug mode using the standard approach.  The first-time debug build is &#039;&#039;required&#039;&#039; after a fresh checkout in order to get autoconf and configure to run properly and set up the Makefile for all the projects.  Eclipse will then piggyback on these.   &lt;br /&gt;
&lt;br /&gt;
If you do not have this done already, please follow the steps in the next section &amp;quot;Setting Up a Debug Shrew Project&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===Setting Up a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.  For example, to get the fully trunk shrew:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn co http://scm.opendap.org/svn/trunk/shrew&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that shrew uses svn externals, so make sure you know which versions you are getting so when you commit you are commiting to the right place!&lt;br /&gt;
&lt;br /&gt;
To check the externals being used, get the property in the shrew directory you checked out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn propget svn:externals&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which for the trunk shrew returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aries@chinchilla$ svn propget svn:externals&lt;br /&gt;
^/trunk/libdap src/libdap&lt;br /&gt;
^/trunk/bes src/bes&lt;br /&gt;
^/trunk/dap-server src/modules/dap-server&lt;br /&gt;
^/trunk/freeform_handler src/modules/freeform_handler&lt;br /&gt;
^/trunk/fileout_netcdf src/modules/fileout_netcdf&lt;br /&gt;
^/trunk/netcdf_handler src/modules/netcdf_handler&lt;br /&gt;
^/trunk/hdf4_handler src/modules/hdf4_handler&lt;br /&gt;
^/trunk/hdf5_handler src/modules/hdf5_handler&lt;br /&gt;
^/trunk/ncml_module src/modules/ncml_module&lt;br /&gt;
^/trunk/wcs_gateway_module src/modules/wcs_gateway_module&lt;br /&gt;
^/trunk/wcs_module src/modules/wcs_module&lt;br /&gt;
^/trunk/olfs src/olfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES in Hyrax 1.6, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
as the shrew starting point as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
====Configuring a Debug Build====&lt;br /&gt;
&lt;br /&gt;
Since you likely plan to use the shrew project for debugging in Eclipse, you&#039;ll want to run the build_hyrax_debug script in order to make sure the configuration for all the subprojects is set up to perform debug builds (i.e. no optimization and full symbol tables).  That way Eclipse will be able to find breakpoints and let you view variables in a running debug.&lt;br /&gt;
&lt;br /&gt;
In a bash terminal in the top-level shrew directory, type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run autoconf on everything, then configure, then build it.  If there are any missing dependencies, make sure to get them until everything builds.  This will ensure that all the subprojects are configured properly so that the Eclipse Build command, which simply calls &#039;make&#039;, will succeed in compiling a debug version of the specified project.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shrew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
==== New Workspace====&lt;br /&gt;
First, create a new workspace if you have an existing one.  You can use:&lt;br /&gt;
&lt;br /&gt;
File &amp;gt; Switch Workspace &amp;gt; Other...&lt;br /&gt;
&lt;br /&gt;
and just create a new directory for the workspace to make the new one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====New Project for BES and/or Libdap====&lt;br /&gt;
&lt;br /&gt;
If you plan to modify the BES or libdap, you can make a project for each of these as well in the same way, but by pointing the location of the project at the appropriate subdirectory (src/bes or src/libdap) of the top-level shrew checkout.&lt;br /&gt;
&lt;br /&gt;
====New Project for a Module====&lt;br /&gt;
&lt;br /&gt;
In this section, we&#039;ll set up the subproject for a particular module you&#039;ll want to develop or debug.  I will use the ncml_module as the example since this is the one I normally develop and I have added some tools to the project to make setting up debugging files easier.&lt;br /&gt;
&lt;br /&gt;
Create the project just like the shrew project, using an Empty Project in the Makefile Project tab.  Set the location to be the subdirectory of the top-level shrew, e.g.&lt;br /&gt;
&lt;br /&gt;
src/modules/ncml_module&lt;br /&gt;
&lt;br /&gt;
This will create a separate project tab for the module.  If you click on this project and press the Build button (with the hammer icon), just that project will be built.&lt;br /&gt;
&lt;br /&gt;
===== Set the Include Path =====&lt;br /&gt;
&lt;br /&gt;
Setting the include path in the workspace will avoid the &amp;quot;can&#039;t find include&amp;quot; problems in the IDE.  The Makefile may have the includes, but Eclipse doesn&#039;t know where to find them.&lt;br /&gt;
&lt;br /&gt;
Under the Project -&amp;gt; Properties dialog (making sure to have the module project selected):&lt;br /&gt;
&lt;br /&gt;
* Click the &amp;quot;C/C++ General&amp;quot; tree to open it.&lt;br /&gt;
* Select &amp;quot;Paths and Symbols&amp;quot;&lt;br /&gt;
* On the &amp;quot;Includes&amp;quot; tab, add libdap and bes to C++ language include paths:&lt;br /&gt;
**Click &amp;quot;Add...&amp;quot;&lt;br /&gt;
**Select all checkmarks: &amp;quot;Add to all configurations&amp;quot;, &amp;quot;Add to all languages&amp;quot; and &amp;quot;Is a workspace path&amp;quot;.&lt;br /&gt;
**Hit the &amp;quot;Workspace...&amp;quot; button and browse to the &amp;quot;shrew/src/libdap&amp;quot; and add it.  It should show up as &amp;quot;/shrew/src/libdap&amp;quot; since we selected &amp;quot;is a workspace path&amp;quot;&lt;br /&gt;
**Do the same for the bes include dir.&lt;br /&gt;
&lt;br /&gt;
==Debugging a Module==&lt;br /&gt;
&lt;br /&gt;
In order to debug a given module, we need to set up a Debug configuration for it.  The way I do this for the ncml_module is by using the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; application and pointing it at the same generated &#039;&#039;bes.conf&#039;&#039; file that the Autotest testsuite uses (all the modules should have this structure at this point).  This makes sure the required modules get loaded, and in particular, the testsuite &#039;&#039;bes.conf&#039;&#039; points at the locally compiled module shared object  in the project &#039;&#039;.libs&#039;&#039; directory, so &#039;make install&#039; isn&#039;t required.  We will also need a BES XML command file to automatically run the command we want to debug.  For the ncml_module, this means we load a given NcML file and ask it for a particular response type (DAS, DDS, DDX, DODS) and perhaps with a constraint.  Then we need to make sure Eclipse knows where to find the dynamically loaded library.  Let&#039;s go through these steps one by one.&lt;br /&gt;
&lt;br /&gt;
===Create a New Debug Configuration===&lt;br /&gt;
&lt;br /&gt;
Go to:&lt;br /&gt;
&lt;br /&gt;
Run &amp;gt; Debug Configurations...&lt;br /&gt;
&lt;br /&gt;
When the dialog pops up, select the &amp;quot;C/C++ Application&amp;quot; entry and &amp;quot;New&amp;quot; to create a new configuration.  This should pop up the configuration options for the new Debug Configuration.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll want to make changes in several of the tabs.&lt;br /&gt;
&lt;br /&gt;
==== Main Tab: Select &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as the application to run====&lt;br /&gt;
&lt;br /&gt;
Now we want to set these options to run &#039;&#039;&#039;besstandalone&#039;&#039;&#039; with the arguments we want.  To do this:&lt;br /&gt;
&lt;br /&gt;
* Select the &amp;quot;Browse...&amp;quot; button under C/C++ Application.&lt;br /&gt;
* Go up from the module directory to the shrew directory and into its &amp;quot;bin&amp;quot; directory (this should exist if you did a successful build_hyrax_debug).&lt;br /&gt;
* Select the executable &#039;&#039;&#039;besstandalone&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The application path will then loom something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/bin/besstandalone&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Leave &amp;quot;Connect process input &amp;amp; output to a terminal&amp;quot; checked.  We want to see the output in the Console.&lt;br /&gt;
&lt;br /&gt;
Leave the configuration window open for the next changes.&lt;br /&gt;
&lt;br /&gt;
==== Arguments Tab ====&lt;br /&gt;
&lt;br /&gt;
Now select the &amp;quot;Arguments&amp;quot; tab.&lt;br /&gt;
&lt;br /&gt;
Under the Program Arguments text field, enter the arguments to give to &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as follows.  First, make sure the working directory is the module directory, i.e.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;${workspace_loc:ncml_module}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in our case.  &lt;br /&gt;
&lt;br /&gt;
Our testsuite directory in ncml_module is &amp;quot;tests&amp;quot;, so that&#039;s where our &#039;&#039;bes.conf&#039;&#039; lives.  Note that other modules use the directory &#039;&#039;bes-testsuite&#039;&#039; instead.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the arguments list we will use for the ncml_module:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;-c tests/bes.conf -d&amp;quot;cerr,ncml,ncml:2&amp;quot; -i tests/eclipse_debug.bescmd&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we:&lt;br /&gt;
&lt;br /&gt;
* Specify the bes.conf to use in the testsuite directory so that we load the locally compiled (uninstalled) module&lt;br /&gt;
* Turn on a few debug channels, here: &amp;quot;cerr&amp;quot;, &amp;quot;ncml&amp;quot; and &amp;quot;ncml:2&amp;quot; which the ncml_module uses for debug output.&lt;br /&gt;
* Tell &#039;&#039;&#039;besstandalone&#039;&#039;&#039; to use the file &amp;quot;tests/eclipse_debug.bescmd&amp;quot; as its input file.  &lt;br /&gt;
&lt;br /&gt;
Note that the &amp;quot;eclipse_debug.bescmd&amp;quot; file doesn&#039;t yet exist.  This is a file that we recreate for each test we want to do.  It can be made by hand, but the ncml_module has a script in tests called &amp;quot;generate_bescmd&amp;quot; that creates a BES XML command for a given ncml file and response type.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example eclipse_debug.bescmd for the DAS response for &amp;quot;/data/ncml/fnoc1_improved.ncml&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;request reqID=&amp;quot;some_unique_value&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;setContext name=&amp;quot;dap_format&amp;quot;&amp;gt;dap2&amp;lt;/setContext&amp;gt;&lt;br /&gt;
    &amp;lt;setContainer name=&amp;quot;c&amp;quot; space=&amp;quot;catalog&amp;quot;&amp;gt;/data/ncml/fnoc1_improved.ncml&amp;lt;/setContainer&amp;gt;&lt;br /&gt;
    &amp;lt;define name=&amp;quot;d&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;container name=&amp;quot;c&amp;quot;&amp;gt;&amp;lt;/container&amp;gt;&lt;br /&gt;
    &amp;lt;/define&amp;gt;&lt;br /&gt;
    &amp;lt;get type=&amp;quot;das&amp;quot; definition=&amp;quot;d&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/request&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you&#039;re using some other module, you probably want to copy this into a new file &#039;&#039;eclipse_debug.bescmd&#039;&#039; and modify it as your debug needs change, such as to test different responses.&lt;br /&gt;
&lt;br /&gt;
====Debugger Tab====&lt;br /&gt;
&lt;br /&gt;
Next, select the Debugger tab.&lt;br /&gt;
&lt;br /&gt;
* Decide whether to leave &amp;quot;Stop on startup at: main&amp;quot; selected or not.  I usually leave it selected for the first pass just to be sure I can get a breakpoint in the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; main() function in case there was a problem.  You can edit the configuration to deselect it later.&lt;br /&gt;
&lt;br /&gt;
* Under &amp;quot;Debugger Options&amp;quot;, select the &amp;quot;Shared Libraries&amp;quot; tab.&lt;br /&gt;
* Make sure &amp;quot;Load shared library symbols automatically&amp;quot; is selected since our modules are dynamically loaded.&lt;br /&gt;
* Under Directories, click the &amp;quot;Add...&amp;quot; button &lt;br /&gt;
* &amp;quot;Browse...&amp;quot; your way to select the &#039;&#039;.libs&#039;&#039; directory in the module directory.  In our case the full path ends up being: &amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/src/modules/ncml_module/.libs&amp;lt;/tt&amp;gt;.  This should match the module loaded in the bes.conf!&lt;br /&gt;
* Leave &amp;quot;Stop on shared library events&amp;quot; unchecked since this will break on every library that gets loaded otherwise.&lt;br /&gt;
&lt;br /&gt;
====Apply Changes====&lt;br /&gt;
&lt;br /&gt;
On the bottom of the configuration, click &amp;quot;Apply&amp;quot; to save the changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Test It====&lt;br /&gt;
&lt;br /&gt;
If you&#039;re still in the debug configuration window, you can click the Debug button (assuming you have created a valid &#039;&#039;eclipse_debug.bescmd&#039;&#039; file) to run the debugger.  If all worked out and you left Stop on startup at main selected, you will eventually get a breakpoint in the bes StandAloneApp.cc main() function!&lt;br /&gt;
&lt;br /&gt;
From now on, if you have the module selected in the project window, you can click the Debug button (the bug icon) (or use Run &amp;gt; Debug).&lt;br /&gt;
&lt;br /&gt;
You might also want to go to the top-level module initialize call and set a breakpoint to make sure you&#039;re module gets loaded properly and that you can stop on a breakpoint in it.  For the NcML Module, this is the file:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NCMLModule.cc&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
and the function &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;NCMLModule::initialize( const string &amp;amp;modname )&amp;lt;/tt&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5646</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5646"/>
		<updated>2010-04-29T19:07:53Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* New Project for Shrew */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
You need to have a shrew project checked out and built in debug mode using the standard approach.  The first-time debug build is &#039;&#039;required&#039;&#039; after a fresh checkout in order to get autoconf and configure to run properly and set up the Makefile for all the projects.  Eclipse will then piggyback on these.   &lt;br /&gt;
&lt;br /&gt;
If you do not have this done already, please follow the steps in the next section &amp;quot;Setting Up a Debug Shrew Project&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===Setting Up a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.  For example, to get the fully trunk shrew:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn co http://scm.opendap.org/svn/trunk/shrew&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that shrew uses svn externals, so make sure you know which versions you are getting so when you commit you are commiting to the right place!&lt;br /&gt;
&lt;br /&gt;
To check the externals being used, get the property in the shrew directory you checked out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn propget svn:externals&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which for the trunk shrew returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aries@chinchilla$ svn propget svn:externals&lt;br /&gt;
^/trunk/libdap src/libdap&lt;br /&gt;
^/trunk/bes src/bes&lt;br /&gt;
^/trunk/dap-server src/modules/dap-server&lt;br /&gt;
^/trunk/freeform_handler src/modules/freeform_handler&lt;br /&gt;
^/trunk/fileout_netcdf src/modules/fileout_netcdf&lt;br /&gt;
^/trunk/netcdf_handler src/modules/netcdf_handler&lt;br /&gt;
^/trunk/hdf4_handler src/modules/hdf4_handler&lt;br /&gt;
^/trunk/hdf5_handler src/modules/hdf5_handler&lt;br /&gt;
^/trunk/ncml_module src/modules/ncml_module&lt;br /&gt;
^/trunk/wcs_gateway_module src/modules/wcs_gateway_module&lt;br /&gt;
^/trunk/wcs_module src/modules/wcs_module&lt;br /&gt;
^/trunk/olfs src/olfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES in Hyrax 1.6, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
as the shrew starting point as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
====Configuring a Debug Build====&lt;br /&gt;
&lt;br /&gt;
Since you likely plan to use the shrew project for debugging in Eclipse, you&#039;ll want to run the build_hyrax_debug script in order to make sure the configuration for all the subprojects is set up to perform debug builds (i.e. no optimization and full symbol tables).  That way Eclipse will be able to find breakpoints and let you view variables in a running debug.&lt;br /&gt;
&lt;br /&gt;
In a bash terminal in the top-level shrew directory, type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run autoconf on everything, then configure, then build it.  If there are any missing dependencies, make sure to get them until everything builds.  This will ensure that all the subprojects are configured properly so that the Eclipse Build command, which simply calls &#039;make&#039;, will succeed in compiling a debug version of the specified project.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
==== New Workspace====&lt;br /&gt;
First, create a new workspace if you have an existing one.  You can use:&lt;br /&gt;
&lt;br /&gt;
File &amp;gt; Switch Workspace &amp;gt; Other...&lt;br /&gt;
&lt;br /&gt;
and just create a new directory for the workspace to make the new one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====New Project for BES and/or Libdap====&lt;br /&gt;
&lt;br /&gt;
If you plan to modify the BES or libdap, you can make a project for each of these as well in the same way, but by pointing the location of the project at the appropriate subdirectory (src/bes or src/libdap) of the top-level shrew checkout.&lt;br /&gt;
&lt;br /&gt;
====New Project for a Module====&lt;br /&gt;
&lt;br /&gt;
In this section, we&#039;ll set up the subproject for a particular module you&#039;ll want to develop or debug.  I will use the ncml_module as the example since this is the one I normally develop and I have added some tools to the project to make setting up debugging files easier.&lt;br /&gt;
&lt;br /&gt;
Create the project just like the shrew project, using an Empty Project in the Makefile Project tab.  Set the location to be the subdirectory of the top-level shrew, e.g.&lt;br /&gt;
&lt;br /&gt;
src/modules/ncml_module&lt;br /&gt;
&lt;br /&gt;
This will create a separate project tab for the module.  If you click on this project and press the Build button (with the hammer icon), just that project will be built.&lt;br /&gt;
&lt;br /&gt;
===== Set the Include Path =====&lt;br /&gt;
&lt;br /&gt;
Setting the include path in the workspace will avoid the &amp;quot;can&#039;t find include&amp;quot; problems in the IDE.  The Makefile may have the includes, but Eclipse doesn&#039;t know where to find them.&lt;br /&gt;
&lt;br /&gt;
Under the Project -&amp;gt; Properties dialog (making sure to have the module project selected):&lt;br /&gt;
&lt;br /&gt;
* Click the &amp;quot;C/C++ General&amp;quot; tree to open it.&lt;br /&gt;
* Select &amp;quot;Paths and Symbols&amp;quot;&lt;br /&gt;
* On the &amp;quot;Includes&amp;quot; tab, add libdap and bes to C++ language include paths:&lt;br /&gt;
**Click &amp;quot;Add...&amp;quot;&lt;br /&gt;
**Select all checkmarks: &amp;quot;Add to all configurations&amp;quot;, &amp;quot;Add to all languages&amp;quot; and &amp;quot;Is a workspace path&amp;quot;.&lt;br /&gt;
**Hit the &amp;quot;Workspace...&amp;quot; button and browse to the &amp;quot;shrew/src/libdap&amp;quot; and add it.  It should show up as &amp;quot;/shrew/src/libdap&amp;quot; since we selected &amp;quot;is a workspace path&amp;quot;&lt;br /&gt;
**Do the same for the bes include dir.&lt;br /&gt;
&lt;br /&gt;
==Debugging a Module==&lt;br /&gt;
&lt;br /&gt;
In order to debug a given module, we need to set up a Debug configuration for it.  The way I do this for the ncml_module is by using the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; application and pointing it at the same generated &#039;&#039;bes.conf&#039;&#039; file that the Autotest testsuite uses (all the modules should have this structure at this point).  This makes sure the required modules get loaded, and in particular, the testsuite &#039;&#039;bes.conf&#039;&#039; points at the locally compiled module shared object  in the project &#039;&#039;.libs&#039;&#039; directory, so &#039;make install&#039; isn&#039;t required.  We will also need a BES XML command file to automatically run the command we want to debug.  For the ncml_module, this means we load a given NcML file and ask it for a particular response type (DAS, DDS, DDX, DODS) and perhaps with a constraint.  Then we need to make sure Eclipse knows where to find the dynamically loaded library.  Let&#039;s go through these steps one by one.&lt;br /&gt;
&lt;br /&gt;
===Create a New Debug Configuration===&lt;br /&gt;
&lt;br /&gt;
Go to:&lt;br /&gt;
&lt;br /&gt;
Run &amp;gt; Debug Configurations...&lt;br /&gt;
&lt;br /&gt;
When the dialog pops up, select the &amp;quot;C/C++ Application&amp;quot; entry and &amp;quot;New&amp;quot; to create a new configuration.  This should pop up the configuration options for the new Debug Configuration.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll want to make changes in several of the tabs.&lt;br /&gt;
&lt;br /&gt;
==== Main Tab: Select &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as the application to run====&lt;br /&gt;
&lt;br /&gt;
Now we want to set these options to run &#039;&#039;&#039;besstandalone&#039;&#039;&#039; with the arguments we want.  To do this:&lt;br /&gt;
&lt;br /&gt;
* Select the &amp;quot;Browse...&amp;quot; button under C/C++ Application.&lt;br /&gt;
* Go up from the module directory to the shrew directory and into its &amp;quot;bin&amp;quot; directory (this should exist if you did a successful build_hyrax_debug).&lt;br /&gt;
* Select the executable &#039;&#039;&#039;besstandalone&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The application path will then loom something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/bin/besstandalone&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Leave &amp;quot;Connect process input &amp;amp; output to a terminal&amp;quot; checked.  We want to see the output in the Console.&lt;br /&gt;
&lt;br /&gt;
Leave the configuration window open for the next changes.&lt;br /&gt;
&lt;br /&gt;
==== Arguments Tab ====&lt;br /&gt;
&lt;br /&gt;
Now select the &amp;quot;Arguments&amp;quot; tab.&lt;br /&gt;
&lt;br /&gt;
Under the Program Arguments text field, enter the arguments to give to &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as follows.  First, make sure the working directory is the module directory, i.e.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;${workspace_loc:ncml_module}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in our case.  &lt;br /&gt;
&lt;br /&gt;
Our testsuite directory in ncml_module is &amp;quot;tests&amp;quot;, so that&#039;s where our &#039;&#039;bes.conf&#039;&#039; lives.  Note that other modules use the directory &#039;&#039;bes-testsuite&#039;&#039; instead.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the arguments list we will use for the ncml_module:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;-c tests/bes.conf -d&amp;quot;cerr,ncml,ncml:2&amp;quot; -i tests/eclipse_debug.bescmd&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we:&lt;br /&gt;
&lt;br /&gt;
* Specify the bes.conf to use in the testsuite directory so that we load the locally compiled (uninstalled) module&lt;br /&gt;
* Turn on a few debug channels, here: &amp;quot;cerr&amp;quot;, &amp;quot;ncml&amp;quot; and &amp;quot;ncml:2&amp;quot; which the ncml_module uses for debug output.&lt;br /&gt;
* Tell &#039;&#039;&#039;besstandalone&#039;&#039;&#039; to use the file &amp;quot;tests/eclipse_debug.bescmd&amp;quot; as its input file.  &lt;br /&gt;
&lt;br /&gt;
Note that the &amp;quot;eclipse_debug.bescmd&amp;quot; file doesn&#039;t yet exist.  This is a file that we recreate for each test we want to do.  It can be made by hand, but the ncml_module has a script in tests called &amp;quot;generate_bescmd&amp;quot; that creates a BES XML command for a given ncml file and response type.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example eclipse_debug.bescmd for the DAS response for &amp;quot;/data/ncml/fnoc1_improved.ncml&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;request reqID=&amp;quot;some_unique_value&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;setContext name=&amp;quot;dap_format&amp;quot;&amp;gt;dap2&amp;lt;/setContext&amp;gt;&lt;br /&gt;
    &amp;lt;setContainer name=&amp;quot;c&amp;quot; space=&amp;quot;catalog&amp;quot;&amp;gt;/data/ncml/fnoc1_improved.ncml&amp;lt;/setContainer&amp;gt;&lt;br /&gt;
    &amp;lt;define name=&amp;quot;d&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;container name=&amp;quot;c&amp;quot;&amp;gt;&amp;lt;/container&amp;gt;&lt;br /&gt;
    &amp;lt;/define&amp;gt;&lt;br /&gt;
    &amp;lt;get type=&amp;quot;das&amp;quot; definition=&amp;quot;d&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/request&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you&#039;re using some other module, you probably want to copy this into a new file &#039;&#039;eclipse_debug.bescmd&#039;&#039; and modify it as your debug needs change, such as to test different responses.&lt;br /&gt;
&lt;br /&gt;
====Debugger Tab====&lt;br /&gt;
&lt;br /&gt;
Next, select the Debugger tab.&lt;br /&gt;
&lt;br /&gt;
* Decide whether to leave &amp;quot;Stop on startup at: main&amp;quot; selected or not.  I usually leave it selected for the first pass just to be sure I can get a breakpoint in the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; main() function in case there was a problem.  You can edit the configuration to deselect it later.&lt;br /&gt;
&lt;br /&gt;
* Under &amp;quot;Debugger Options&amp;quot;, select the &amp;quot;Shared Libraries&amp;quot; tab.&lt;br /&gt;
* Make sure &amp;quot;Load shared library symbols automatically&amp;quot; is selected since our modules are dynamically loaded.&lt;br /&gt;
* Under Directories, click the &amp;quot;Add...&amp;quot; button &lt;br /&gt;
* &amp;quot;Browse...&amp;quot; your way to select the &#039;&#039;.libs&#039;&#039; directory in the module directory.  In our case the full path ends up being: &amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/src/modules/ncml_module/.libs&amp;lt;/tt&amp;gt;.  This should match the module loaded in the bes.conf!&lt;br /&gt;
* Leave &amp;quot;Stop on shared library events&amp;quot; unchecked since this will break on every library that gets loaded otherwise.&lt;br /&gt;
&lt;br /&gt;
====Apply Changes====&lt;br /&gt;
&lt;br /&gt;
On the bottom of the configuration, click &amp;quot;Apply&amp;quot; to save the changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Test It====&lt;br /&gt;
&lt;br /&gt;
If you&#039;re still in the debug configuration window, you can click the Debug button (assuming you have created a valid &#039;&#039;eclipse_debug.bescmd&#039;&#039; file) to run the debugger.  If all worked out and you left Stop on startup at main selected, you will eventually get a breakpoint in the bes StandAloneApp.cc main() function!&lt;br /&gt;
&lt;br /&gt;
From now on, if you have the module selected in the project window, you can click the Debug button (the bug icon) (or use Run &amp;gt; Debug).&lt;br /&gt;
&lt;br /&gt;
You might also want to go to the top-level module initialize call and set a breakpoint to make sure you&#039;re module gets loaded properly and that you can stop on a breakpoint in it.  For the NcML Module, this is the file:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NCMLModule.cc&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
and the function &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;NCMLModule::initialize( const string &amp;amp;modname )&amp;lt;/tt&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5645</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5645"/>
		<updated>2010-04-29T17:16:17Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* New Project for a Module */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
You need to have a shrew project checked out and built in debug mode using the standard approach.  The first-time debug build is &#039;&#039;required&#039;&#039; after a fresh checkout in order to get autoconf and configure to run properly and set up the Makefile for all the projects.  Eclipse will then piggyback on these.   &lt;br /&gt;
&lt;br /&gt;
If you do not have this done already, please follow the steps in the next section &amp;quot;Setting Up a Debug Shrew Project&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===Setting Up a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.  For example, to get the fully trunk shrew:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn co http://scm.opendap.org/svn/trunk/shrew&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that shrew uses svn externals, so make sure you know which versions you are getting so when you commit you are commiting to the right place!&lt;br /&gt;
&lt;br /&gt;
To check the externals being used, get the property in the shrew directory you checked out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn propget svn:externals&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which for the trunk shrew returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aries@chinchilla$ svn propget svn:externals&lt;br /&gt;
^/trunk/libdap src/libdap&lt;br /&gt;
^/trunk/bes src/bes&lt;br /&gt;
^/trunk/dap-server src/modules/dap-server&lt;br /&gt;
^/trunk/freeform_handler src/modules/freeform_handler&lt;br /&gt;
^/trunk/fileout_netcdf src/modules/fileout_netcdf&lt;br /&gt;
^/trunk/netcdf_handler src/modules/netcdf_handler&lt;br /&gt;
^/trunk/hdf4_handler src/modules/hdf4_handler&lt;br /&gt;
^/trunk/hdf5_handler src/modules/hdf5_handler&lt;br /&gt;
^/trunk/ncml_module src/modules/ncml_module&lt;br /&gt;
^/trunk/wcs_gateway_module src/modules/wcs_gateway_module&lt;br /&gt;
^/trunk/wcs_module src/modules/wcs_module&lt;br /&gt;
^/trunk/olfs src/olfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES in Hyrax 1.6, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
as the shrew starting point as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
====Configuring a Debug Build====&lt;br /&gt;
&lt;br /&gt;
Since you likely plan to use the shrew project for debugging in Eclipse, you&#039;ll want to run the build_hyrax_debug script in order to make sure the configuration for all the subprojects is set up to perform debug builds (i.e. no optimization and full symbol tables).  That way Eclipse will be able to find breakpoints and let you view variables in a running debug.&lt;br /&gt;
&lt;br /&gt;
In a bash terminal in the top-level shrew directory, type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run autoconf on everything, then configure, then build it.  If there are any missing dependencies, make sure to get them until everything builds.  This will ensure that all the subprojects are configured properly so that the Eclipse Build command, which simply calls &#039;make&#039;, will succeed in compiling a debug version of the specified project.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
==== New Workspace====&lt;br /&gt;
First, create a new workspace if you have an existing one.  You can use:&lt;br /&gt;
&lt;br /&gt;
File &amp;gt; Switch Workspace &amp;gt; Other...&lt;br /&gt;
&lt;br /&gt;
and just create a new directory for the workspace to make the new one.&lt;br /&gt;
&lt;br /&gt;
====New Project for Shrew====&lt;br /&gt;
&lt;br /&gt;
You probably won&#039;t use this directly, but making a top-level project for shrew will let Workspace searches find functions and files in all the subprojects.  More likely, you will be using a specific subproject directly.  (More on this later).&lt;br /&gt;
&lt;br /&gt;
Create a new Project in the workspace. &lt;br /&gt;
&lt;br /&gt;
File &amp;gt; New &amp;gt; C++ Project&lt;br /&gt;
&lt;br /&gt;
In the dialog:&lt;br /&gt;
&lt;br /&gt;
* Enter a project name.  Something like &amp;quot;Shrew&amp;quot; should be OK.&lt;br /&gt;
* UNcheck &amp;quot;Use Default Location&amp;quot; since we want to point at an existing directory&lt;br /&gt;
* Enter the location of the shrew project you checked out and want to debug (you can use Browse...)&lt;br /&gt;
* Select the &amp;quot;Makefile Project&amp;quot; tab since we want to use &#039;make&#039; to build&lt;br /&gt;
* Under the &amp;quot;Makefile Project&amp;quot; select &amp;quot;Empty Project&amp;quot; so Eclipse doesn&#039;t overwrite the existing Makefile&lt;br /&gt;
* Select the &amp;quot;MaxOSX GCC Toolchain&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You will now have a shrew project.  Since Eclipse uses &#039;make all&#039; to build and shrew doesn&#039;t have this target, you can&#039;t use Build on shrew.  In general, you&#039;ll want to create a subproject for each project you plan to modify so that you can do make on each one.  Otherwise, you will want to do makes in the shell as needed.&lt;br /&gt;
&lt;br /&gt;
====New Project for BES and/or Libdap====&lt;br /&gt;
&lt;br /&gt;
If you plan to modify the BES or libdap, you can make a project for each of these as well in the same way, but by pointing the location of the project at the appropriate subdirectory (src/bes or src/libdap) of the top-level shrew checkout.&lt;br /&gt;
&lt;br /&gt;
====New Project for a Module====&lt;br /&gt;
&lt;br /&gt;
In this section, we&#039;ll set up the subproject for a particular module you&#039;ll want to develop or debug.  I will use the ncml_module as the example since this is the one I normally develop and I have added some tools to the project to make setting up debugging files easier.&lt;br /&gt;
&lt;br /&gt;
Create the project just like the shrew project, using an Empty Project in the Makefile Project tab.  Set the location to be the subdirectory of the top-level shrew, e.g.&lt;br /&gt;
&lt;br /&gt;
src/modules/ncml_module&lt;br /&gt;
&lt;br /&gt;
This will create a separate project tab for the module.  If you click on this project and press the Build button (with the hammer icon), just that project will be built.&lt;br /&gt;
&lt;br /&gt;
===== Set the Include Path =====&lt;br /&gt;
&lt;br /&gt;
Setting the include path in the workspace will avoid the &amp;quot;can&#039;t find include&amp;quot; problems in the IDE.  The Makefile may have the includes, but Eclipse doesn&#039;t know where to find them.&lt;br /&gt;
&lt;br /&gt;
Under the Project -&amp;gt; Properties dialog (making sure to have the module project selected):&lt;br /&gt;
&lt;br /&gt;
* Click the &amp;quot;C/C++ General&amp;quot; tree to open it.&lt;br /&gt;
* Select &amp;quot;Paths and Symbols&amp;quot;&lt;br /&gt;
* On the &amp;quot;Includes&amp;quot; tab, add libdap and bes to C++ language include paths:&lt;br /&gt;
**Click &amp;quot;Add...&amp;quot;&lt;br /&gt;
**Select all checkmarks: &amp;quot;Add to all configurations&amp;quot;, &amp;quot;Add to all languages&amp;quot; and &amp;quot;Is a workspace path&amp;quot;.&lt;br /&gt;
**Hit the &amp;quot;Workspace...&amp;quot; button and browse to the &amp;quot;shrew/src/libdap&amp;quot; and add it.  It should show up as &amp;quot;/shrew/src/libdap&amp;quot; since we selected &amp;quot;is a workspace path&amp;quot;&lt;br /&gt;
**Do the same for the bes include dir.&lt;br /&gt;
&lt;br /&gt;
==Debugging a Module==&lt;br /&gt;
&lt;br /&gt;
In order to debug a given module, we need to set up a Debug configuration for it.  The way I do this for the ncml_module is by using the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; application and pointing it at the same generated &#039;&#039;bes.conf&#039;&#039; file that the Autotest testsuite uses (all the modules should have this structure at this point).  This makes sure the required modules get loaded, and in particular, the testsuite &#039;&#039;bes.conf&#039;&#039; points at the locally compiled module shared object  in the project &#039;&#039;.libs&#039;&#039; directory, so &#039;make install&#039; isn&#039;t required.  We will also need a BES XML command file to automatically run the command we want to debug.  For the ncml_module, this means we load a given NcML file and ask it for a particular response type (DAS, DDS, DDX, DODS) and perhaps with a constraint.  Then we need to make sure Eclipse knows where to find the dynamically loaded library.  Let&#039;s go through these steps one by one.&lt;br /&gt;
&lt;br /&gt;
===Create a New Debug Configuration===&lt;br /&gt;
&lt;br /&gt;
Go to:&lt;br /&gt;
&lt;br /&gt;
Run &amp;gt; Debug Configurations...&lt;br /&gt;
&lt;br /&gt;
When the dialog pops up, select the &amp;quot;C/C++ Application&amp;quot; entry and &amp;quot;New&amp;quot; to create a new configuration.  This should pop up the configuration options for the new Debug Configuration.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll want to make changes in several of the tabs.&lt;br /&gt;
&lt;br /&gt;
==== Main Tab: Select &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as the application to run====&lt;br /&gt;
&lt;br /&gt;
Now we want to set these options to run &#039;&#039;&#039;besstandalone&#039;&#039;&#039; with the arguments we want.  To do this:&lt;br /&gt;
&lt;br /&gt;
* Select the &amp;quot;Browse...&amp;quot; button under C/C++ Application.&lt;br /&gt;
* Go up from the module directory to the shrew directory and into its &amp;quot;bin&amp;quot; directory (this should exist if you did a successful build_hyrax_debug).&lt;br /&gt;
* Select the executable &#039;&#039;&#039;besstandalone&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The application path will then loom something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/bin/besstandalone&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Leave &amp;quot;Connect process input &amp;amp; output to a terminal&amp;quot; checked.  We want to see the output in the Console.&lt;br /&gt;
&lt;br /&gt;
Leave the configuration window open for the next changes.&lt;br /&gt;
&lt;br /&gt;
==== Arguments Tab ====&lt;br /&gt;
&lt;br /&gt;
Now select the &amp;quot;Arguments&amp;quot; tab.&lt;br /&gt;
&lt;br /&gt;
Under the Program Arguments text field, enter the arguments to give to &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as follows.  First, make sure the working directory is the module directory, i.e.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;${workspace_loc:ncml_module}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in our case.  &lt;br /&gt;
&lt;br /&gt;
Our testsuite directory in ncml_module is &amp;quot;tests&amp;quot;, so that&#039;s where our &#039;&#039;bes.conf&#039;&#039; lives.  Note that other modules use the directory &#039;&#039;bes-testsuite&#039;&#039; instead.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the arguments list we will use for the ncml_module:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;-c tests/bes.conf -d&amp;quot;cerr,ncml,ncml:2&amp;quot; -i tests/eclipse_debug.bescmd&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we:&lt;br /&gt;
&lt;br /&gt;
* Specify the bes.conf to use in the testsuite directory so that we load the locally compiled (uninstalled) module&lt;br /&gt;
* Turn on a few debug channels, here: &amp;quot;cerr&amp;quot;, &amp;quot;ncml&amp;quot; and &amp;quot;ncml:2&amp;quot; which the ncml_module uses for debug output.&lt;br /&gt;
* Tell &#039;&#039;&#039;besstandalone&#039;&#039;&#039; to use the file &amp;quot;tests/eclipse_debug.bescmd&amp;quot; as its input file.  &lt;br /&gt;
&lt;br /&gt;
Note that the &amp;quot;eclipse_debug.bescmd&amp;quot; file doesn&#039;t yet exist.  This is a file that we recreate for each test we want to do.  It can be made by hand, but the ncml_module has a script in tests called &amp;quot;generate_bescmd&amp;quot; that creates a BES XML command for a given ncml file and response type.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example eclipse_debug.bescmd for the DAS response for &amp;quot;/data/ncml/fnoc1_improved.ncml&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;request reqID=&amp;quot;some_unique_value&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;setContext name=&amp;quot;dap_format&amp;quot;&amp;gt;dap2&amp;lt;/setContext&amp;gt;&lt;br /&gt;
    &amp;lt;setContainer name=&amp;quot;c&amp;quot; space=&amp;quot;catalog&amp;quot;&amp;gt;/data/ncml/fnoc1_improved.ncml&amp;lt;/setContainer&amp;gt;&lt;br /&gt;
    &amp;lt;define name=&amp;quot;d&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;container name=&amp;quot;c&amp;quot;&amp;gt;&amp;lt;/container&amp;gt;&lt;br /&gt;
    &amp;lt;/define&amp;gt;&lt;br /&gt;
    &amp;lt;get type=&amp;quot;das&amp;quot; definition=&amp;quot;d&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/request&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you&#039;re using some other module, you probably want to copy this into a new file &#039;&#039;eclipse_debug.bescmd&#039;&#039; and modify it as your debug needs change, such as to test different responses.&lt;br /&gt;
&lt;br /&gt;
====Debugger Tab====&lt;br /&gt;
&lt;br /&gt;
Next, select the Debugger tab.&lt;br /&gt;
&lt;br /&gt;
* Decide whether to leave &amp;quot;Stop on startup at: main&amp;quot; selected or not.  I usually leave it selected for the first pass just to be sure I can get a breakpoint in the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; main() function in case there was a problem.  You can edit the configuration to deselect it later.&lt;br /&gt;
&lt;br /&gt;
* Under &amp;quot;Debugger Options&amp;quot;, select the &amp;quot;Shared Libraries&amp;quot; tab.&lt;br /&gt;
* Make sure &amp;quot;Load shared library symbols automatically&amp;quot; is selected since our modules are dynamically loaded.&lt;br /&gt;
* Under Directories, click the &amp;quot;Add...&amp;quot; button &lt;br /&gt;
* &amp;quot;Browse...&amp;quot; your way to select the &#039;&#039;.libs&#039;&#039; directory in the module directory.  In our case the full path ends up being: &amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/src/modules/ncml_module/.libs&amp;lt;/tt&amp;gt;.  This should match the module loaded in the bes.conf!&lt;br /&gt;
* Leave &amp;quot;Stop on shared library events&amp;quot; unchecked since this will break on every library that gets loaded otherwise.&lt;br /&gt;
&lt;br /&gt;
====Apply Changes====&lt;br /&gt;
&lt;br /&gt;
On the bottom of the configuration, click &amp;quot;Apply&amp;quot; to save the changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Test It====&lt;br /&gt;
&lt;br /&gt;
If you&#039;re still in the debug configuration window, you can click the Debug button (assuming you have created a valid &#039;&#039;eclipse_debug.bescmd&#039;&#039; file) to run the debugger.  If all worked out and you left Stop on startup at main selected, you will eventually get a breakpoint in the bes StandAloneApp.cc main() function!&lt;br /&gt;
&lt;br /&gt;
From now on, if you have the module selected in the project window, you can click the Debug button (the bug icon) (or use Run &amp;gt; Debug).&lt;br /&gt;
&lt;br /&gt;
You might also want to go to the top-level module initialize call and set a breakpoint to make sure you&#039;re module gets loaded properly and that you can stop on a breakpoint in it.  For the NcML Module, this is the file:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NCMLModule.cc&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
and the function &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;NCMLModule::initialize( const string &amp;amp;modname )&amp;lt;/tt&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5644</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5644"/>
		<updated>2010-04-29T16:16:57Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Debugger Tab */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
You need to have a shrew project checked out and built in debug mode using the standard approach.  The first-time debug build is &#039;&#039;required&#039;&#039; after a fresh checkout in order to get autoconf and configure to run properly and set up the Makefile for all the projects.  Eclipse will then piggyback on these.   &lt;br /&gt;
&lt;br /&gt;
If you do not have this done already, please follow the steps in the next section &amp;quot;Setting Up a Debug Shrew Project&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===Setting Up a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.  For example, to get the fully trunk shrew:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn co http://scm.opendap.org/svn/trunk/shrew&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that shrew uses svn externals, so make sure you know which versions you are getting so when you commit you are commiting to the right place!&lt;br /&gt;
&lt;br /&gt;
To check the externals being used, get the property in the shrew directory you checked out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn propget svn:externals&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which for the trunk shrew returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aries@chinchilla$ svn propget svn:externals&lt;br /&gt;
^/trunk/libdap src/libdap&lt;br /&gt;
^/trunk/bes src/bes&lt;br /&gt;
^/trunk/dap-server src/modules/dap-server&lt;br /&gt;
^/trunk/freeform_handler src/modules/freeform_handler&lt;br /&gt;
^/trunk/fileout_netcdf src/modules/fileout_netcdf&lt;br /&gt;
^/trunk/netcdf_handler src/modules/netcdf_handler&lt;br /&gt;
^/trunk/hdf4_handler src/modules/hdf4_handler&lt;br /&gt;
^/trunk/hdf5_handler src/modules/hdf5_handler&lt;br /&gt;
^/trunk/ncml_module src/modules/ncml_module&lt;br /&gt;
^/trunk/wcs_gateway_module src/modules/wcs_gateway_module&lt;br /&gt;
^/trunk/wcs_module src/modules/wcs_module&lt;br /&gt;
^/trunk/olfs src/olfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES in Hyrax 1.6, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
as the shrew starting point as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
====Configuring a Debug Build====&lt;br /&gt;
&lt;br /&gt;
Since you likely plan to use the shrew project for debugging in Eclipse, you&#039;ll want to run the build_hyrax_debug script in order to make sure the configuration for all the subprojects is set up to perform debug builds (i.e. no optimization and full symbol tables).  That way Eclipse will be able to find breakpoints and let you view variables in a running debug.&lt;br /&gt;
&lt;br /&gt;
In a bash terminal in the top-level shrew directory, type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run autoconf on everything, then configure, then build it.  If there are any missing dependencies, make sure to get them until everything builds.  This will ensure that all the subprojects are configured properly so that the Eclipse Build command, which simply calls &#039;make&#039;, will succeed in compiling a debug version of the specified project.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
==== New Workspace====&lt;br /&gt;
First, create a new workspace if you have an existing one.  You can use:&lt;br /&gt;
&lt;br /&gt;
File &amp;gt; Switch Workspace &amp;gt; Other...&lt;br /&gt;
&lt;br /&gt;
and just create a new directory for the workspace to make the new one.&lt;br /&gt;
&lt;br /&gt;
====New Project for Shrew====&lt;br /&gt;
&lt;br /&gt;
You probably won&#039;t use this directly, but making a top-level project for shrew will let Workspace searches find functions and files in all the subprojects.  More likely, you will be using a specific subproject directly.  (More on this later).&lt;br /&gt;
&lt;br /&gt;
Create a new Project in the workspace. &lt;br /&gt;
&lt;br /&gt;
File &amp;gt; New &amp;gt; C++ Project&lt;br /&gt;
&lt;br /&gt;
In the dialog:&lt;br /&gt;
&lt;br /&gt;
* Enter a project name.  Something like &amp;quot;Shrew&amp;quot; should be OK.&lt;br /&gt;
* UNcheck &amp;quot;Use Default Location&amp;quot; since we want to point at an existing directory&lt;br /&gt;
* Enter the location of the shrew project you checked out and want to debug (you can use Browse...)&lt;br /&gt;
* Select the &amp;quot;Makefile Project&amp;quot; tab since we want to use &#039;make&#039; to build&lt;br /&gt;
* Under the &amp;quot;Makefile Project&amp;quot; select &amp;quot;Empty Project&amp;quot; so Eclipse doesn&#039;t overwrite the existing Makefile&lt;br /&gt;
* Select the &amp;quot;MaxOSX GCC Toolchain&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You will now have a shrew project.  Since Eclipse uses &#039;make all&#039; to build and shrew doesn&#039;t have this target, you can&#039;t use Build on shrew.  In general, you&#039;ll want to create a subproject for each project you plan to modify so that you can do make on each one.  Otherwise, you will want to do makes in the shell as needed.&lt;br /&gt;
&lt;br /&gt;
====New Project for BES and/or Libdap====&lt;br /&gt;
&lt;br /&gt;
If you plan to modify the BES or libdap, you can make a project for each of these as well in the same way, but by pointing the location of the project at the appropriate subdirectory (src/bes or src/libdap) of the top-level shrew checkout.&lt;br /&gt;
&lt;br /&gt;
====New Project for a Module====&lt;br /&gt;
&lt;br /&gt;
In this section, we&#039;ll set up the subproject for a particular module you&#039;ll want to develop or debug.  I will use the ncml_module as the example since this is the one I normally develop and I have added some tools to the project to make setting up debugging files easier.&lt;br /&gt;
&lt;br /&gt;
Create the project just like the shrew project, using an Empty Project in the Makefile Project tab.  Set the location to be the subdirectory of the top-level shrew, e.g.&lt;br /&gt;
&lt;br /&gt;
src/modules/ncml_module&lt;br /&gt;
&lt;br /&gt;
This will create a separate project tab for the module.  If you click on this project and press the Build button (with the hammer icon), just that project will be built.&lt;br /&gt;
&lt;br /&gt;
==Debugging a Module==&lt;br /&gt;
&lt;br /&gt;
In order to debug a given module, we need to set up a Debug configuration for it.  The way I do this for the ncml_module is by using the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; application and pointing it at the same generated &#039;&#039;bes.conf&#039;&#039; file that the Autotest testsuite uses (all the modules should have this structure at this point).  This makes sure the required modules get loaded, and in particular, the testsuite &#039;&#039;bes.conf&#039;&#039; points at the locally compiled module shared object  in the project &#039;&#039;.libs&#039;&#039; directory, so &#039;make install&#039; isn&#039;t required.  We will also need a BES XML command file to automatically run the command we want to debug.  For the ncml_module, this means we load a given NcML file and ask it for a particular response type (DAS, DDS, DDX, DODS) and perhaps with a constraint.  Then we need to make sure Eclipse knows where to find the dynamically loaded library.  Let&#039;s go through these steps one by one.&lt;br /&gt;
&lt;br /&gt;
===Create a New Debug Configuration===&lt;br /&gt;
&lt;br /&gt;
Go to:&lt;br /&gt;
&lt;br /&gt;
Run &amp;gt; Debug Configurations...&lt;br /&gt;
&lt;br /&gt;
When the dialog pops up, select the &amp;quot;C/C++ Application&amp;quot; entry and &amp;quot;New&amp;quot; to create a new configuration.  This should pop up the configuration options for the new Debug Configuration.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll want to make changes in several of the tabs.&lt;br /&gt;
&lt;br /&gt;
==== Main Tab: Select &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as the application to run====&lt;br /&gt;
&lt;br /&gt;
Now we want to set these options to run &#039;&#039;&#039;besstandalone&#039;&#039;&#039; with the arguments we want.  To do this:&lt;br /&gt;
&lt;br /&gt;
* Select the &amp;quot;Browse...&amp;quot; button under C/C++ Application.&lt;br /&gt;
* Go up from the module directory to the shrew directory and into its &amp;quot;bin&amp;quot; directory (this should exist if you did a successful build_hyrax_debug).&lt;br /&gt;
* Select the executable &#039;&#039;&#039;besstandalone&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The application path will then loom something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/bin/besstandalone&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Leave &amp;quot;Connect process input &amp;amp; output to a terminal&amp;quot; checked.  We want to see the output in the Console.&lt;br /&gt;
&lt;br /&gt;
Leave the configuration window open for the next changes.&lt;br /&gt;
&lt;br /&gt;
==== Arguments Tab ====&lt;br /&gt;
&lt;br /&gt;
Now select the &amp;quot;Arguments&amp;quot; tab.&lt;br /&gt;
&lt;br /&gt;
Under the Program Arguments text field, enter the arguments to give to &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as follows.  First, make sure the working directory is the module directory, i.e.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;${workspace_loc:ncml_module}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in our case.  &lt;br /&gt;
&lt;br /&gt;
Our testsuite directory in ncml_module is &amp;quot;tests&amp;quot;, so that&#039;s where our &#039;&#039;bes.conf&#039;&#039; lives.  Note that other modules use the directory &#039;&#039;bes-testsuite&#039;&#039; instead.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the arguments list we will use for the ncml_module:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;-c tests/bes.conf -d&amp;quot;cerr,ncml,ncml:2&amp;quot; -i tests/eclipse_debug.bescmd&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we:&lt;br /&gt;
&lt;br /&gt;
* Specify the bes.conf to use in the testsuite directory so that we load the locally compiled (uninstalled) module&lt;br /&gt;
* Turn on a few debug channels, here: &amp;quot;cerr&amp;quot;, &amp;quot;ncml&amp;quot; and &amp;quot;ncml:2&amp;quot; which the ncml_module uses for debug output.&lt;br /&gt;
* Tell &#039;&#039;&#039;besstandalone&#039;&#039;&#039; to use the file &amp;quot;tests/eclipse_debug.bescmd&amp;quot; as its input file.  &lt;br /&gt;
&lt;br /&gt;
Note that the &amp;quot;eclipse_debug.bescmd&amp;quot; file doesn&#039;t yet exist.  This is a file that we recreate for each test we want to do.  It can be made by hand, but the ncml_module has a script in tests called &amp;quot;generate_bescmd&amp;quot; that creates a BES XML command for a given ncml file and response type.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example eclipse_debug.bescmd for the DAS response for &amp;quot;/data/ncml/fnoc1_improved.ncml&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;request reqID=&amp;quot;some_unique_value&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;setContext name=&amp;quot;dap_format&amp;quot;&amp;gt;dap2&amp;lt;/setContext&amp;gt;&lt;br /&gt;
    &amp;lt;setContainer name=&amp;quot;c&amp;quot; space=&amp;quot;catalog&amp;quot;&amp;gt;/data/ncml/fnoc1_improved.ncml&amp;lt;/setContainer&amp;gt;&lt;br /&gt;
    &amp;lt;define name=&amp;quot;d&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;container name=&amp;quot;c&amp;quot;&amp;gt;&amp;lt;/container&amp;gt;&lt;br /&gt;
    &amp;lt;/define&amp;gt;&lt;br /&gt;
    &amp;lt;get type=&amp;quot;das&amp;quot; definition=&amp;quot;d&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/request&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you&#039;re using some other module, you probably want to copy this into a new file &#039;&#039;eclipse_debug.bescmd&#039;&#039; and modify it as your debug needs change, such as to test different responses.&lt;br /&gt;
&lt;br /&gt;
====Debugger Tab====&lt;br /&gt;
&lt;br /&gt;
Next, select the Debugger tab.&lt;br /&gt;
&lt;br /&gt;
* Decide whether to leave &amp;quot;Stop on startup at: main&amp;quot; selected or not.  I usually leave it selected for the first pass just to be sure I can get a breakpoint in the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; main() function in case there was a problem.  You can edit the configuration to deselect it later.&lt;br /&gt;
&lt;br /&gt;
* Under &amp;quot;Debugger Options&amp;quot;, select the &amp;quot;Shared Libraries&amp;quot; tab.&lt;br /&gt;
* Make sure &amp;quot;Load shared library symbols automatically&amp;quot; is selected since our modules are dynamically loaded.&lt;br /&gt;
* Under Directories, click the &amp;quot;Add...&amp;quot; button &lt;br /&gt;
* &amp;quot;Browse...&amp;quot; your way to select the &#039;&#039;.libs&#039;&#039; directory in the module directory.  In our case the full path ends up being: &amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/src/modules/ncml_module/.libs&amp;lt;/tt&amp;gt;.  This should match the module loaded in the bes.conf!&lt;br /&gt;
* Leave &amp;quot;Stop on shared library events&amp;quot; unchecked since this will break on every library that gets loaded otherwise.&lt;br /&gt;
&lt;br /&gt;
====Apply Changes====&lt;br /&gt;
&lt;br /&gt;
On the bottom of the configuration, click &amp;quot;Apply&amp;quot; to save the changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Test It====&lt;br /&gt;
&lt;br /&gt;
If you&#039;re still in the debug configuration window, you can click the Debug button (assuming you have created a valid &#039;&#039;eclipse_debug.bescmd&#039;&#039; file) to run the debugger.  If all worked out and you left Stop on startup at main selected, you will eventually get a breakpoint in the bes StandAloneApp.cc main() function!&lt;br /&gt;
&lt;br /&gt;
From now on, if you have the module selected in the project window, you can click the Debug button (the bug icon) (or use Run &amp;gt; Debug).&lt;br /&gt;
&lt;br /&gt;
You might also want to go to the top-level module initialize call and set a breakpoint to make sure you&#039;re module gets loaded properly and that you can stop on a breakpoint in it.  For the NcML Module, this is the file:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NCMLModule.cc&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
and the function &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;NCMLModule::initialize( const string &amp;amp;modname )&amp;lt;/tt&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5643</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5643"/>
		<updated>2010-04-29T15:35:42Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Debugger Tab */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
You need to have a shrew project checked out and built in debug mode using the standard approach.  The first-time debug build is &#039;&#039;required&#039;&#039; after a fresh checkout in order to get autoconf and configure to run properly and set up the Makefile for all the projects.  Eclipse will then piggyback on these.   &lt;br /&gt;
&lt;br /&gt;
If you do not have this done already, please follow the steps in the next section &amp;quot;Setting Up a Debug Shrew Project&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===Setting Up a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.  For example, to get the fully trunk shrew:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn co http://scm.opendap.org/svn/trunk/shrew&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that shrew uses svn externals, so make sure you know which versions you are getting so when you commit you are commiting to the right place!&lt;br /&gt;
&lt;br /&gt;
To check the externals being used, get the property in the shrew directory you checked out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn propget svn:externals&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which for the trunk shrew returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aries@chinchilla$ svn propget svn:externals&lt;br /&gt;
^/trunk/libdap src/libdap&lt;br /&gt;
^/trunk/bes src/bes&lt;br /&gt;
^/trunk/dap-server src/modules/dap-server&lt;br /&gt;
^/trunk/freeform_handler src/modules/freeform_handler&lt;br /&gt;
^/trunk/fileout_netcdf src/modules/fileout_netcdf&lt;br /&gt;
^/trunk/netcdf_handler src/modules/netcdf_handler&lt;br /&gt;
^/trunk/hdf4_handler src/modules/hdf4_handler&lt;br /&gt;
^/trunk/hdf5_handler src/modules/hdf5_handler&lt;br /&gt;
^/trunk/ncml_module src/modules/ncml_module&lt;br /&gt;
^/trunk/wcs_gateway_module src/modules/wcs_gateway_module&lt;br /&gt;
^/trunk/wcs_module src/modules/wcs_module&lt;br /&gt;
^/trunk/olfs src/olfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES in Hyrax 1.6, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
as the shrew starting point as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
====Configuring a Debug Build====&lt;br /&gt;
&lt;br /&gt;
Since you likely plan to use the shrew project for debugging in Eclipse, you&#039;ll want to run the build_hyrax_debug script in order to make sure the configuration for all the subprojects is set up to perform debug builds (i.e. no optimization and full symbol tables).  That way Eclipse will be able to find breakpoints and let you view variables in a running debug.&lt;br /&gt;
&lt;br /&gt;
In a bash terminal in the top-level shrew directory, type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run autoconf on everything, then configure, then build it.  If there are any missing dependencies, make sure to get them until everything builds.  This will ensure that all the subprojects are configured properly so that the Eclipse Build command, which simply calls &#039;make&#039;, will succeed in compiling a debug version of the specified project.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
==== New Workspace====&lt;br /&gt;
First, create a new workspace if you have an existing one.  You can use:&lt;br /&gt;
&lt;br /&gt;
File &amp;gt; Switch Workspace &amp;gt; Other...&lt;br /&gt;
&lt;br /&gt;
and just create a new directory for the workspace to make the new one.&lt;br /&gt;
&lt;br /&gt;
====New Project for Shrew====&lt;br /&gt;
&lt;br /&gt;
You probably won&#039;t use this directly, but making a top-level project for shrew will let Workspace searches find functions and files in all the subprojects.  More likely, you will be using a specific subproject directly.  (More on this later).&lt;br /&gt;
&lt;br /&gt;
Create a new Project in the workspace. &lt;br /&gt;
&lt;br /&gt;
File &amp;gt; New &amp;gt; C++ Project&lt;br /&gt;
&lt;br /&gt;
In the dialog:&lt;br /&gt;
&lt;br /&gt;
* Enter a project name.  Something like &amp;quot;Shrew&amp;quot; should be OK.&lt;br /&gt;
* UNcheck &amp;quot;Use Default Location&amp;quot; since we want to point at an existing directory&lt;br /&gt;
* Enter the location of the shrew project you checked out and want to debug (you can use Browse...)&lt;br /&gt;
* Select the &amp;quot;Makefile Project&amp;quot; tab since we want to use &#039;make&#039; to build&lt;br /&gt;
* Under the &amp;quot;Makefile Project&amp;quot; select &amp;quot;Empty Project&amp;quot; so Eclipse doesn&#039;t overwrite the existing Makefile&lt;br /&gt;
* Select the &amp;quot;MaxOSX GCC Toolchain&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You will now have a shrew project.  Since Eclipse uses &#039;make all&#039; to build and shrew doesn&#039;t have this target, you can&#039;t use Build on shrew.  In general, you&#039;ll want to create a subproject for each project you plan to modify so that you can do make on each one.  Otherwise, you will want to do makes in the shell as needed.&lt;br /&gt;
&lt;br /&gt;
====New Project for BES and/or Libdap====&lt;br /&gt;
&lt;br /&gt;
If you plan to modify the BES or libdap, you can make a project for each of these as well in the same way, but by pointing the location of the project at the appropriate subdirectory (src/bes or src/libdap) of the top-level shrew checkout.&lt;br /&gt;
&lt;br /&gt;
====New Project for a Module====&lt;br /&gt;
&lt;br /&gt;
In this section, we&#039;ll set up the subproject for a particular module you&#039;ll want to develop or debug.  I will use the ncml_module as the example since this is the one I normally develop and I have added some tools to the project to make setting up debugging files easier.&lt;br /&gt;
&lt;br /&gt;
Create the project just like the shrew project, using an Empty Project in the Makefile Project tab.  Set the location to be the subdirectory of the top-level shrew, e.g.&lt;br /&gt;
&lt;br /&gt;
src/modules/ncml_module&lt;br /&gt;
&lt;br /&gt;
This will create a separate project tab for the module.  If you click on this project and press the Build button (with the hammer icon), just that project will be built.&lt;br /&gt;
&lt;br /&gt;
==Debugging a Module==&lt;br /&gt;
&lt;br /&gt;
In order to debug a given module, we need to set up a Debug configuration for it.  The way I do this for the ncml_module is by using the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; application and pointing it at the same generated &#039;&#039;bes.conf&#039;&#039; file that the Autotest testsuite uses (all the modules should have this structure at this point).  This makes sure the required modules get loaded, and in particular, the testsuite &#039;&#039;bes.conf&#039;&#039; points at the locally compiled module shared object  in the project &#039;&#039;.libs&#039;&#039; directory, so &#039;make install&#039; isn&#039;t required.  We will also need a BES XML command file to automatically run the command we want to debug.  For the ncml_module, this means we load a given NcML file and ask it for a particular response type (DAS, DDS, DDX, DODS) and perhaps with a constraint.  Then we need to make sure Eclipse knows where to find the dynamically loaded library.  Let&#039;s go through these steps one by one.&lt;br /&gt;
&lt;br /&gt;
===Create a New Debug Configuration===&lt;br /&gt;
&lt;br /&gt;
Go to:&lt;br /&gt;
&lt;br /&gt;
Run &amp;gt; Debug Configurations...&lt;br /&gt;
&lt;br /&gt;
When the dialog pops up, select the &amp;quot;C/C++ Application&amp;quot; entry and &amp;quot;New&amp;quot; to create a new configuration.  This should pop up the configuration options for the new Debug Configuration.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll want to make changes in several of the tabs.&lt;br /&gt;
&lt;br /&gt;
==== Main Tab: Select &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as the application to run====&lt;br /&gt;
&lt;br /&gt;
Now we want to set these options to run &#039;&#039;&#039;besstandalone&#039;&#039;&#039; with the arguments we want.  To do this:&lt;br /&gt;
&lt;br /&gt;
* Select the &amp;quot;Browse...&amp;quot; button under C/C++ Application.&lt;br /&gt;
* Go up from the module directory to the shrew directory and into its &amp;quot;bin&amp;quot; directory (this should exist if you did a successful build_hyrax_debug).&lt;br /&gt;
* Select the executable &#039;&#039;&#039;besstandalone&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The application path will then loom something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/bin/besstandalone&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Leave &amp;quot;Connect process input &amp;amp; output to a terminal&amp;quot; checked.  We want to see the output in the Console.&lt;br /&gt;
&lt;br /&gt;
Leave the configuration window open for the next changes.&lt;br /&gt;
&lt;br /&gt;
==== Arguments Tab ====&lt;br /&gt;
&lt;br /&gt;
Now select the &amp;quot;Arguments&amp;quot; tab.&lt;br /&gt;
&lt;br /&gt;
Under the Program Arguments text field, enter the arguments to give to &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as follows.  First, make sure the working directory is the module directory, i.e.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;${workspace_loc:ncml_module}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in our case.  &lt;br /&gt;
&lt;br /&gt;
Our testsuite directory in ncml_module is &amp;quot;tests&amp;quot;, so that&#039;s where our &#039;&#039;bes.conf&#039;&#039; lives.  Note that other modules use the directory &#039;&#039;bes-testsuite&#039;&#039; instead.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the arguments list we will use for the ncml_module:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;-c tests/bes.conf -d&amp;quot;cerr,ncml,ncml:2&amp;quot; -i tests/eclipse_debug.bescmd&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we:&lt;br /&gt;
&lt;br /&gt;
* Specify the bes.conf to use in the testsuite directory so that we load the locally compiled (uninstalled) module&lt;br /&gt;
* Turn on a few debug channels, here: &amp;quot;cerr&amp;quot;, &amp;quot;ncml&amp;quot; and &amp;quot;ncml:2&amp;quot; which the ncml_module uses for debug output.&lt;br /&gt;
* Tell &#039;&#039;&#039;besstandalone&#039;&#039;&#039; to use the file &amp;quot;tests/eclipse_debug.bescmd&amp;quot; as its input file.  &lt;br /&gt;
&lt;br /&gt;
Note that the &amp;quot;eclipse_debug.bescmd&amp;quot; file doesn&#039;t yet exist.  This is a file that we recreate for each test we want to do.  It can be made by hand, but the ncml_module has a script in tests called &amp;quot;generate_bescmd&amp;quot; that creates a BES XML command for a given ncml file and response type.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example eclipse_debug.bescmd for the DAS response for &amp;quot;/data/ncml/fnoc1_improved.ncml&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;request reqID=&amp;quot;some_unique_value&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;setContext name=&amp;quot;dap_format&amp;quot;&amp;gt;dap2&amp;lt;/setContext&amp;gt;&lt;br /&gt;
    &amp;lt;setContainer name=&amp;quot;c&amp;quot; space=&amp;quot;catalog&amp;quot;&amp;gt;/data/ncml/fnoc1_improved.ncml&amp;lt;/setContainer&amp;gt;&lt;br /&gt;
    &amp;lt;define name=&amp;quot;d&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;container name=&amp;quot;c&amp;quot;&amp;gt;&amp;lt;/container&amp;gt;&lt;br /&gt;
    &amp;lt;/define&amp;gt;&lt;br /&gt;
    &amp;lt;get type=&amp;quot;das&amp;quot; definition=&amp;quot;d&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/request&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you&#039;re using some other module, you probably want to copy this into a new file &#039;&#039;eclipse_debug.bescmd&#039;&#039; and modify it as your debug needs change, such as to test different responses.&lt;br /&gt;
&lt;br /&gt;
====Debugger Tab====&lt;br /&gt;
&lt;br /&gt;
Next, select the Debugger tab.&lt;br /&gt;
&lt;br /&gt;
* Decide whether to leave &amp;quot;Stop on startup at: main&amp;quot; selected or not.  I usually leave it selected for the first pass just to be sure I can get a breakpoint in the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; main() function in case there was a problem.  You can edit the configuration to deselect it later.&lt;br /&gt;
* Under the &amp;quot;Debugger Options&amp;quot; Main tab, check off &amp;quot;Use full file path to set breakpoints.&amp;quot; [&#039;&#039;NOTE&#039;&#039;: I think this is needed to get the breakpoints in a dynamically loaded module, but not sure...]&lt;br /&gt;
&lt;br /&gt;
* Under &amp;quot;Debugger Options&amp;quot;, select the &amp;quot;Shared Libraries&amp;quot; tab.&lt;br /&gt;
* Make sure &amp;quot;Load shared library symbols automatically&amp;quot; is selected since our modules are dynamically loaded.&lt;br /&gt;
* Under Directories, click the &amp;quot;Add...&amp;quot; button &lt;br /&gt;
* &amp;quot;Browse...&amp;quot; your way to select the &#039;&#039;.libs&#039;&#039; directory in the module directory.  In our case the full path ends up being: &amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/src/modules/ncml_module/.libs&amp;lt;/tt&amp;gt;.  This should match the module loaded in the bes.conf!&lt;br /&gt;
* Leave &amp;quot;Stop on shared library events&amp;quot; unchecked since this will break on every library that gets loaded otherwise.&lt;br /&gt;
&lt;br /&gt;
====Apply Changes====&lt;br /&gt;
&lt;br /&gt;
On the bottom of the configuration, click &amp;quot;Apply&amp;quot; to save the changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Test It====&lt;br /&gt;
&lt;br /&gt;
If you&#039;re still in the debug configuration window, you can click the Debug button (assuming you have created a valid &#039;&#039;eclipse_debug.bescmd&#039;&#039; file) to run the debugger.  If all worked out and you left Stop on startup at main selected, you will eventually get a breakpoint in the bes StandAloneApp.cc main() function!&lt;br /&gt;
&lt;br /&gt;
From now on, if you have the module selected in the project window, you can click the Debug button (the bug icon) (or use Run &amp;gt; Debug).&lt;br /&gt;
&lt;br /&gt;
You might also want to go to the top-level module initialize call and set a breakpoint to make sure you&#039;re module gets loaded properly and that you can stop on a breakpoint in it.  For the NcML Module, this is the file:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NCMLModule.cc&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
and the function &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;NCMLModule::initialize( const string &amp;amp;modname )&amp;lt;/tt&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5616</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5616"/>
		<updated>2010-04-22T21:17:49Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Arguments Tab */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
You need to have a shrew project checked out and built in debug mode using the standard approach.  The first-time debug build is &#039;&#039;required&#039;&#039; after a fresh checkout in order to get autoconf and configure to run properly and set up the Makefile for all the projects.  Eclipse will then piggyback on these.   &lt;br /&gt;
&lt;br /&gt;
If you do not have this done already, please follow the steps in the next section &amp;quot;Setting Up a Debug Shrew Project&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===Setting Up a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.  For example, to get the fully trunk shrew:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn co http://scm.opendap.org/svn/trunk/shrew&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that shrew uses svn externals, so make sure you know which versions you are getting so when you commit you are commiting to the right place!&lt;br /&gt;
&lt;br /&gt;
To check the externals being used, get the property in the shrew directory you checked out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn propget svn:externals&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which for the trunk shrew returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aries@chinchilla$ svn propget svn:externals&lt;br /&gt;
^/trunk/libdap src/libdap&lt;br /&gt;
^/trunk/bes src/bes&lt;br /&gt;
^/trunk/dap-server src/modules/dap-server&lt;br /&gt;
^/trunk/freeform_handler src/modules/freeform_handler&lt;br /&gt;
^/trunk/fileout_netcdf src/modules/fileout_netcdf&lt;br /&gt;
^/trunk/netcdf_handler src/modules/netcdf_handler&lt;br /&gt;
^/trunk/hdf4_handler src/modules/hdf4_handler&lt;br /&gt;
^/trunk/hdf5_handler src/modules/hdf5_handler&lt;br /&gt;
^/trunk/ncml_module src/modules/ncml_module&lt;br /&gt;
^/trunk/wcs_gateway_module src/modules/wcs_gateway_module&lt;br /&gt;
^/trunk/wcs_module src/modules/wcs_module&lt;br /&gt;
^/trunk/olfs src/olfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES in Hyrax 1.6, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
as the shrew starting point as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
====Configuring a Debug Build====&lt;br /&gt;
&lt;br /&gt;
Since you likely plan to use the shrew project for debugging in Eclipse, you&#039;ll want to run the build_hyrax_debug script in order to make sure the configuration for all the subprojects is set up to perform debug builds (i.e. no optimization and full symbol tables).  That way Eclipse will be able to find breakpoints and let you view variables in a running debug.&lt;br /&gt;
&lt;br /&gt;
In a bash terminal in the top-level shrew directory, type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run autoconf on everything, then configure, then build it.  If there are any missing dependencies, make sure to get them until everything builds.  This will ensure that all the subprojects are configured properly so that the Eclipse Build command, which simply calls &#039;make&#039;, will succeed in compiling a debug version of the specified project.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
==== New Workspace====&lt;br /&gt;
First, create a new workspace if you have an existing one.  You can use:&lt;br /&gt;
&lt;br /&gt;
File &amp;gt; Switch Workspace &amp;gt; Other...&lt;br /&gt;
&lt;br /&gt;
and just create a new directory for the workspace to make the new one.&lt;br /&gt;
&lt;br /&gt;
====New Project for Shrew====&lt;br /&gt;
&lt;br /&gt;
You probably won&#039;t use this directly, but making a top-level project for shrew will let Workspace searches find functions and files in all the subprojects.  More likely, you will be using a specific subproject directly.  (More on this later).&lt;br /&gt;
&lt;br /&gt;
Create a new Project in the workspace. &lt;br /&gt;
&lt;br /&gt;
File &amp;gt; New &amp;gt; C++ Project&lt;br /&gt;
&lt;br /&gt;
In the dialog:&lt;br /&gt;
&lt;br /&gt;
* Enter a project name.  Something like &amp;quot;Shrew&amp;quot; should be OK.&lt;br /&gt;
* UNcheck &amp;quot;Use Default Location&amp;quot; since we want to point at an existing directory&lt;br /&gt;
* Enter the location of the shrew project you checked out and want to debug (you can use Browse...)&lt;br /&gt;
* Select the &amp;quot;Makefile Project&amp;quot; tab since we want to use &#039;make&#039; to build&lt;br /&gt;
* Under the &amp;quot;Makefile Project&amp;quot; select &amp;quot;Empty Project&amp;quot; so Eclipse doesn&#039;t overwrite the existing Makefile&lt;br /&gt;
* Select the &amp;quot;MaxOSX GCC Toolchain&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You will now have a shrew project.  Since Eclipse uses &#039;make all&#039; to build and shrew doesn&#039;t have this target, you can&#039;t use Build on shrew.  In general, you&#039;ll want to create a subproject for each project you plan to modify so that you can do make on each one.  Otherwise, you will want to do makes in the shell as needed.&lt;br /&gt;
&lt;br /&gt;
====New Project for BES and/or Libdap====&lt;br /&gt;
&lt;br /&gt;
If you plan to modify the BES or libdap, you can make a project for each of these as well in the same way, but by pointing the location of the project at the appropriate subdirectory (src/bes or src/libdap) of the top-level shrew checkout.&lt;br /&gt;
&lt;br /&gt;
====New Project for a Module====&lt;br /&gt;
&lt;br /&gt;
In this section, we&#039;ll set up the subproject for a particular module you&#039;ll want to develop or debug.  I will use the ncml_module as the example since this is the one I normally develop and I have added some tools to the project to make setting up debugging files easier.&lt;br /&gt;
&lt;br /&gt;
Create the project just like the shrew project, using an Empty Project in the Makefile Project tab.  Set the location to be the subdirectory of the top-level shrew, e.g.&lt;br /&gt;
&lt;br /&gt;
src/modules/ncml_module&lt;br /&gt;
&lt;br /&gt;
This will create a separate project tab for the module.  If you click on this project and press the Build button (with the hammer icon), just that project will be built.&lt;br /&gt;
&lt;br /&gt;
==Debugging a Module==&lt;br /&gt;
&lt;br /&gt;
In order to debug a given module, we need to set up a Debug configuration for it.  The way I do this for the ncml_module is by using the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; application and pointing it at the same generated &#039;&#039;bes.conf&#039;&#039; file that the Autotest testsuite uses (all the modules should have this structure at this point).  This makes sure the required modules get loaded, and in particular, the testsuite &#039;&#039;bes.conf&#039;&#039; points at the locally compiled module shared object  in the project &#039;&#039;.libs&#039;&#039; directory, so &#039;make install&#039; isn&#039;t required.  We will also need a BES XML command file to automatically run the command we want to debug.  For the ncml_module, this means we load a given NcML file and ask it for a particular response type (DAS, DDS, DDX, DODS) and perhaps with a constraint.  Then we need to make sure Eclipse knows where to find the dynamically loaded library.  Let&#039;s go through these steps one by one.&lt;br /&gt;
&lt;br /&gt;
===Create a New Debug Configuration===&lt;br /&gt;
&lt;br /&gt;
Go to:&lt;br /&gt;
&lt;br /&gt;
Run &amp;gt; Debug Configurations...&lt;br /&gt;
&lt;br /&gt;
When the dialog pops up, select the &amp;quot;C/C++ Application&amp;quot; entry and &amp;quot;New&amp;quot; to create a new configuration.  This should pop up the configuration options for the new Debug Configuration.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll want to make changes in several of the tabs.&lt;br /&gt;
&lt;br /&gt;
==== Main Tab: Select &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as the application to run====&lt;br /&gt;
&lt;br /&gt;
Now we want to set these options to run &#039;&#039;&#039;besstandalone&#039;&#039;&#039; with the arguments we want.  To do this:&lt;br /&gt;
&lt;br /&gt;
* Select the &amp;quot;Browse...&amp;quot; button under C/C++ Application.&lt;br /&gt;
* Go up from the module directory to the shrew directory and into its &amp;quot;bin&amp;quot; directory (this should exist if you did a successful build_hyrax_debug).&lt;br /&gt;
* Select the executable &#039;&#039;&#039;besstandalone&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The application path will then loom something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/bin/besstandalone&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Leave &amp;quot;Connect process input &amp;amp; output to a terminal&amp;quot; checked.  We want to see the output in the Console.&lt;br /&gt;
&lt;br /&gt;
Leave the configuration window open for the next changes.&lt;br /&gt;
&lt;br /&gt;
==== Arguments Tab ====&lt;br /&gt;
&lt;br /&gt;
Now select the &amp;quot;Arguments&amp;quot; tab.&lt;br /&gt;
&lt;br /&gt;
Under the Program Arguments text field, enter the arguments to give to &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as follows.  First, make sure the working directory is the module directory, i.e.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;${workspace_loc:ncml_module}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in our case.  &lt;br /&gt;
&lt;br /&gt;
Our testsuite directory in ncml_module is &amp;quot;tests&amp;quot;, so that&#039;s where our &#039;&#039;bes.conf&#039;&#039; lives.  Note that other modules use the directory &#039;&#039;bes-testsuite&#039;&#039; instead.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the arguments list we will use for the ncml_module:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;-c tests/bes.conf -d&amp;quot;cerr,ncml,ncml:2&amp;quot; -i tests/eclipse_debug.bescmd&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we:&lt;br /&gt;
&lt;br /&gt;
* Specify the bes.conf to use in the testsuite directory so that we load the locally compiled (uninstalled) module&lt;br /&gt;
* Turn on a few debug channels, here: &amp;quot;cerr&amp;quot;, &amp;quot;ncml&amp;quot; and &amp;quot;ncml:2&amp;quot; which the ncml_module uses for debug output.&lt;br /&gt;
* Tell &#039;&#039;&#039;besstandalone&#039;&#039;&#039; to use the file &amp;quot;tests/eclipse_debug.bescmd&amp;quot; as its input file.  &lt;br /&gt;
&lt;br /&gt;
Note that the &amp;quot;eclipse_debug.bescmd&amp;quot; file doesn&#039;t yet exist.  This is a file that we recreate for each test we want to do.  It can be made by hand, but the ncml_module has a script in tests called &amp;quot;generate_bescmd&amp;quot; that creates a BES XML command for a given ncml file and response type.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example eclipse_debug.bescmd for the DAS response for &amp;quot;/data/ncml/fnoc1_improved.ncml&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;request reqID=&amp;quot;some_unique_value&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;setContext name=&amp;quot;dap_format&amp;quot;&amp;gt;dap2&amp;lt;/setContext&amp;gt;&lt;br /&gt;
    &amp;lt;setContainer name=&amp;quot;c&amp;quot; space=&amp;quot;catalog&amp;quot;&amp;gt;/data/ncml/fnoc1_improved.ncml&amp;lt;/setContainer&amp;gt;&lt;br /&gt;
    &amp;lt;define name=&amp;quot;d&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;container name=&amp;quot;c&amp;quot;&amp;gt;&amp;lt;/container&amp;gt;&lt;br /&gt;
    &amp;lt;/define&amp;gt;&lt;br /&gt;
    &amp;lt;get type=&amp;quot;das&amp;quot; definition=&amp;quot;d&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/request&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you&#039;re using some other module, you probably want to copy this into a new file &#039;&#039;eclipse_debug.bescmd&#039;&#039; and modify it as your debug needs change, such as to test different responses.&lt;br /&gt;
&lt;br /&gt;
====Debugger Tab====&lt;br /&gt;
&lt;br /&gt;
Next, select the Debugger tab.&lt;br /&gt;
&lt;br /&gt;
* Decide whether to leave &amp;quot;Stop on startup at: main&amp;quot; selected or not.  I usually leave it selected for the first pass just to be sure I can get a breakpoint in the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; main() function in case there was a problem.  You can edit the configuration to deselect it later.&lt;br /&gt;
&lt;br /&gt;
* Under &amp;quot;Debugger Options&amp;quot;, select the &amp;quot;Shared Libraries&amp;quot; tab.&lt;br /&gt;
* Make sure &amp;quot;Load shared library symbols automatically&amp;quot; is selected since our modules are dynamically loaded.&lt;br /&gt;
* Under Directories, click the &amp;quot;Add...&amp;quot; button &lt;br /&gt;
* &amp;quot;Browse...&amp;quot; your way to select the &#039;&#039;.libs&#039;&#039; directory in the module directory.  In our case the full path ends up being: &amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/src/modules/ncml_module/.libs&amp;lt;/tt&amp;gt;.  This should match the module loaded in the bes.conf!&lt;br /&gt;
* Leave &amp;quot;Stop on shared library events&amp;quot; unchecked since this will break on every library that gets loaded otherwise.&lt;br /&gt;
&lt;br /&gt;
====Apply Changes====&lt;br /&gt;
&lt;br /&gt;
On the bottom of the configuration, click &amp;quot;Apply&amp;quot; to save the changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Test It====&lt;br /&gt;
&lt;br /&gt;
If you&#039;re still in the debug configuration window, you can click the Debug button (assuming you have created a valid &#039;&#039;eclipse_debug.bescmd&#039;&#039; file) to run the debugger.  If all worked out and you left Stop on startup at main selected, you will eventually get a breakpoint in the bes StandAloneApp.cc main() function!&lt;br /&gt;
&lt;br /&gt;
From now on, if you have the module selected in the project window, you can click the Debug button (the bug icon) (or use Run &amp;gt; Debug).&lt;br /&gt;
&lt;br /&gt;
You might also want to go to the top-level module initialize call and set a breakpoint to make sure you&#039;re module gets loaded properly and that you can stop on a breakpoint in it.  For the NcML Module, this is the file:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NCMLModule.cc&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
and the function &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;NCMLModule::initialize( const string &amp;amp;modname )&amp;lt;/tt&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5615</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5615"/>
		<updated>2010-04-22T21:05:41Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Test It */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
You need to have a shrew project checked out and built in debug mode using the standard approach.  The first-time debug build is &#039;&#039;required&#039;&#039; after a fresh checkout in order to get autoconf and configure to run properly and set up the Makefile for all the projects.  Eclipse will then piggyback on these.   &lt;br /&gt;
&lt;br /&gt;
If you do not have this done already, please follow the steps in the next section &amp;quot;Setting Up a Debug Shrew Project&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===Setting Up a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.  For example, to get the fully trunk shrew:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn co http://scm.opendap.org/svn/trunk/shrew&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that shrew uses svn externals, so make sure you know which versions you are getting so when you commit you are commiting to the right place!&lt;br /&gt;
&lt;br /&gt;
To check the externals being used, get the property in the shrew directory you checked out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn propget svn:externals&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which for the trunk shrew returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aries@chinchilla$ svn propget svn:externals&lt;br /&gt;
^/trunk/libdap src/libdap&lt;br /&gt;
^/trunk/bes src/bes&lt;br /&gt;
^/trunk/dap-server src/modules/dap-server&lt;br /&gt;
^/trunk/freeform_handler src/modules/freeform_handler&lt;br /&gt;
^/trunk/fileout_netcdf src/modules/fileout_netcdf&lt;br /&gt;
^/trunk/netcdf_handler src/modules/netcdf_handler&lt;br /&gt;
^/trunk/hdf4_handler src/modules/hdf4_handler&lt;br /&gt;
^/trunk/hdf5_handler src/modules/hdf5_handler&lt;br /&gt;
^/trunk/ncml_module src/modules/ncml_module&lt;br /&gt;
^/trunk/wcs_gateway_module src/modules/wcs_gateway_module&lt;br /&gt;
^/trunk/wcs_module src/modules/wcs_module&lt;br /&gt;
^/trunk/olfs src/olfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES in Hyrax 1.6, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
as the shrew starting point as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
====Configuring a Debug Build====&lt;br /&gt;
&lt;br /&gt;
Since you likely plan to use the shrew project for debugging in Eclipse, you&#039;ll want to run the build_hyrax_debug script in order to make sure the configuration for all the subprojects is set up to perform debug builds (i.e. no optimization and full symbol tables).  That way Eclipse will be able to find breakpoints and let you view variables in a running debug.&lt;br /&gt;
&lt;br /&gt;
In a bash terminal in the top-level shrew directory, type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run autoconf on everything, then configure, then build it.  If there are any missing dependencies, make sure to get them until everything builds.  This will ensure that all the subprojects are configured properly so that the Eclipse Build command, which simply calls &#039;make&#039;, will succeed in compiling a debug version of the specified project.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
==== New Workspace====&lt;br /&gt;
First, create a new workspace if you have an existing one.  You can use:&lt;br /&gt;
&lt;br /&gt;
File &amp;gt; Switch Workspace &amp;gt; Other...&lt;br /&gt;
&lt;br /&gt;
and just create a new directory for the workspace to make the new one.&lt;br /&gt;
&lt;br /&gt;
====New Project for Shrew====&lt;br /&gt;
&lt;br /&gt;
You probably won&#039;t use this directly, but making a top-level project for shrew will let Workspace searches find functions and files in all the subprojects.  More likely, you will be using a specific subproject directly.  (More on this later).&lt;br /&gt;
&lt;br /&gt;
Create a new Project in the workspace. &lt;br /&gt;
&lt;br /&gt;
File &amp;gt; New &amp;gt; C++ Project&lt;br /&gt;
&lt;br /&gt;
In the dialog:&lt;br /&gt;
&lt;br /&gt;
* Enter a project name.  Something like &amp;quot;Shrew&amp;quot; should be OK.&lt;br /&gt;
* UNcheck &amp;quot;Use Default Location&amp;quot; since we want to point at an existing directory&lt;br /&gt;
* Enter the location of the shrew project you checked out and want to debug (you can use Browse...)&lt;br /&gt;
* Select the &amp;quot;Makefile Project&amp;quot; tab since we want to use &#039;make&#039; to build&lt;br /&gt;
* Under the &amp;quot;Makefile Project&amp;quot; select &amp;quot;Empty Project&amp;quot; so Eclipse doesn&#039;t overwrite the existing Makefile&lt;br /&gt;
* Select the &amp;quot;MaxOSX GCC Toolchain&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You will now have a shrew project.  Since Eclipse uses &#039;make all&#039; to build and shrew doesn&#039;t have this target, you can&#039;t use Build on shrew.  In general, you&#039;ll want to create a subproject for each project you plan to modify so that you can do make on each one.  Otherwise, you will want to do makes in the shell as needed.&lt;br /&gt;
&lt;br /&gt;
====New Project for BES and/or Libdap====&lt;br /&gt;
&lt;br /&gt;
If you plan to modify the BES or libdap, you can make a project for each of these as well in the same way, but by pointing the location of the project at the appropriate subdirectory (src/bes or src/libdap) of the top-level shrew checkout.&lt;br /&gt;
&lt;br /&gt;
====New Project for a Module====&lt;br /&gt;
&lt;br /&gt;
In this section, we&#039;ll set up the subproject for a particular module you&#039;ll want to develop or debug.  I will use the ncml_module as the example since this is the one I normally develop and I have added some tools to the project to make setting up debugging files easier.&lt;br /&gt;
&lt;br /&gt;
Create the project just like the shrew project, using an Empty Project in the Makefile Project tab.  Set the location to be the subdirectory of the top-level shrew, e.g.&lt;br /&gt;
&lt;br /&gt;
src/modules/ncml_module&lt;br /&gt;
&lt;br /&gt;
This will create a separate project tab for the module.  If you click on this project and press the Build button (with the hammer icon), just that project will be built.&lt;br /&gt;
&lt;br /&gt;
==Debugging a Module==&lt;br /&gt;
&lt;br /&gt;
In order to debug a given module, we need to set up a Debug configuration for it.  The way I do this for the ncml_module is by using the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; application and pointing it at the same generated &#039;&#039;bes.conf&#039;&#039; file that the Autotest testsuite uses (all the modules should have this structure at this point).  This makes sure the required modules get loaded, and in particular, the testsuite &#039;&#039;bes.conf&#039;&#039; points at the locally compiled module shared object  in the project &#039;&#039;.libs&#039;&#039; directory, so &#039;make install&#039; isn&#039;t required.  We will also need a BES XML command file to automatically run the command we want to debug.  For the ncml_module, this means we load a given NcML file and ask it for a particular response type (DAS, DDS, DDX, DODS) and perhaps with a constraint.  Then we need to make sure Eclipse knows where to find the dynamically loaded library.  Let&#039;s go through these steps one by one.&lt;br /&gt;
&lt;br /&gt;
===Create a New Debug Configuration===&lt;br /&gt;
&lt;br /&gt;
Go to:&lt;br /&gt;
&lt;br /&gt;
Run &amp;gt; Debug Configurations...&lt;br /&gt;
&lt;br /&gt;
When the dialog pops up, select the &amp;quot;C/C++ Application&amp;quot; entry and &amp;quot;New&amp;quot; to create a new configuration.  This should pop up the configuration options for the new Debug Configuration.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll want to make changes in several of the tabs.&lt;br /&gt;
&lt;br /&gt;
==== Main Tab: Select &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as the application to run====&lt;br /&gt;
&lt;br /&gt;
Now we want to set these options to run &#039;&#039;&#039;besstandalone&#039;&#039;&#039; with the arguments we want.  To do this:&lt;br /&gt;
&lt;br /&gt;
* Select the &amp;quot;Browse...&amp;quot; button under C/C++ Application.&lt;br /&gt;
* Go up from the module directory to the shrew directory and into its &amp;quot;bin&amp;quot; directory (this should exist if you did a successful build_hyrax_debug).&lt;br /&gt;
* Select the executable &#039;&#039;&#039;besstandalone&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The application path will then loom something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/bin/besstandalone&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Leave &amp;quot;Connect process input &amp;amp; output to a terminal&amp;quot; checked.  We want to see the output in the Console.&lt;br /&gt;
&lt;br /&gt;
Leave the configuration window open for the next changes.&lt;br /&gt;
&lt;br /&gt;
==== Arguments Tab ====&lt;br /&gt;
&lt;br /&gt;
Now select the &amp;quot;Arguments&amp;quot; tab.&lt;br /&gt;
&lt;br /&gt;
Under the Program Arguments text field, enter the arguments to give to &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as follows.  First, make sure the working directory is the module directory, i.e.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;${workspace_loc:ncml_module}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in our case.  &lt;br /&gt;
&lt;br /&gt;
Our testsuite directory in ncml_module is &amp;quot;tests&amp;quot;, so that&#039;s where our &#039;&#039;bes.conf&#039;&#039; lives.  Note that other modules use the directory &#039;&#039;bes-testsuite&#039;&#039; instead.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the arguments list we will use for the ncml_module:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;-c tests/bes.conf -d&amp;quot;cerr,ncml,ncml:2&amp;quot; -i tests/eclipse_debug.bescmd&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we:&lt;br /&gt;
&lt;br /&gt;
* Specify the bes.conf to use in the testsuite directory so that we load the locally compiled (uninstalled) module&lt;br /&gt;
* Turn on a few debug channels, here: &amp;quot;cerr&amp;quot;, &amp;quot;ncml&amp;quot; and &amp;quot;ncml:2&amp;quot; which the ncml_module uses for debug output.&lt;br /&gt;
* Tell &#039;&#039;&#039;besstandalone&#039;&#039;&#039; to use the file &amp;quot;tests/eclipse_debug.bescmd&amp;quot; as its input file.  &lt;br /&gt;
&lt;br /&gt;
Note that the &amp;quot;eclipse_debug.bescmd&amp;quot; file doesn&#039;t yet exist.  This is a file that we recreate for each test we want to do.  It can be made by hand, but the ncml_module has a script in tests called &amp;quot;generate_bescmd&amp;quot; that creates a BES XML command for a given ncml file and response type.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example eclipse_debug.bescmd for the DAS response for &amp;quot;/data/ncml/fnoc1_improved.ncml&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;request reqID=&amp;quot;some_unique_value&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;setContext name=&amp;quot;dap_format&amp;quot;&amp;gt;dap2&amp;lt;/setContext&amp;gt;&lt;br /&gt;
    &amp;lt;setContainer name=&amp;quot;c&amp;quot; space=&amp;quot;catalog&amp;quot;&amp;gt;/data/ncml/fnoc1_improved.ncml&amp;lt;/setCo&lt;br /&gt;
ntainer&amp;gt;&lt;br /&gt;
    &amp;lt;define name=&amp;quot;d&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;container name=&amp;quot;c&amp;quot;&amp;gt;&amp;lt;/container&amp;gt;&lt;br /&gt;
    &amp;lt;/define&amp;gt;&lt;br /&gt;
    &amp;lt;get type=&amp;quot;das&amp;quot; definition=&amp;quot;d&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/request&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you&#039;re using some other module, you probably want to copy this into a new file &#039;&#039;eclipse_debug.bescmd&#039;&#039; and modify it as your debug needs change, such as to test different responses.&lt;br /&gt;
&lt;br /&gt;
====Debugger Tab====&lt;br /&gt;
&lt;br /&gt;
Next, select the Debugger tab.&lt;br /&gt;
&lt;br /&gt;
* Decide whether to leave &amp;quot;Stop on startup at: main&amp;quot; selected or not.  I usually leave it selected for the first pass just to be sure I can get a breakpoint in the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; main() function in case there was a problem.  You can edit the configuration to deselect it later.&lt;br /&gt;
&lt;br /&gt;
* Under &amp;quot;Debugger Options&amp;quot;, select the &amp;quot;Shared Libraries&amp;quot; tab.&lt;br /&gt;
* Make sure &amp;quot;Load shared library symbols automatically&amp;quot; is selected since our modules are dynamically loaded.&lt;br /&gt;
* Under Directories, click the &amp;quot;Add...&amp;quot; button &lt;br /&gt;
* &amp;quot;Browse...&amp;quot; your way to select the &#039;&#039;.libs&#039;&#039; directory in the module directory.  In our case the full path ends up being: &amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/src/modules/ncml_module/.libs&amp;lt;/tt&amp;gt;.  This should match the module loaded in the bes.conf!&lt;br /&gt;
* Leave &amp;quot;Stop on shared library events&amp;quot; unchecked since this will break on every library that gets loaded otherwise.&lt;br /&gt;
&lt;br /&gt;
====Apply Changes====&lt;br /&gt;
&lt;br /&gt;
On the bottom of the configuration, click &amp;quot;Apply&amp;quot; to save the changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Test It====&lt;br /&gt;
&lt;br /&gt;
If you&#039;re still in the debug configuration window, you can click the Debug button (assuming you have created a valid &#039;&#039;eclipse_debug.bescmd&#039;&#039; file) to run the debugger.  If all worked out and you left Stop on startup at main selected, you will eventually get a breakpoint in the bes StandAloneApp.cc main() function!&lt;br /&gt;
&lt;br /&gt;
From now on, if you have the module selected in the project window, you can click the Debug button (the bug icon) (or use Run &amp;gt; Debug).&lt;br /&gt;
&lt;br /&gt;
You might also want to go to the top-level module initialize call and set a breakpoint to make sure you&#039;re module gets loaded properly and that you can stop on a breakpoint in it.  For the NcML Module, this is the file:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NCMLModule.cc&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
and the function &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;NCMLModule::initialize( const string &amp;amp;modname )&amp;lt;/tt&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5614</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5614"/>
		<updated>2010-04-22T21:05:19Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Create a New Debug Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
You need to have a shrew project checked out and built in debug mode using the standard approach.  The first-time debug build is &#039;&#039;required&#039;&#039; after a fresh checkout in order to get autoconf and configure to run properly and set up the Makefile for all the projects.  Eclipse will then piggyback on these.   &lt;br /&gt;
&lt;br /&gt;
If you do not have this done already, please follow the steps in the next section &amp;quot;Setting Up a Debug Shrew Project&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===Setting Up a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.  For example, to get the fully trunk shrew:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn co http://scm.opendap.org/svn/trunk/shrew&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that shrew uses svn externals, so make sure you know which versions you are getting so when you commit you are commiting to the right place!&lt;br /&gt;
&lt;br /&gt;
To check the externals being used, get the property in the shrew directory you checked out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn propget svn:externals&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which for the trunk shrew returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aries@chinchilla$ svn propget svn:externals&lt;br /&gt;
^/trunk/libdap src/libdap&lt;br /&gt;
^/trunk/bes src/bes&lt;br /&gt;
^/trunk/dap-server src/modules/dap-server&lt;br /&gt;
^/trunk/freeform_handler src/modules/freeform_handler&lt;br /&gt;
^/trunk/fileout_netcdf src/modules/fileout_netcdf&lt;br /&gt;
^/trunk/netcdf_handler src/modules/netcdf_handler&lt;br /&gt;
^/trunk/hdf4_handler src/modules/hdf4_handler&lt;br /&gt;
^/trunk/hdf5_handler src/modules/hdf5_handler&lt;br /&gt;
^/trunk/ncml_module src/modules/ncml_module&lt;br /&gt;
^/trunk/wcs_gateway_module src/modules/wcs_gateway_module&lt;br /&gt;
^/trunk/wcs_module src/modules/wcs_module&lt;br /&gt;
^/trunk/olfs src/olfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES in Hyrax 1.6, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
as the shrew starting point as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
====Configuring a Debug Build====&lt;br /&gt;
&lt;br /&gt;
Since you likely plan to use the shrew project for debugging in Eclipse, you&#039;ll want to run the build_hyrax_debug script in order to make sure the configuration for all the subprojects is set up to perform debug builds (i.e. no optimization and full symbol tables).  That way Eclipse will be able to find breakpoints and let you view variables in a running debug.&lt;br /&gt;
&lt;br /&gt;
In a bash terminal in the top-level shrew directory, type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run autoconf on everything, then configure, then build it.  If there are any missing dependencies, make sure to get them until everything builds.  This will ensure that all the subprojects are configured properly so that the Eclipse Build command, which simply calls &#039;make&#039;, will succeed in compiling a debug version of the specified project.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
==== New Workspace====&lt;br /&gt;
First, create a new workspace if you have an existing one.  You can use:&lt;br /&gt;
&lt;br /&gt;
File &amp;gt; Switch Workspace &amp;gt; Other...&lt;br /&gt;
&lt;br /&gt;
and just create a new directory for the workspace to make the new one.&lt;br /&gt;
&lt;br /&gt;
====New Project for Shrew====&lt;br /&gt;
&lt;br /&gt;
You probably won&#039;t use this directly, but making a top-level project for shrew will let Workspace searches find functions and files in all the subprojects.  More likely, you will be using a specific subproject directly.  (More on this later).&lt;br /&gt;
&lt;br /&gt;
Create a new Project in the workspace. &lt;br /&gt;
&lt;br /&gt;
File &amp;gt; New &amp;gt; C++ Project&lt;br /&gt;
&lt;br /&gt;
In the dialog:&lt;br /&gt;
&lt;br /&gt;
* Enter a project name.  Something like &amp;quot;Shrew&amp;quot; should be OK.&lt;br /&gt;
* UNcheck &amp;quot;Use Default Location&amp;quot; since we want to point at an existing directory&lt;br /&gt;
* Enter the location of the shrew project you checked out and want to debug (you can use Browse...)&lt;br /&gt;
* Select the &amp;quot;Makefile Project&amp;quot; tab since we want to use &#039;make&#039; to build&lt;br /&gt;
* Under the &amp;quot;Makefile Project&amp;quot; select &amp;quot;Empty Project&amp;quot; so Eclipse doesn&#039;t overwrite the existing Makefile&lt;br /&gt;
* Select the &amp;quot;MaxOSX GCC Toolchain&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You will now have a shrew project.  Since Eclipse uses &#039;make all&#039; to build and shrew doesn&#039;t have this target, you can&#039;t use Build on shrew.  In general, you&#039;ll want to create a subproject for each project you plan to modify so that you can do make on each one.  Otherwise, you will want to do makes in the shell as needed.&lt;br /&gt;
&lt;br /&gt;
====New Project for BES and/or Libdap====&lt;br /&gt;
&lt;br /&gt;
If you plan to modify the BES or libdap, you can make a project for each of these as well in the same way, but by pointing the location of the project at the appropriate subdirectory (src/bes or src/libdap) of the top-level shrew checkout.&lt;br /&gt;
&lt;br /&gt;
====New Project for a Module====&lt;br /&gt;
&lt;br /&gt;
In this section, we&#039;ll set up the subproject for a particular module you&#039;ll want to develop or debug.  I will use the ncml_module as the example since this is the one I normally develop and I have added some tools to the project to make setting up debugging files easier.&lt;br /&gt;
&lt;br /&gt;
Create the project just like the shrew project, using an Empty Project in the Makefile Project tab.  Set the location to be the subdirectory of the top-level shrew, e.g.&lt;br /&gt;
&lt;br /&gt;
src/modules/ncml_module&lt;br /&gt;
&lt;br /&gt;
This will create a separate project tab for the module.  If you click on this project and press the Build button (with the hammer icon), just that project will be built.&lt;br /&gt;
&lt;br /&gt;
==Debugging a Module==&lt;br /&gt;
&lt;br /&gt;
In order to debug a given module, we need to set up a Debug configuration for it.  The way I do this for the ncml_module is by using the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; application and pointing it at the same generated &#039;&#039;bes.conf&#039;&#039; file that the Autotest testsuite uses (all the modules should have this structure at this point).  This makes sure the required modules get loaded, and in particular, the testsuite &#039;&#039;bes.conf&#039;&#039; points at the locally compiled module shared object  in the project &#039;&#039;.libs&#039;&#039; directory, so &#039;make install&#039; isn&#039;t required.  We will also need a BES XML command file to automatically run the command we want to debug.  For the ncml_module, this means we load a given NcML file and ask it for a particular response type (DAS, DDS, DDX, DODS) and perhaps with a constraint.  Then we need to make sure Eclipse knows where to find the dynamically loaded library.  Let&#039;s go through these steps one by one.&lt;br /&gt;
&lt;br /&gt;
===Create a New Debug Configuration===&lt;br /&gt;
&lt;br /&gt;
Go to:&lt;br /&gt;
&lt;br /&gt;
Run &amp;gt; Debug Configurations...&lt;br /&gt;
&lt;br /&gt;
When the dialog pops up, select the &amp;quot;C/C++ Application&amp;quot; entry and &amp;quot;New&amp;quot; to create a new configuration.  This should pop up the configuration options for the new Debug Configuration.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll want to make changes in several of the tabs.&lt;br /&gt;
&lt;br /&gt;
==== Main Tab: Select &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as the application to run====&lt;br /&gt;
&lt;br /&gt;
Now we want to set these options to run &#039;&#039;&#039;besstandalone&#039;&#039;&#039; with the arguments we want.  To do this:&lt;br /&gt;
&lt;br /&gt;
* Select the &amp;quot;Browse...&amp;quot; button under C/C++ Application.&lt;br /&gt;
* Go up from the module directory to the shrew directory and into its &amp;quot;bin&amp;quot; directory (this should exist if you did a successful build_hyrax_debug).&lt;br /&gt;
* Select the executable &#039;&#039;&#039;besstandalone&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The application path will then loom something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/bin/besstandalone&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Leave &amp;quot;Connect process input &amp;amp; output to a terminal&amp;quot; checked.  We want to see the output in the Console.&lt;br /&gt;
&lt;br /&gt;
Leave the configuration window open for the next changes.&lt;br /&gt;
&lt;br /&gt;
==== Arguments Tab ====&lt;br /&gt;
&lt;br /&gt;
Now select the &amp;quot;Arguments&amp;quot; tab.&lt;br /&gt;
&lt;br /&gt;
Under the Program Arguments text field, enter the arguments to give to &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as follows.  First, make sure the working directory is the module directory, i.e.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;${workspace_loc:ncml_module}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in our case.  &lt;br /&gt;
&lt;br /&gt;
Our testsuite directory in ncml_module is &amp;quot;tests&amp;quot;, so that&#039;s where our &#039;&#039;bes.conf&#039;&#039; lives.  Note that other modules use the directory &#039;&#039;bes-testsuite&#039;&#039; instead.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the arguments list we will use for the ncml_module:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;-c tests/bes.conf -d&amp;quot;cerr,ncml,ncml:2&amp;quot; -i tests/eclipse_debug.bescmd&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we:&lt;br /&gt;
&lt;br /&gt;
* Specify the bes.conf to use in the testsuite directory so that we load the locally compiled (uninstalled) module&lt;br /&gt;
* Turn on a few debug channels, here: &amp;quot;cerr&amp;quot;, &amp;quot;ncml&amp;quot; and &amp;quot;ncml:2&amp;quot; which the ncml_module uses for debug output.&lt;br /&gt;
* Tell &#039;&#039;&#039;besstandalone&#039;&#039;&#039; to use the file &amp;quot;tests/eclipse_debug.bescmd&amp;quot; as its input file.  &lt;br /&gt;
&lt;br /&gt;
Note that the &amp;quot;eclipse_debug.bescmd&amp;quot; file doesn&#039;t yet exist.  This is a file that we recreate for each test we want to do.  It can be made by hand, but the ncml_module has a script in tests called &amp;quot;generate_bescmd&amp;quot; that creates a BES XML command for a given ncml file and response type.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example eclipse_debug.bescmd for the DAS response for &amp;quot;/data/ncml/fnoc1_improved.ncml&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;request reqID=&amp;quot;some_unique_value&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;setContext name=&amp;quot;dap_format&amp;quot;&amp;gt;dap2&amp;lt;/setContext&amp;gt;&lt;br /&gt;
    &amp;lt;setContainer name=&amp;quot;c&amp;quot; space=&amp;quot;catalog&amp;quot;&amp;gt;/data/ncml/fnoc1_improved.ncml&amp;lt;/setCo&lt;br /&gt;
ntainer&amp;gt;&lt;br /&gt;
    &amp;lt;define name=&amp;quot;d&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;container name=&amp;quot;c&amp;quot;&amp;gt;&amp;lt;/container&amp;gt;&lt;br /&gt;
    &amp;lt;/define&amp;gt;&lt;br /&gt;
    &amp;lt;get type=&amp;quot;das&amp;quot; definition=&amp;quot;d&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/request&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you&#039;re using some other module, you probably want to copy this into a new file &#039;&#039;eclipse_debug.bescmd&#039;&#039; and modify it as your debug needs change, such as to test different responses.&lt;br /&gt;
&lt;br /&gt;
====Debugger Tab====&lt;br /&gt;
&lt;br /&gt;
Next, select the Debugger tab.&lt;br /&gt;
&lt;br /&gt;
* Decide whether to leave &amp;quot;Stop on startup at: main&amp;quot; selected or not.  I usually leave it selected for the first pass just to be sure I can get a breakpoint in the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; main() function in case there was a problem.  You can edit the configuration to deselect it later.&lt;br /&gt;
&lt;br /&gt;
* Under &amp;quot;Debugger Options&amp;quot;, select the &amp;quot;Shared Libraries&amp;quot; tab.&lt;br /&gt;
* Make sure &amp;quot;Load shared library symbols automatically&amp;quot; is selected since our modules are dynamically loaded.&lt;br /&gt;
* Under Directories, click the &amp;quot;Add...&amp;quot; button &lt;br /&gt;
* &amp;quot;Browse...&amp;quot; your way to select the &#039;&#039;.libs&#039;&#039; directory in the module directory.  In our case the full path ends up being: &amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/src/modules/ncml_module/.libs&amp;lt;/tt&amp;gt;.  This should match the module loaded in the bes.conf!&lt;br /&gt;
* Leave &amp;quot;Stop on shared library events&amp;quot; unchecked since this will break on every library that gets loaded otherwise.&lt;br /&gt;
&lt;br /&gt;
====Apply Changes====&lt;br /&gt;
&lt;br /&gt;
On the bottom of the configuration, click &amp;quot;Apply&amp;quot; to save the changes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Test It====&lt;br /&gt;
&lt;br /&gt;
If you&#039;re still in the debug configuration window, you can click the Debug button (assuming you have created a valid &#039;&#039;eclipse_debug.bescmd&#039;&#039; file) to run the debugger.  If all worked out and you left Stop on startup at main selected, you will eventually get a breakpoint in the bes StandAloneApp.cc main() function!&lt;br /&gt;
&lt;br /&gt;
From now on, if you have the module selected in the project window, you can click the Debug button (the bug icon) (or use Run &amp;gt; Debug).&lt;br /&gt;
&lt;br /&gt;
You might also want to go to the top-level module initialize call and set a breakpoint to make sure you&#039;re module gets loaded properly and that you can stop on a breakpoint in it.  For the NcML Module, this is the file:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;NCMLModule.cc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
and the function &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;NCMLModule::initialize( const string &amp;amp;modname )&amp;lt;/tt&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5613</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5613"/>
		<updated>2010-04-22T20:50:11Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Debugging a Module */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
You need to have a shrew project checked out and built in debug mode using the standard approach.  The first-time debug build is &#039;&#039;required&#039;&#039; after a fresh checkout in order to get autoconf and configure to run properly and set up the Makefile for all the projects.  Eclipse will then piggyback on these.   &lt;br /&gt;
&lt;br /&gt;
If you do not have this done already, please follow the steps in the next section &amp;quot;Setting Up a Debug Shrew Project&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===Setting Up a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.  For example, to get the fully trunk shrew:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn co http://scm.opendap.org/svn/trunk/shrew&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that shrew uses svn externals, so make sure you know which versions you are getting so when you commit you are commiting to the right place!&lt;br /&gt;
&lt;br /&gt;
To check the externals being used, get the property in the shrew directory you checked out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn propget svn:externals&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which for the trunk shrew returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aries@chinchilla$ svn propget svn:externals&lt;br /&gt;
^/trunk/libdap src/libdap&lt;br /&gt;
^/trunk/bes src/bes&lt;br /&gt;
^/trunk/dap-server src/modules/dap-server&lt;br /&gt;
^/trunk/freeform_handler src/modules/freeform_handler&lt;br /&gt;
^/trunk/fileout_netcdf src/modules/fileout_netcdf&lt;br /&gt;
^/trunk/netcdf_handler src/modules/netcdf_handler&lt;br /&gt;
^/trunk/hdf4_handler src/modules/hdf4_handler&lt;br /&gt;
^/trunk/hdf5_handler src/modules/hdf5_handler&lt;br /&gt;
^/trunk/ncml_module src/modules/ncml_module&lt;br /&gt;
^/trunk/wcs_gateway_module src/modules/wcs_gateway_module&lt;br /&gt;
^/trunk/wcs_module src/modules/wcs_module&lt;br /&gt;
^/trunk/olfs src/olfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES in Hyrax 1.6, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
as the shrew starting point as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
====Configuring a Debug Build====&lt;br /&gt;
&lt;br /&gt;
Since you likely plan to use the shrew project for debugging in Eclipse, you&#039;ll want to run the build_hyrax_debug script in order to make sure the configuration for all the subprojects is set up to perform debug builds (i.e. no optimization and full symbol tables).  That way Eclipse will be able to find breakpoints and let you view variables in a running debug.&lt;br /&gt;
&lt;br /&gt;
In a bash terminal in the top-level shrew directory, type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run autoconf on everything, then configure, then build it.  If there are any missing dependencies, make sure to get them until everything builds.  This will ensure that all the subprojects are configured properly so that the Eclipse Build command, which simply calls &#039;make&#039;, will succeed in compiling a debug version of the specified project.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
==== New Workspace====&lt;br /&gt;
First, create a new workspace if you have an existing one.  You can use:&lt;br /&gt;
&lt;br /&gt;
File &amp;gt; Switch Workspace &amp;gt; Other...&lt;br /&gt;
&lt;br /&gt;
and just create a new directory for the workspace to make the new one.&lt;br /&gt;
&lt;br /&gt;
====New Project for Shrew====&lt;br /&gt;
&lt;br /&gt;
You probably won&#039;t use this directly, but making a top-level project for shrew will let Workspace searches find functions and files in all the subprojects.  More likely, you will be using a specific subproject directly.  (More on this later).&lt;br /&gt;
&lt;br /&gt;
Create a new Project in the workspace. &lt;br /&gt;
&lt;br /&gt;
File &amp;gt; New &amp;gt; C++ Project&lt;br /&gt;
&lt;br /&gt;
In the dialog:&lt;br /&gt;
&lt;br /&gt;
* Enter a project name.  Something like &amp;quot;Shrew&amp;quot; should be OK.&lt;br /&gt;
* UNcheck &amp;quot;Use Default Location&amp;quot; since we want to point at an existing directory&lt;br /&gt;
* Enter the location of the shrew project you checked out and want to debug (you can use Browse...)&lt;br /&gt;
* Select the &amp;quot;Makefile Project&amp;quot; tab since we want to use &#039;make&#039; to build&lt;br /&gt;
* Under the &amp;quot;Makefile Project&amp;quot; select &amp;quot;Empty Project&amp;quot; so Eclipse doesn&#039;t overwrite the existing Makefile&lt;br /&gt;
* Select the &amp;quot;MaxOSX GCC Toolchain&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You will now have a shrew project.  Since Eclipse uses &#039;make all&#039; to build and shrew doesn&#039;t have this target, you can&#039;t use Build on shrew.  In general, you&#039;ll want to create a subproject for each project you plan to modify so that you can do make on each one.  Otherwise, you will want to do makes in the shell as needed.&lt;br /&gt;
&lt;br /&gt;
====New Project for BES and/or Libdap====&lt;br /&gt;
&lt;br /&gt;
If you plan to modify the BES or libdap, you can make a project for each of these as well in the same way, but by pointing the location of the project at the appropriate subdirectory (src/bes or src/libdap) of the top-level shrew checkout.&lt;br /&gt;
&lt;br /&gt;
====New Project for a Module====&lt;br /&gt;
&lt;br /&gt;
In this section, we&#039;ll set up the subproject for a particular module you&#039;ll want to develop or debug.  I will use the ncml_module as the example since this is the one I normally develop and I have added some tools to the project to make setting up debugging files easier.&lt;br /&gt;
&lt;br /&gt;
Create the project just like the shrew project, using an Empty Project in the Makefile Project tab.  Set the location to be the subdirectory of the top-level shrew, e.g.&lt;br /&gt;
&lt;br /&gt;
src/modules/ncml_module&lt;br /&gt;
&lt;br /&gt;
This will create a separate project tab for the module.  If you click on this project and press the Build button (with the hammer icon), just that project will be built.&lt;br /&gt;
&lt;br /&gt;
==Debugging a Module==&lt;br /&gt;
&lt;br /&gt;
In order to debug a given module, we need to set up a Debug configuration for it.  The way I do this for the ncml_module is by using the &#039;&#039;&#039;besstandalone&#039;&#039;&#039; application and pointing it at the same generated &#039;&#039;bes.conf&#039;&#039; file that the Autotest testsuite uses (all the modules should have this structure at this point).  This makes sure the required modules get loaded, and in particular, the testsuite &#039;&#039;bes.conf&#039;&#039; points at the locally compiled module shared object  in the project &#039;&#039;.libs&#039;&#039; directory, so &#039;make install&#039; isn&#039;t required.  We will also need a BES XML command file to automatically run the command we want to debug.  For the ncml_module, this means we load a given NcML file and ask it for a particular response type (DAS, DDS, DDX, DODS) and perhaps with a constraint.  Then we need to make sure Eclipse knows where to find the dynamically loaded library.  Let&#039;s go through these steps one by one.&lt;br /&gt;
&lt;br /&gt;
===Create a New Debug Configuration===&lt;br /&gt;
&lt;br /&gt;
Go to:&lt;br /&gt;
&lt;br /&gt;
Run &amp;gt; Debug Configurations...&lt;br /&gt;
&lt;br /&gt;
When the dialog pops up, select the &amp;quot;C/C++ Application&amp;quot; entry and &amp;quot;New&amp;quot; to create a new configuration.  This should pop up the configuration options for the new Debug Configuration.&lt;br /&gt;
&lt;br /&gt;
==== Select &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as the application to run====&lt;br /&gt;
&lt;br /&gt;
Now we want to set these options to run &#039;&#039;&#039;besstandalone&#039;&#039;&#039; with the arguments we want.  To do this:&lt;br /&gt;
&lt;br /&gt;
* Select the &amp;quot;Browse...&amp;quot; button under C/C++ Application.&lt;br /&gt;
* Go up from the module directory to the shrew directory and into its &amp;quot;bin&amp;quot; directory (this should exist if you did a successful build_hyrax_debug).&lt;br /&gt;
* Select the executable &#039;&#039;&#039;besstandalone&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The application path will then loom something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/Users/aries/src/module_dev_1.6/bin/besstandalone&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Leave &amp;quot;Connect process input &amp;amp; output to a terminal&amp;quot; checked.  We want to see the output in the Console.&lt;br /&gt;
&lt;br /&gt;
Leave the configuration window open for the next changes.&lt;br /&gt;
&lt;br /&gt;
==== Arguments ====&lt;br /&gt;
&lt;br /&gt;
Now select the &amp;quot;Arguments&amp;quot; tab.&lt;br /&gt;
&lt;br /&gt;
Under the Program Arguments text field, enter the arguments to give to &#039;&#039;&#039;besstandalone&#039;&#039;&#039; as follows.  First, make sure the working directory is the module directory, i.e.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;${workspace_loc:ncml_module}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in our case.  &lt;br /&gt;
&lt;br /&gt;
Our testsuite directory in ncml_module is &amp;quot;tests&amp;quot;, so that&#039;s where our &#039;&#039;bes.conf&#039;&#039; lives.  Note that other modules use the directory &#039;&#039;bes-testsuite&#039;&#039; instead.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the arguments list we will use for the ncml_module:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;-c tests/bes.conf -d&amp;quot;cerr,ncml,ncml:2&amp;quot; -i tests/eclipse_debug.bescmd&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we:&lt;br /&gt;
&lt;br /&gt;
* Specify the bes.conf to use in the testsuite directory so that we load the locally compiled (uninstalled) module&lt;br /&gt;
* Turn on a few debug channels, here: &amp;quot;cerr&amp;quot;, &amp;quot;ncml&amp;quot; and &amp;quot;ncml:2&amp;quot; which the ncml_module uses for debug output.&lt;br /&gt;
* Tell &#039;&#039;&#039;besstandalone&#039;&#039;&#039; to use the file &amp;quot;tests/eclipse_debug.bescmd&amp;quot; as its input file.  &lt;br /&gt;
&lt;br /&gt;
Note that the &amp;quot;eclipse_debug.bescmd&amp;quot; file doesn&#039;t yet exist.  This is a file that we recreate for each test we want to do.  It can be made by hand, but the ncml_module has a script in tests called &amp;quot;generate_bescmd&amp;quot; that creates a BES XML command for a given ncml file and response type.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example eclipse_debug.bescmd for the DAS response for &amp;quot;/data/ncml/fnoc1_improved.ncml&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;request reqID=&amp;quot;some_unique_value&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;setContext name=&amp;quot;dap_format&amp;quot;&amp;gt;dap2&amp;lt;/setContext&amp;gt;&lt;br /&gt;
    &amp;lt;setContainer name=&amp;quot;c&amp;quot; space=&amp;quot;catalog&amp;quot;&amp;gt;/data/ncml/fnoc1_improved.ncml&amp;lt;/setCo&lt;br /&gt;
ntainer&amp;gt;&lt;br /&gt;
    &amp;lt;define name=&amp;quot;d&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;container name=&amp;quot;c&amp;quot;&amp;gt;&amp;lt;/container&amp;gt;&lt;br /&gt;
    &amp;lt;/define&amp;gt;&lt;br /&gt;
    &amp;lt;get type=&amp;quot;das&amp;quot; definition=&amp;quot;d&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;/request&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you&#039;re using some other module, you probably want to copy this into a new file &#039;&#039;eclipse_debug.bescmd&#039;&#039; and modify it as your debug needs change, such as to test different responses.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5612</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5612"/>
		<updated>2010-04-22T20:11:27Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Eclipse as an IDE for Shew */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
You need to have a shrew project checked out and built in debug mode using the standard approach.  The first-time debug build is &#039;&#039;required&#039;&#039; after a fresh checkout in order to get autoconf and configure to run properly and set up the Makefile for all the projects.  Eclipse will then piggyback on these.   &lt;br /&gt;
&lt;br /&gt;
If you do not have this done already, please follow the steps in the next section &amp;quot;Setting Up a Debug Shrew Project&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===Setting Up a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.  For example, to get the fully trunk shrew:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn co http://scm.opendap.org/svn/trunk/shrew&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that shrew uses svn externals, so make sure you know which versions you are getting so when you commit you are commiting to the right place!&lt;br /&gt;
&lt;br /&gt;
To check the externals being used, get the property in the shrew directory you checked out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn propget svn:externals&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which for the trunk shrew returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aries@chinchilla$ svn propget svn:externals&lt;br /&gt;
^/trunk/libdap src/libdap&lt;br /&gt;
^/trunk/bes src/bes&lt;br /&gt;
^/trunk/dap-server src/modules/dap-server&lt;br /&gt;
^/trunk/freeform_handler src/modules/freeform_handler&lt;br /&gt;
^/trunk/fileout_netcdf src/modules/fileout_netcdf&lt;br /&gt;
^/trunk/netcdf_handler src/modules/netcdf_handler&lt;br /&gt;
^/trunk/hdf4_handler src/modules/hdf4_handler&lt;br /&gt;
^/trunk/hdf5_handler src/modules/hdf5_handler&lt;br /&gt;
^/trunk/ncml_module src/modules/ncml_module&lt;br /&gt;
^/trunk/wcs_gateway_module src/modules/wcs_gateway_module&lt;br /&gt;
^/trunk/wcs_module src/modules/wcs_module&lt;br /&gt;
^/trunk/olfs src/olfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES in Hyrax 1.6, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
as the shrew starting point as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
====Configuring a Debug Build====&lt;br /&gt;
&lt;br /&gt;
Since you likely plan to use the shrew project for debugging in Eclipse, you&#039;ll want to run the build_hyrax_debug script in order to make sure the configuration for all the subprojects is set up to perform debug builds (i.e. no optimization and full symbol tables).  That way Eclipse will be able to find breakpoints and let you view variables in a running debug.&lt;br /&gt;
&lt;br /&gt;
In a bash terminal in the top-level shrew directory, type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run autoconf on everything, then configure, then build it.  If there are any missing dependencies, make sure to get them until everything builds.  This will ensure that all the subprojects are configured properly so that the Eclipse Build command, which simply calls &#039;make&#039;, will succeed in compiling a debug version of the specified project.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
==== New Workspace====&lt;br /&gt;
First, create a new workspace if you have an existing one.  You can use:&lt;br /&gt;
&lt;br /&gt;
File &amp;gt; Switch Workspace &amp;gt; Other...&lt;br /&gt;
&lt;br /&gt;
and just create a new directory for the workspace to make the new one.&lt;br /&gt;
&lt;br /&gt;
====New Project for Shrew====&lt;br /&gt;
&lt;br /&gt;
You probably won&#039;t use this directly, but making a top-level project for shrew will let Workspace searches find functions and files in all the subprojects.  More likely, you will be using a specific subproject directly.  (More on this later).&lt;br /&gt;
&lt;br /&gt;
Create a new Project in the workspace. &lt;br /&gt;
&lt;br /&gt;
File &amp;gt; New &amp;gt; C++ Project&lt;br /&gt;
&lt;br /&gt;
In the dialog:&lt;br /&gt;
&lt;br /&gt;
* Enter a project name.  Something like &amp;quot;Shrew&amp;quot; should be OK.&lt;br /&gt;
* UNcheck &amp;quot;Use Default Location&amp;quot; since we want to point at an existing directory&lt;br /&gt;
* Enter the location of the shrew project you checked out and want to debug (you can use Browse...)&lt;br /&gt;
* Select the &amp;quot;Makefile Project&amp;quot; tab since we want to use &#039;make&#039; to build&lt;br /&gt;
* Under the &amp;quot;Makefile Project&amp;quot; select &amp;quot;Empty Project&amp;quot; so Eclipse doesn&#039;t overwrite the existing Makefile&lt;br /&gt;
* Select the &amp;quot;MaxOSX GCC Toolchain&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You will now have a shrew project.  Since Eclipse uses &#039;make all&#039; to build and shrew doesn&#039;t have this target, you can&#039;t use Build on shrew.  In general, you&#039;ll want to create a subproject for each project you plan to modify so that you can do make on each one.  Otherwise, you will want to do makes in the shell as needed.&lt;br /&gt;
&lt;br /&gt;
====New Project for BES and/or Libdap====&lt;br /&gt;
&lt;br /&gt;
If you plan to modify the BES or libdap, you can make a project for each of these as well in the same way, but by pointing the location of the project at the appropriate subdirectory (src/bes or src/libdap) of the top-level shrew checkout.&lt;br /&gt;
&lt;br /&gt;
====New Project for a Module====&lt;br /&gt;
&lt;br /&gt;
In this section, we&#039;ll set up the subproject for a particular module you&#039;ll want to develop or debug.  I will use the ncml_module as the example since this is the one I normally develop and I have added some tools to the project to make setting up debugging files easier.&lt;br /&gt;
&lt;br /&gt;
Create the project just like the shrew project, using an Empty Project in the Makefile Project tab.  Set the location to be the subdirectory of the top-level shrew, e.g.&lt;br /&gt;
&lt;br /&gt;
src/modules/ncml_module&lt;br /&gt;
&lt;br /&gt;
This will create a separate project tab for the module.  If you click on this project and press the Build button (with the hammer icon), just that project will be built.&lt;br /&gt;
&lt;br /&gt;
==Debugging a Module==&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5611</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5611"/>
		<updated>2010-04-22T20:10:52Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* New Project for a Module */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
You need to have a shrew project checked out and built in debug mode using the standard approach.  The first-time debug build is &#039;&#039;required&#039;&#039; after a fresh checkout in order to get autoconf and configure to run properly and set up the Makefile for all the projects.  Eclipse will then piggyback on these.   &lt;br /&gt;
&lt;br /&gt;
If you do not have this done already, please follow the steps in the next section &amp;quot;Setting Up a Debug Shrew Project&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===Setting Up a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.  For example, to get the fully trunk shrew:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn co http://scm.opendap.org/svn/trunk/shrew&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that shrew uses svn externals, so make sure you know which versions you are getting so when you commit you are commiting to the right place!&lt;br /&gt;
&lt;br /&gt;
To check the externals being used, get the property in the shrew directory you checked out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn propget svn:externals&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which for the trunk shrew returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aries@chinchilla$ svn propget svn:externals&lt;br /&gt;
^/trunk/libdap src/libdap&lt;br /&gt;
^/trunk/bes src/bes&lt;br /&gt;
^/trunk/dap-server src/modules/dap-server&lt;br /&gt;
^/trunk/freeform_handler src/modules/freeform_handler&lt;br /&gt;
^/trunk/fileout_netcdf src/modules/fileout_netcdf&lt;br /&gt;
^/trunk/netcdf_handler src/modules/netcdf_handler&lt;br /&gt;
^/trunk/hdf4_handler src/modules/hdf4_handler&lt;br /&gt;
^/trunk/hdf5_handler src/modules/hdf5_handler&lt;br /&gt;
^/trunk/ncml_module src/modules/ncml_module&lt;br /&gt;
^/trunk/wcs_gateway_module src/modules/wcs_gateway_module&lt;br /&gt;
^/trunk/wcs_module src/modules/wcs_module&lt;br /&gt;
^/trunk/olfs src/olfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES in Hyrax 1.6, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
as the shrew starting point as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
====Configuring a Debug Build====&lt;br /&gt;
&lt;br /&gt;
Since you likely plan to use the shrew project for debugging in Eclipse, you&#039;ll want to run the build_hyrax_debug script in order to make sure the configuration for all the subprojects is set up to perform debug builds (i.e. no optimization and full symbol tables).  That way Eclipse will be able to find breakpoints and let you view variables in a running debug.&lt;br /&gt;
&lt;br /&gt;
In a bash terminal in the top-level shrew directory, type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run autoconf on everything, then configure, then build it.  If there are any missing dependencies, make sure to get them until everything builds.  This will ensure that all the subprojects are configured properly so that the Eclipse Build command, which simply calls &#039;make&#039;, will succeed in compiling a debug version of the specified project.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
==== New Workspace====&lt;br /&gt;
First, create a new workspace if you have an existing one.  You can use:&lt;br /&gt;
&lt;br /&gt;
File &amp;gt; Switch Workspace &amp;gt; Other...&lt;br /&gt;
&lt;br /&gt;
and just create a new directory for the workspace to make the new one.&lt;br /&gt;
&lt;br /&gt;
====New Project for Shrew====&lt;br /&gt;
&lt;br /&gt;
You probably won&#039;t use this directly, but making a top-level project for shrew will let Workspace searches find functions and files in all the subprojects.  More likely, you will be using a specific subproject directly.  (More on this later).&lt;br /&gt;
&lt;br /&gt;
Create a new Project in the workspace. &lt;br /&gt;
&lt;br /&gt;
File &amp;gt; New &amp;gt; C++ Project&lt;br /&gt;
&lt;br /&gt;
In the dialog:&lt;br /&gt;
&lt;br /&gt;
* Enter a project name.  Something like &amp;quot;Shrew&amp;quot; should be OK.&lt;br /&gt;
* UNcheck &amp;quot;Use Default Location&amp;quot; since we want to point at an existing directory&lt;br /&gt;
* Enter the location of the shrew project you checked out and want to debug (you can use Browse...)&lt;br /&gt;
* Select the &amp;quot;Makefile Project&amp;quot; tab since we want to use &#039;make&#039; to build&lt;br /&gt;
* Under the &amp;quot;Makefile Project&amp;quot; select &amp;quot;Empty Project&amp;quot; so Eclipse doesn&#039;t overwrite the existing Makefile&lt;br /&gt;
* Select the &amp;quot;MaxOSX GCC Toolchain&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You will now have a shrew project.  Since Eclipse uses &#039;make all&#039; to build and shrew doesn&#039;t have this target, you can&#039;t use Build on shrew.  In general, you&#039;ll want to create a subproject for each project you plan to modify so that you can do make on each one.  Otherwise, you will want to do makes in the shell as needed.&lt;br /&gt;
&lt;br /&gt;
====New Project for BES and/or Libdap====&lt;br /&gt;
&lt;br /&gt;
If you plan to modify the BES or libdap, you can make a project for each of these as well in the same way, but by pointing the location of the project at the appropriate subdirectory (src/bes or src/libdap) of the top-level shrew checkout.&lt;br /&gt;
&lt;br /&gt;
====New Project for a Module====&lt;br /&gt;
&lt;br /&gt;
In this section, we&#039;ll set up the subproject for a particular module you&#039;ll want to develop or debug.  I will use the ncml_module as the example since this is the one I normally develop and I have added some tools to the project to make setting up debugging files easier.&lt;br /&gt;
&lt;br /&gt;
Create the project just like the shrew project, using an Empty Project in the Makefile Project tab.  Set the location to be the subdirectory of the top-level shrew, e.g.&lt;br /&gt;
&lt;br /&gt;
src/modules/ncml_module&lt;br /&gt;
&lt;br /&gt;
This will create a separate project tab for the module.  If you click on this project and press the Build button (with the hammer icon), just that project will be built.&lt;br /&gt;
&lt;br /&gt;
==Building==&lt;br /&gt;
==Debugging a Module==&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5610</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5610"/>
		<updated>2010-04-22T20:06:33Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Pointing the Workspace at Shew Using Existing Makefiles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
You need to have a shrew project checked out and built in debug mode using the standard approach.  The first-time debug build is &#039;&#039;required&#039;&#039; after a fresh checkout in order to get autoconf and configure to run properly and set up the Makefile for all the projects.  Eclipse will then piggyback on these.   &lt;br /&gt;
&lt;br /&gt;
If you do not have this done already, please follow the steps in the next section &amp;quot;Setting Up a Debug Shrew Project&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===Setting Up a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.  For example, to get the fully trunk shrew:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn co http://scm.opendap.org/svn/trunk/shrew&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that shrew uses svn externals, so make sure you know which versions you are getting so when you commit you are commiting to the right place!&lt;br /&gt;
&lt;br /&gt;
To check the externals being used, get the property in the shrew directory you checked out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn propget svn:externals&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which for the trunk shrew returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aries@chinchilla$ svn propget svn:externals&lt;br /&gt;
^/trunk/libdap src/libdap&lt;br /&gt;
^/trunk/bes src/bes&lt;br /&gt;
^/trunk/dap-server src/modules/dap-server&lt;br /&gt;
^/trunk/freeform_handler src/modules/freeform_handler&lt;br /&gt;
^/trunk/fileout_netcdf src/modules/fileout_netcdf&lt;br /&gt;
^/trunk/netcdf_handler src/modules/netcdf_handler&lt;br /&gt;
^/trunk/hdf4_handler src/modules/hdf4_handler&lt;br /&gt;
^/trunk/hdf5_handler src/modules/hdf5_handler&lt;br /&gt;
^/trunk/ncml_module src/modules/ncml_module&lt;br /&gt;
^/trunk/wcs_gateway_module src/modules/wcs_gateway_module&lt;br /&gt;
^/trunk/wcs_module src/modules/wcs_module&lt;br /&gt;
^/trunk/olfs src/olfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES in Hyrax 1.6, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
as the shrew starting point as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
====Configuring a Debug Build====&lt;br /&gt;
&lt;br /&gt;
Since you likely plan to use the shrew project for debugging in Eclipse, you&#039;ll want to run the build_hyrax_debug script in order to make sure the configuration for all the subprojects is set up to perform debug builds (i.e. no optimization and full symbol tables).  That way Eclipse will be able to find breakpoints and let you view variables in a running debug.&lt;br /&gt;
&lt;br /&gt;
In a bash terminal in the top-level shrew directory, type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run autoconf on everything, then configure, then build it.  If there are any missing dependencies, make sure to get them until everything builds.  This will ensure that all the subprojects are configured properly so that the Eclipse Build command, which simply calls &#039;make&#039;, will succeed in compiling a debug version of the specified project.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
==== New Workspace====&lt;br /&gt;
First, create a new workspace if you have an existing one.  You can use:&lt;br /&gt;
&lt;br /&gt;
File &amp;gt; Switch Workspace &amp;gt; Other...&lt;br /&gt;
&lt;br /&gt;
and just create a new directory for the workspace to make the new one.&lt;br /&gt;
&lt;br /&gt;
====New Project for Shrew====&lt;br /&gt;
&lt;br /&gt;
You probably won&#039;t use this directly, but making a top-level project for shrew will let Workspace searches find functions and files in all the subprojects.  More likely, you will be using a specific subproject directly.  (More on this later).&lt;br /&gt;
&lt;br /&gt;
Create a new Project in the workspace. &lt;br /&gt;
&lt;br /&gt;
File &amp;gt; New &amp;gt; C++ Project&lt;br /&gt;
&lt;br /&gt;
In the dialog:&lt;br /&gt;
&lt;br /&gt;
* Enter a project name.  Something like &amp;quot;Shrew&amp;quot; should be OK.&lt;br /&gt;
* UNcheck &amp;quot;Use Default Location&amp;quot; since we want to point at an existing directory&lt;br /&gt;
* Enter the location of the shrew project you checked out and want to debug (you can use Browse...)&lt;br /&gt;
* Select the &amp;quot;Makefile Project&amp;quot; tab since we want to use &#039;make&#039; to build&lt;br /&gt;
* Under the &amp;quot;Makefile Project&amp;quot; select &amp;quot;Empty Project&amp;quot; so Eclipse doesn&#039;t overwrite the existing Makefile&lt;br /&gt;
* Select the &amp;quot;MaxOSX GCC Toolchain&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You will now have a shrew project.  Since Eclipse uses &#039;make all&#039; to build and shrew doesn&#039;t have this target, you can&#039;t use Build on shrew.  In general, you&#039;ll want to create a subproject for each project you plan to modify so that you can do make on each one.  Otherwise, you will want to do makes in the shell as needed.&lt;br /&gt;
&lt;br /&gt;
====New Project for BES and/or Libdap====&lt;br /&gt;
&lt;br /&gt;
If you plan to modify the BES or libdap, you can make a project for each of these as well in the same way, but by pointing the location of the project at the appropriate subdirectory (src/bes or src/libdap) of the top-level shrew checkout.&lt;br /&gt;
&lt;br /&gt;
====New Project for a Module====&lt;br /&gt;
&lt;br /&gt;
==Building==&lt;br /&gt;
==Debugging a Module==&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5609</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5609"/>
		<updated>2010-04-22T20:01:32Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Creating a Workspace In A Shrew Directory */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
You need to have a shrew project checked out and built in debug mode using the standard approach.  The first-time debug build is &#039;&#039;required&#039;&#039; after a fresh checkout in order to get autoconf and configure to run properly and set up the Makefile for all the projects.  Eclipse will then piggyback on these.   &lt;br /&gt;
&lt;br /&gt;
If you do not have this done already, please follow the steps in the next section &amp;quot;Setting Up a Debug Shrew Project&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===Setting Up a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.  For example, to get the fully trunk shrew:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn co http://scm.opendap.org/svn/trunk/shrew&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that shrew uses svn externals, so make sure you know which versions you are getting so when you commit you are commiting to the right place!&lt;br /&gt;
&lt;br /&gt;
To check the externals being used, get the property in the shrew directory you checked out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn propget svn:externals&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which for the trunk shrew returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aries@chinchilla$ svn propget svn:externals&lt;br /&gt;
^/trunk/libdap src/libdap&lt;br /&gt;
^/trunk/bes src/bes&lt;br /&gt;
^/trunk/dap-server src/modules/dap-server&lt;br /&gt;
^/trunk/freeform_handler src/modules/freeform_handler&lt;br /&gt;
^/trunk/fileout_netcdf src/modules/fileout_netcdf&lt;br /&gt;
^/trunk/netcdf_handler src/modules/netcdf_handler&lt;br /&gt;
^/trunk/hdf4_handler src/modules/hdf4_handler&lt;br /&gt;
^/trunk/hdf5_handler src/modules/hdf5_handler&lt;br /&gt;
^/trunk/ncml_module src/modules/ncml_module&lt;br /&gt;
^/trunk/wcs_gateway_module src/modules/wcs_gateway_module&lt;br /&gt;
^/trunk/wcs_module src/modules/wcs_module&lt;br /&gt;
^/trunk/olfs src/olfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES in Hyrax 1.6, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
as the shrew starting point as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
====Configuring a Debug Build====&lt;br /&gt;
&lt;br /&gt;
Since you likely plan to use the shrew project for debugging in Eclipse, you&#039;ll want to run the build_hyrax_debug script in order to make sure the configuration for all the subprojects is set up to perform debug builds (i.e. no optimization and full symbol tables).  That way Eclipse will be able to find breakpoints and let you view variables in a running debug.&lt;br /&gt;
&lt;br /&gt;
In a bash terminal in the top-level shrew directory, type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run autoconf on everything, then configure, then build it.  If there are any missing dependencies, make sure to get them until everything builds.  This will ensure that all the subprojects are configured properly so that the Eclipse Build command, which simply calls &#039;make&#039;, will succeed in compiling a debug version of the specified project.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
==== New Workspace====&lt;br /&gt;
First, create a new workspace if you have an existing one.  You can use:&lt;br /&gt;
&lt;br /&gt;
File &amp;gt; Switch Workspace &amp;gt; Other...&lt;br /&gt;
&lt;br /&gt;
and just create a new directory for the workspace to make the new one.&lt;br /&gt;
&lt;br /&gt;
====New Project for Shrew====&lt;br /&gt;
&lt;br /&gt;
You probably won&#039;t use this directly, but making a top-level project for shrew will let Workspace searches find functions and files in all the subprojects.  More likely, you will be using a specific subproject directly.  (More on this later).&lt;br /&gt;
&lt;br /&gt;
Create a new Project in the workspace. &lt;br /&gt;
&lt;br /&gt;
File &amp;gt; New &amp;gt; C++ Project&lt;br /&gt;
&lt;br /&gt;
In the dialog:&lt;br /&gt;
&lt;br /&gt;
* Enter a project name.  Something like &amp;quot;Shrew&amp;quot; should be OK.&lt;br /&gt;
* UNcheck &amp;quot;Use Default Location&amp;quot; since we want to point at an existing directory&lt;br /&gt;
* Enter the location of the shrew project you checked out and want to debug (you can use Browse...)&lt;br /&gt;
* Select the &amp;quot;Makefile Project&amp;quot; tab since we want to use &#039;make&#039; to build&lt;br /&gt;
* Under the &amp;quot;Makefile Project&amp;quot; select &amp;quot;Empty Project&amp;quot; so Eclipse doesn&#039;t overwrite the existing Makefile&lt;br /&gt;
* Select the &amp;quot;MaxOSX GCC Toolchain&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You will now have a shrew project.  Since Eclipse uses &#039;make all&#039; to build and shrew doesn&#039;t have this target, you can&#039;t use Build on shrew.  In general, you&#039;ll want to create a subproject for each project you plan to modify so that you can do make on each one.  Otherwise, you will want to do makes in the shell as needed.&lt;br /&gt;
&lt;br /&gt;
==Building==&lt;br /&gt;
==Debugging a Module==&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5608</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5608"/>
		<updated>2010-04-22T19:58:56Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Pointing the Workspace at Shew Using Existing Makefiles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
We assume you have a shrew project checked out and built using the standard approach.  If not, please follow the steps in the next section.&lt;br /&gt;
&lt;br /&gt;
===Getting a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.  For example, to get the fully trunk shrew:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn co http://scm.opendap.org/svn/trunk/shrew&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that shrew uses svn externals, so make sure you know which versions you are getting so when you commit you are commiting to the right place!&lt;br /&gt;
&lt;br /&gt;
To check the externals being used, get the property in the shrew directory you checked out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn propget svn:externals&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which for the trunk shrew returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aries@chinchilla$ svn propget svn:externals&lt;br /&gt;
^/trunk/libdap src/libdap&lt;br /&gt;
^/trunk/bes src/bes&lt;br /&gt;
^/trunk/dap-server src/modules/dap-server&lt;br /&gt;
^/trunk/freeform_handler src/modules/freeform_handler&lt;br /&gt;
^/trunk/fileout_netcdf src/modules/fileout_netcdf&lt;br /&gt;
^/trunk/netcdf_handler src/modules/netcdf_handler&lt;br /&gt;
^/trunk/hdf4_handler src/modules/hdf4_handler&lt;br /&gt;
^/trunk/hdf5_handler src/modules/hdf5_handler&lt;br /&gt;
^/trunk/ncml_module src/modules/ncml_module&lt;br /&gt;
^/trunk/wcs_gateway_module src/modules/wcs_gateway_module&lt;br /&gt;
^/trunk/wcs_module src/modules/wcs_module&lt;br /&gt;
^/trunk/olfs src/olfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
to start as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
====Configuring a Debug Build====&lt;br /&gt;
&lt;br /&gt;
Since you likely plan to use the shrew project for debugging in Eclipse, you&#039;ll want to run the build_hyrax_debug script in order to make sure the configuration for all the subprojects is set up to perform debug builds (i.e. no optimization and full symbol tables).  That way Eclipse will be able to find breakpoints and let you view variables in a running debug.&lt;br /&gt;
&lt;br /&gt;
In a bash terminal in the top-level shrew directory, type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run autoconf on everything, then configure, then build it.  If there are any missing dependencies, make sure to get them until everything builds.  This will ensure that all the subprojects are configured properly so that the Eclipse Build command, which simply calls &#039;make&#039;, will succeed in compiling a debug version of the specified project.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
==== New Workspace====&lt;br /&gt;
First, create a new workspace if you have an existing one.  You can use:&lt;br /&gt;
&lt;br /&gt;
File &amp;gt; Switch Workspace &amp;gt; Other...&lt;br /&gt;
&lt;br /&gt;
and just create a new directory for the workspace to make the new one.&lt;br /&gt;
&lt;br /&gt;
====New Project for Shrew====&lt;br /&gt;
&lt;br /&gt;
You probably won&#039;t use this directly, but making a top-level project for shrew will let Workspace searches find functions and files in all the subprojects.  More likely, you will be using a specific subproject directly.  (More on this later).&lt;br /&gt;
&lt;br /&gt;
Create a new Project in the workspace. &lt;br /&gt;
&lt;br /&gt;
File &amp;gt; New &amp;gt; C++ Project&lt;br /&gt;
&lt;br /&gt;
In the dialog:&lt;br /&gt;
&lt;br /&gt;
* Enter a project name.  Something like &amp;quot;Shrew&amp;quot; should be OK.&lt;br /&gt;
* UNcheck &amp;quot;Use Default Location&amp;quot; since we want to point at an existing directory&lt;br /&gt;
* Enter the location of the shrew project you checked out and want to debug (you can use Browse...)&lt;br /&gt;
* Select the &amp;quot;Makefile Project&amp;quot; tab since we want to use &#039;make&#039; to build&lt;br /&gt;
* Under the &amp;quot;Makefile Project&amp;quot; select &amp;quot;Empty Project&amp;quot; so Eclipse doesn&#039;t overwrite the existing Makefile&lt;br /&gt;
* Select the &amp;quot;MaxOSX GCC Toolchain&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You will now have a shrew project.  Since Eclipse uses &#039;make all&#039; to build and shrew doesn&#039;t have this target, you can&#039;t use Build on shrew.  In general, you&#039;ll want to create a subproject for each project you plan to modify so that you can do make on each one.  Otherwise, you will want to do makes in the shell as needed.&lt;br /&gt;
&lt;br /&gt;
==Building==&lt;br /&gt;
==Debugging a Module==&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5607</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5607"/>
		<updated>2010-04-22T19:17:09Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Pointing the Workspace at Shew Using Existing Makefiles */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
We assume you have a shrew project checked out and built using the standard approach.  If not, please follow the steps in the next section.&lt;br /&gt;
&lt;br /&gt;
===Getting a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.  For example, to get the fully trunk shrew:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn co http://scm.opendap.org/svn/trunk/shrew&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that shrew uses svn externals, so make sure you know which versions you are getting so when you commit you are commiting to the right place!&lt;br /&gt;
&lt;br /&gt;
To check the externals being used, get the property in the shrew directory you checked out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn propget svn:externals&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which for the trunk shrew returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aries@chinchilla$ svn propget svn:externals&lt;br /&gt;
^/trunk/libdap src/libdap&lt;br /&gt;
^/trunk/bes src/bes&lt;br /&gt;
^/trunk/dap-server src/modules/dap-server&lt;br /&gt;
^/trunk/freeform_handler src/modules/freeform_handler&lt;br /&gt;
^/trunk/fileout_netcdf src/modules/fileout_netcdf&lt;br /&gt;
^/trunk/netcdf_handler src/modules/netcdf_handler&lt;br /&gt;
^/trunk/hdf4_handler src/modules/hdf4_handler&lt;br /&gt;
^/trunk/hdf5_handler src/modules/hdf5_handler&lt;br /&gt;
^/trunk/ncml_module src/modules/ncml_module&lt;br /&gt;
^/trunk/wcs_gateway_module src/modules/wcs_gateway_module&lt;br /&gt;
^/trunk/wcs_module src/modules/wcs_module&lt;br /&gt;
^/trunk/olfs src/olfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
to start as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
====Configuring a Debug Build====&lt;br /&gt;
&lt;br /&gt;
Since you likely plan to use the shrew project for debugging in Eclipse, you&#039;ll want to run the build_hyrax_debug script in order to make sure the configuration for all the subprojects is set up to perform debug builds (i.e. no optimization and full symbol tables).  That way Eclipse will be able to find breakpoints and let you view variables in a running debug.&lt;br /&gt;
&lt;br /&gt;
In a bash terminal in the top-level shrew directory, type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run autoconf on everything, then configure, then build it.  If there are any missing dependencies, make sure to get them until everything builds.  This will ensure that all the subprojects are configured properly so that the Eclipse Build command, which simply calls &#039;make&#039;, will succeed in compiling a debug version of the specified project.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
First, create a new workspace if you have an existing one.  You can use:&lt;br /&gt;
&lt;br /&gt;
File &amp;gt; Switch Workspace &amp;gt; Other...&lt;br /&gt;
&lt;br /&gt;
and just create a new directory for the workspace to make the new one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Next, create a new Project in the workspace.  You will want to create a new Makefile Empty Project to avoid breaking the existing Makefile&#039;s!&lt;br /&gt;
&lt;br /&gt;
==Building==&lt;br /&gt;
==Debugging a Module==&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5606</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5606"/>
		<updated>2010-04-22T19:05:55Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Creating a Workspace In A Shrew Directory */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
We assume you have a shrew project checked out and built using the standard approach.  If not, please follow the steps in the next section.&lt;br /&gt;
&lt;br /&gt;
===Getting a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.  For example, to get the fully trunk shrew:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn co http://scm.opendap.org/svn/trunk/shrew&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that shrew uses svn externals, so make sure you know which versions you are getting so when you commit you are commiting to the right place!&lt;br /&gt;
&lt;br /&gt;
To check the externals being used, get the property in the shrew directory you checked out:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;svn propget svn:externals&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which for the trunk shrew returns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
aries@chinchilla$ svn propget svn:externals&lt;br /&gt;
^/trunk/libdap src/libdap&lt;br /&gt;
^/trunk/bes src/bes&lt;br /&gt;
^/trunk/dap-server src/modules/dap-server&lt;br /&gt;
^/trunk/freeform_handler src/modules/freeform_handler&lt;br /&gt;
^/trunk/fileout_netcdf src/modules/fileout_netcdf&lt;br /&gt;
^/trunk/netcdf_handler src/modules/netcdf_handler&lt;br /&gt;
^/trunk/hdf4_handler src/modules/hdf4_handler&lt;br /&gt;
^/trunk/hdf5_handler src/modules/hdf5_handler&lt;br /&gt;
^/trunk/ncml_module src/modules/ncml_module&lt;br /&gt;
^/trunk/wcs_gateway_module src/modules/wcs_gateway_module&lt;br /&gt;
^/trunk/wcs_module src/modules/wcs_module&lt;br /&gt;
^/trunk/olfs src/olfs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
to start as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
====Configuring a Debug Build====&lt;br /&gt;
&lt;br /&gt;
Since you likely plan to use the shrew project for debugging in Eclipse, you&#039;ll want to run the build_hyrax_debug script in order to make sure the configuration for all the subprojects is set up to perform debug builds (i.e. no optimization and full symbol tables).  That way Eclipse will be able to find breakpoints and let you view variables in a running debug.&lt;br /&gt;
&lt;br /&gt;
In a bash terminal in the top-level shrew directory, type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;source build_hyrax_debug&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run autoconf on everything, then configure, then build it.  If there are any missing dependencies, make sure to get them until everything builds.  This will ensure that all the subprojects are configured properly so that the Eclipse Build command, which simply calls &#039;make&#039;, will succeed in compiling a debug version of the specified project.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
==Building==&lt;br /&gt;
==Debugging a Module==&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5605</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5605"/>
		<updated>2010-04-22T18:23:04Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Creating a Workspace In A Shrew Directory */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
&lt;br /&gt;
We assume you have a shrew project checked out and built using the standard approach.  If not, please follow the steps in the next section.&lt;br /&gt;
&lt;br /&gt;
===Getting a Debug Shrew Project===&lt;br /&gt;
&lt;br /&gt;
Go to the directory you want the shrew project and do a checkout.&lt;br /&gt;
&lt;br /&gt;
==== Module Development/Debugging ====&lt;br /&gt;
&lt;br /&gt;
If you plan to debug or develop modules for the BES, we suggest you use:&lt;br /&gt;
&lt;br /&gt;
http://scm.opendap.org/svn/branch/shrew/module_dev_1.6&lt;br /&gt;
&lt;br /&gt;
to start as this will be set to use the trunk versions of the modules but to use the fixed, release versions of libdap and the BES for Hyrax 1.6.  This ensures that development doesn&#039;t use any new APIs from the libdap or bes trunk versions so that modules may be released incrementally and dynamically work with an existing Hyrax 1.6 installation with no other changes necessary.&lt;br /&gt;
&lt;br /&gt;
===Pointing the Workspace at Shew Using Existing Makefiles===&lt;br /&gt;
&lt;br /&gt;
==Building==&lt;br /&gt;
==Debugging a Module==&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5604</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5604"/>
		<updated>2010-04-22T18:18:05Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Downloading Eclipse */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
&lt;br /&gt;
Eclipse may be found at http://eclipse.org/downloads/&lt;br /&gt;
&lt;br /&gt;
Download the Eclipse for C/C++ Development (with Mylyn Integration).  &lt;br /&gt;
&lt;br /&gt;
If you also plan to do Java development, you can add these bundles in later using the Software Update.&lt;br /&gt;
&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
==Building==&lt;br /&gt;
==Debugging a Module==&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5603</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5603"/>
		<updated>2010-04-22T18:01:34Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Eclipse as an IDE for Shew */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;br /&gt;
==Creating a Workspace In A Shrew Directory==&lt;br /&gt;
==Building==&lt;br /&gt;
==Debugging a Module==&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5602</id>
		<title>Eclipse - How to Setup Eclipse in a Shrew Checkout</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Eclipse_-_How_to_Setup_Eclipse_in_a_Shrew_Checkout&amp;diff=5602"/>
		<updated>2010-04-22T18:00:36Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: New page: =Eclipse as an IDE for Shew=  It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code index...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eclipse as an IDE for Shew=&lt;br /&gt;
&lt;br /&gt;
It can be useful to use an IDE when debugging and developing for Hyrax due to the graphical interface to gdb as well as the extensive searching and code indexing features that Eclipse provides.  This document will go through the steps for getting Eclipse set up pointing into a Shrew checkout.  We also explain how we set up debug configurations for debugging modules using the besstandalone program.&lt;br /&gt;
&lt;br /&gt;
==Downloading Eclipse==&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Hyrax_Development&amp;diff=5601</id>
		<title>Hyrax Development</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Hyrax_Development&amp;diff=5601"/>
		<updated>2010-04-22T17:57:30Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Background Information */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;We are in the process of moving pages from our Trac Wiki on Hyrax to the is wiki. More Soon.&#039;&#039; Until then, here&#039;s where a good bit of the Hyrax design docs are living: [http://scm.opendap.org:8090/trac/wiki/Hyrax Hyrax Design Documentation]&lt;br /&gt;
&lt;br /&gt;
== Background Information ==&lt;br /&gt;
&lt;br /&gt;
* [[BES - How to Debug the BES]]&lt;br /&gt;
* [[Eclipse - How to Setup Eclipse in a Shrew Checkout]]&lt;br /&gt;
&lt;br /&gt;
== Features &amp;amp; Projects ==&lt;br /&gt;
&lt;br /&gt;
These are projects currently in their initial stages.&lt;br /&gt;
&lt;br /&gt;
* [[AIS Using NcML]]&lt;br /&gt;
* [[BES Aggregation using NcML]]&lt;br /&gt;
* [[Fixing the (currently) broken Hyrax catalogs]]&lt;br /&gt;
* [[How to build the DataDDX response in/with Hyrax]]&lt;br /&gt;
* [[Configurable BES cmdln client]]&lt;br /&gt;
* [[Configurable Communication Protocol]] - AMQP instead of PPT for example&lt;br /&gt;
&lt;br /&gt;
== Projects that are now Released ==&lt;br /&gt;
&lt;br /&gt;
These might not be all complete, but all have passed through the initial planning and implementation stages and are at a stage where we are adding new capabilities to them or are &#039;in maintenance.&#039;&lt;br /&gt;
&lt;br /&gt;
In Hyrax 1.7:&lt;br /&gt;
* [[Single Constraint per Definition]]&lt;br /&gt;
&lt;br /&gt;
In Hyrax 1.6:&lt;br /&gt;
* [[BES Configuration File]]&lt;br /&gt;
&lt;br /&gt;
In Hyrax 1.5:&lt;br /&gt;
* [[THREDDS using XSLT]]&lt;br /&gt;
* [[BES XML Commands]]&lt;br /&gt;
* [[BES File Out NetCDF]]&lt;br /&gt;
&lt;br /&gt;
== Releases ==&lt;br /&gt;
&lt;br /&gt;
* [http://scm.opendap.org:8090/trac/wiki/Hyrax_1.5_release Hyrax 1.5] New feature freeze on 1 Jan 2009; Beta release on 26 Jan 2009; Second beta release 23 Feb 2009; Final release 6 April 2009&lt;br /&gt;
&lt;br /&gt;
[[Category:Development|Hyrax Development]][[Category:Hyrax Development|Hyrax Development]]&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Grid_Metadata_Tutorial&amp;diff=5600</id>
		<title>Grid Metadata Tutorial</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Grid_Metadata_Tutorial&amp;diff=5600"/>
		<updated>2010-04-20T21:19:32Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* An Example of Adding Metadata to a Grid */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= An Example of Adding Metadata to a Grid =&lt;br /&gt;
[[:Category:NCML]]&lt;br /&gt;
&lt;br /&gt;
We will go through a basic example of adding metadata to all the possible scopes in a Grid variable:&lt;br /&gt;
&lt;br /&gt;
* The top-level Grid Structure itself&lt;br /&gt;
* The data Array in the Grid&lt;br /&gt;
* Each Map vector in the Grid&lt;br /&gt;
&lt;br /&gt;
We will also modify the global dataset attribute container to elucidate the difference between an attribute Structure and a variable Structure.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start with a &amp;quot;pass-through&amp;quot; NcML file which wraps a Netcdf dataset that Hyrax represents as a Grid.  This will let us see the exact structure of the data we will want to modify (which may be slightly different than the wrapped dataset due to legacy issues with how shared dimensions are represented, etc):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- This space intentionally left blank! --&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This gives the DDS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        UInt32 dsp_band_1[lat = 1024][lon = 1024];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 lat[1024];&lt;br /&gt;
        Float64 lon[1024];&lt;br /&gt;
    } dsp_band_1;&lt;br /&gt;
} grid_attributes_2.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and the (extensive) DAS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    HDF_GLOBAL {&lt;br /&gt;
        UInt16 dsp_SubImageId 0;&lt;br /&gt;
        String dsp_SubImageName &amp;quot;N/A&amp;quot;;&lt;br /&gt;
        Int32 dsp_ModificationDate 20040416;&lt;br /&gt;
        Int32 dsp_ModificationTime 160521;&lt;br /&gt;
        Int32 dsp_SubImageFlag 64;&lt;br /&gt;
        String dsp_SubImageTitle &amp;quot;Ingested by SCRIPP&amp;quot;;&lt;br /&gt;
        Int32 dsp_StartDate 19970701;&lt;br /&gt;
        Float32 dsp_StartTime 70958.5;&lt;br /&gt;
        Int32 dsp_SizeX 1024;&lt;br /&gt;
        Int32 dsp_SizeY 1024;&lt;br /&gt;
        Int32 dsp_OffsetX 0;&lt;br /&gt;
        Int32 dsp_RecordLength 2048;&lt;br /&gt;
        Byte dsp_DataOrganization 64;&lt;br /&gt;
        Byte dsp_NumberOfBands 1;&lt;br /&gt;
        String dsp_ing_tiros_ourid &amp;quot;NO14****C\\217\\345P?\\253\\205\\037&amp;quot;;&lt;br /&gt;
        UInt16 dsp_ing_tiros_numscn 44305;&lt;br /&gt;
        UInt16 dsp_ing_tiros_idsat 2560;&lt;br /&gt;
        UInt16 dsp_ing_tiros_iddata 768;&lt;br /&gt;
        UInt16 dsp_ing_tiros_year 24832;&lt;br /&gt;
        UInt16 dsp_ing_tiros_daysmp 46592;&lt;br /&gt;
        Int32 dsp_ing_tiros_milsec 1235716353;&lt;br /&gt;
        Int32 dsp_ing_tiros_slope 1075636998, 551287046, -426777345, -1339034123, 5871604;&lt;br /&gt;
        Int32 dsp_ing_tiros_intcpt 514263295, 1892553983, -371365632, 9497638, -2140793044;&lt;br /&gt;
        UInt16 dsp_ing_tiros_tabadr 256, 512, 768;&lt;br /&gt;
        UInt16 dsp_ing_tiros_cnlins 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_cncols 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_czncs 8;&lt;br /&gt;
        UInt16 dsp_ing_tiros_line 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_icol 0;&lt;br /&gt;
        String dsp_ing_tiros_date0 &amp;quot;23-MAY-10 13:54:29\\030&amp;quot;;&lt;br /&gt;
        String dsp_ing_tiros_time0 &amp;quot;13:54:29\\030&amp;quot;;&lt;br /&gt;
        UInt16 dsp_ing_tiros_label 14112, 12576, 14137;&lt;br /&gt;
        UInt16 dsp_ing_tiros_nxtblk 1280;&lt;br /&gt;
        UInt16 dsp_ing_tiros_datblk 1280;&lt;br /&gt;
        UInt16 dsp_ing_tiros_itape 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_cbias 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ccoeff 0;&lt;br /&gt;
        Int32 dsp_ing_tiros_pastim 1235716353;&lt;br /&gt;
        UInt16 dsp_ing_tiros_passcn 3840;&lt;br /&gt;
        UInt16 dsp_ing_tiros_lostct 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_lost 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ndrll 1280;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ndrrec 3840, 5376, 6912, 8448, 9984, 0, 0, 0, 0, 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ndrlat 46110, 44318, 42526, 40478, 38686, 0, 0, 0, 0, 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ndrlon 49891, 48611, 47075, 45539, 44259, 0, 0, 0, 0, 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_chncnt 1280;&lt;br /&gt;
        UInt16 dsp_ing_tiros_chndsq 8, 8, 8, 8, 8;&lt;br /&gt;
        UInt16 dsp_ing_tiros_czncs2 4;&lt;br /&gt;
        UInt16 dsp_ing_tiros_wrdsiz 512;&lt;br /&gt;
        UInt16 dsp_ing_tiros_nchbas 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_nchlst 1280;&lt;br /&gt;
        Float32 dsp_ing_tiros_rpmclc 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_numpix 8;&lt;br /&gt;
        UInt16 dsp_ing_tiros_scnden 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_eltden 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_orbtno 23858;&lt;br /&gt;
        Int32 dsp_ing_tiros_slope2 1075636998, 551287046, -426777345, -1339034123, 5871604;&lt;br /&gt;
        Int32 dsp_ing_tiros_intcp2 514263295, 1892553983, -371365632, 9497638, -2140793044;&lt;br /&gt;
        Float32 dsp_ing_tiros_prtemp 3.0811e+10;&lt;br /&gt;
        Float32 dsp_ing_tiros_timerr 5.6611e-20;&lt;br /&gt;
        UInt16 dsp_ing_tiros_timstn 8279;&lt;br /&gt;
        String dsp_nav_xsatid &amp;quot;NO14\\005\\002&amp;quot;;&lt;br /&gt;
        Byte dsp_nav_xsatty 5;&lt;br /&gt;
        Byte dsp_nav_xproty 2;&lt;br /&gt;
        Byte dsp_nav_xmapsl 0;&lt;br /&gt;
        Byte dsp_nav_xtmpch 4;&lt;br /&gt;
        Float32 dsp_nav_ximgdy 97182;&lt;br /&gt;
        Float32 dsp_nav_ximgtm 70954.4;&lt;br /&gt;
        Float32 dsp_nav_xorbit 12893;&lt;br /&gt;
        Float32 dsp_nav_ximgcv 71.1722, 0, 4.88181, 0, -112.11, 0, -27.9583, 0;&lt;br /&gt;
        Float32 dsp_nav_earth_linoff 0;&lt;br /&gt;
        Float32 dsp_nav_earth_pixoff 0;&lt;br /&gt;
        Float32 dsp_nav_earth_scnstr 1;&lt;br /&gt;
        Float32 dsp_nav_earth_scnstp 1024;&lt;br /&gt;
        Float32 dsp_nav_earth_pixstr 1;&lt;br /&gt;
        Float32 dsp_nav_earth_pixstp 1024;&lt;br /&gt;
        Float32 dsp_nav_earth_latorg 0;&lt;br /&gt;
        Float32 dsp_nav_earth_lonorg 0;&lt;br /&gt;
        Float32 dsp_nav_earth_orgrot 0;&lt;br /&gt;
        Float32 dsp_nav_earth_lattop 0;&lt;br /&gt;
        Float32 dsp_nav_earth_latbot 0;&lt;br /&gt;
        Float32 dsp_nav_earth_latcen 38;&lt;br /&gt;
        Float32 dsp_nav_earth_loncen -70;&lt;br /&gt;
        Float32 dsp_nav_earth_height 66.3444;&lt;br /&gt;
        Float32 dsp_nav_earth_width 84.2205;&lt;br /&gt;
        Float32 dsp_nav_earth_level 1;&lt;br /&gt;
        Float32 dsp_nav_earth_xspace 5.99902;&lt;br /&gt;
        Float32 dsp_nav_earth_yspace 5.99902;&lt;br /&gt;
        String dsp_nav_earth_rev &amp;quot; 0.1&amp;quot;;&lt;br /&gt;
        Float32 dsp_nav_earth_dflag 0;&lt;br /&gt;
        Float32 dsp_nav_earth_toplat 71.1722;&lt;br /&gt;
        Float32 dsp_nav_earth_botlat 4.88181;&lt;br /&gt;
        Float32 dsp_nav_earth_leflon -112.11;&lt;br /&gt;
        Float32 dsp_nav_earth_ritlon -27.9583;&lt;br /&gt;
        Float32 dsp_nav_earth_numpix 1024;&lt;br /&gt;
        Float32 dsp_nav_earth_numras 1024;&lt;br /&gt;
        Float32 dsp_nav_earth_magxx 6;&lt;br /&gt;
        Float32 dsp_nav_earth_magyy 6;&lt;br /&gt;
        Int32 dsp_hgt_llnval 18;&lt;br /&gt;
        Int32 dsp_hgt_lltime 25744350;&lt;br /&gt;
        Float32 dsp_hgt_llvect 869.428, 1.14767, 868.659, 1.09635, 867.84, 1.04502, 866.979, 0.9937, 866.084, 0.942374, 865.165, 0.891045, 864.231, 0.839715, 863.292, 0.788383, 862.356, 0.737049, 861.434, 0.685714, 860.536, 0.634378, 859.67, 0.58304, 858.847, 0.531702, 858.075, 0.480362, 857.363, 0.429022, 856.718, 0.377682, 856.148, 0.326341, 855.66, 0.275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;&lt;br /&gt;
        String history &amp;quot;\\001PATHNLC May 23 22:40:54 2000 PATHNLC t,3,269.16,0.125,0.,0.01,271.16,308.16,,,,1,,,2,,,3,,,,,,4,,,,,,,2.,,35.,0.1,5,,,,,,,2.,,35.,0.15,55.,80.,0.005,20,,,-2,6.,t,,,,,,,,,,16,,3.5 allb=0 nlsst=1 in=/pathfdr5//97182070958.N14@INGEST@ in1=/pathfdr10/mask/oi.9727.mean out=/pathfdr4/nlc/f97182070958.FMG@0\\012\\004PATHNLC  NLSST Temp calculation date: April 10, 1996\\012\\001OISST Jan 12 17:53:43 1998 OISST  /usr3/gacsst/maketc/oi/dinp/oi.comp.bias.1997,/usr3/gacsst/maketc/oi/dout/oi.97,-3.,0.15,oi.dates.97,0\\012\\004OISST 26 97 06 22 97 06 28  7        472\\012\\001STATS Jan 12 18:27:34 1998 STATS minpix=1 maxpix=255 in=/usr3/gacsst/maketc/oi/dout//oi.9726 \\011  audit=t, callim=f, cal=f, cloud=f \\011  outm=/usr3/gacsst/etc/oi/oi.9727.mean\\012\\001OISST Jan 12 17:53:43 1998 OISST  /usr3/gacsst/maketc/oi/dinp/oi.comp.bias.1997,/usr3/gacsst/maketc/oi/dout/oi.97,-3.,0.15,oi.dates.97,0\\012\\004OISST 27 97 06 29 97 07 05  7        472\\012\\002STATS /usr3/gacsst/maketc/oi/dout//oi.9727\\012\\001OISST Jan 12 17:53:43 1998 OISST  /usr3/gacsst/maketc/oi/dinp/oi.comp.bias.1997,/usr3/gacsst/maketc/oi/dout/oi.97,-3.,0.15,oi.dates.97,0\\012\\004OISST 27 97 06 29 97 07 05  7        472\\012\\002STATS /usr3/gacsst/maketc/oi/dout//oi.9727\\012\\001OISST Jan 12 17:53:43 1998 OISST  /usr3/gacsst/maketc/oi/dinp/oi.comp.bias.1997,/usr3/gacsst/maketc/oi/dout/oi.97,-3.,0.15,oi.dates.97,0\\012\\004OISST 28 97 07 06 97 07 12  7        472\\012\\002STATS /usr3/gacsst/maketc/oi/dout//oi.9728\\012\\002PATHNLC /pathfdr10/mask/oi.9727.mean\\012\\004PATHNLC  45d coeffs used (1) =    0.759   0.947   0.110   1.460   0.000\\012\\004PATHNLC  45d coeffs used (2) =    1.320   0.952   0.071   0.882   0.000\\012\\004PATHNLC  45d coeffs used (3) =    0.000   0.000   0.000   0.000   0.000\\012\\004PATHNLC  GETOZONE I     0.0900    0.0000\\012\\001REMAP Jun  4 07:59:42 2000 REMAP in=/coral/miami/remaps/sst_8r/file_uZ.FMG out=/coral/miami/remaps/sst_8r/f97182070958.nwa16\\012\\004REMAP Output image pixel, line size =    6144,    6144\\012\\004REMAP Grid spacing (X,Y) = (        6.00,        6.00), Projection Code=     1\\012\\004REMAP center lon,lat,dlon,dlat =       -70.00       38.00        0.01        0.01\\012\\001merge_sb Apr 16 16:05:09 2004 merge_sb in=(file=/NOPP/carlw/atlantic/remaps/nwa16/f97182070958.nwa16, filecheck=/RAID2/sbaker/atlantic/bslines97/f97182070958.nwa16) val=0 valcheck=0 tag=0 out=(file1=/RAID2/sbaker/nwa1024d/NDC/dsp_data/f97182070958.tmp_m2)\\012\\001merge_sb Apr 16 16:05:18 2004 merge_sb in=(file=/RAID2/sbaker/nwa1024d/NDC/dsp_data/f97182070958.tmp_m2, filecheck=/RAID/sbaker/DECLOUD/landmask16.img) val=1 valcheck=2 tag=0 out=(file1=/RAID2/sbaker/nwa6144d/NDC/dsp_data/f97182070958.nwa16)\\012\\001CONVRT Apr 16 16:05:21 2004 CONVRT 1024,1024,0,0,6,6,0,0,f,f,t,16,,SUB,1 in=/RAID2/sbaker/nwa6144d/NDC/dsp_data/f97182070958.nwa16   out=/RAID2/sbaker/nwa1024d/NDC/dsp_data/f97182070958.nwa16\\012\\012@\\000\\000\\000&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to add the following attributes:&lt;br /&gt;
&lt;br /&gt;
# Add an attribute to the HDF_GLOBAL attribute container called &amp;quot;ncml_location&amp;quot; since the file is wrapped by our NcML and the original location being wrapped might not be obvious.  &lt;br /&gt;
# Add the same attribute to the &#039;&#039;&#039;dsp_band_1&#039;&#039;&#039; Grid itself so it&#039;s easier to see and in case of projections &lt;br /&gt;
# Add &amp;quot;units&amp;quot; to the Array member variable &#039;&#039;&#039;dsp_band_1&#039;&#039;&#039; of the Grid that matches the containing Grid&#039;s &amp;quot;units&amp;quot; attribute with value &amp;quot;Temp&amp;quot;&lt;br /&gt;
# Add &amp;quot;units&amp;quot; to the &#039;&#039;&#039;lat&#039;&#039;&#039; map vector as a String with value &amp;quot;degrees_north&amp;quot;&lt;br /&gt;
# Add &amp;quot;units&amp;quot; to the &#039;&#039;&#039;lon&#039;&#039;&#039; map vector as a String with value &amp;quot;degrees_east&amp;quot;&lt;br /&gt;
&lt;br /&gt;
First, let&#039;s add the &amp;quot;ncml_location&amp;quot; into the HDF_GLOBAL attribute container.  To do this, we need to specify the &amp;quot;scope&amp;quot; of the HDF_GLOBAL attribute container (called a Structure in NcML):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Traverse into the HDF_GLOBAL attribute Structure (container) --&amp;gt;&lt;br /&gt;
  &amp;lt;attribute name=&amp;quot;HDF_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
1)  &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/attribute&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
This results in the following (clipped for clarity) DAS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    HDF_GLOBAL {&lt;br /&gt;
        UInt16 dsp_SubImageId 0;&lt;br /&gt;
        ... *** CLIPPED FOR CLARITY ***  ...&lt;br /&gt;
1)    String ncml_location &amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can see at the 1) where the new attribute has been added to HDF_GLOBAL as desired.&lt;br /&gt;
&lt;br /&gt;
Next, we want to add the same attribute to the top-level &#039;&#039;&#039;dsp_band_1&#039;&#039;&#039; Grid variable.  Here&#039;s the NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Traverse into the HDF_GLOBAL attribute Structure (container) --&amp;gt;&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;HDF_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!-- Traverse into the dsp_band_1 variable Structure (actually a Grid) --&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;dsp_band_1&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
2) &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which gives the (clipped again) DAS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    HDF_GLOBAL {&lt;br /&gt;
       ... *** CLIPPED FOR CLARITY *** ...&lt;br /&gt;
        String ncml_location &amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
2)    String ncml_location &amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;;&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have denoted the injected metadata with a 2).  &lt;br /&gt;
&lt;br /&gt;
As a learning exercise, let&#039;s say we made a mistake and tried to use &amp;lt;attribute&amp;gt; to specify the &#039;&#039;&#039;dsp_band_1&#039;&#039;&#039; attribute table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Traverse into the HDF_GLOBAL attribute Structure (container) --&amp;gt;&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;HDF_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!-- THIS IS AN ERROR! --&amp;gt;&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;dsp_band_1&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/attribute&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then we get a Parse Error:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;ISO-8859-1&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;response xmlns=&amp;quot;http://xml.opendap.org/ns/bes/1.0#&amp;quot; reqID=&amp;quot;some_unique_value&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;getDAS&amp;gt;&lt;br /&gt;
      &amp;lt;BESError&amp;gt;&amp;lt;Type&amp;gt;3&amp;lt;/Type&amp;gt;&lt;br /&gt;
           &amp;lt;Message&amp;gt;NCMLModule ParseError: at line 11: Cannot create a new attribute container with name=dsp_band_1 at current scope since a variable with that name already exists.  Scope=&amp;lt;/Message&amp;gt;&lt;br /&gt;
           &amp;lt;Administrator&amp;gt;admin.email.address@your.domain.name&amp;lt;/Administrator&amp;gt;&amp;lt;Location&amp;gt;&amp;lt;File&amp;gt;AttributeElement.cc&amp;lt;/File&amp;gt;&amp;lt;Line&amp;gt;277&amp;lt;/Line&amp;gt;&amp;lt;/Location&amp;gt;&lt;br /&gt;
      &amp;lt;/BESError&amp;gt;&lt;br /&gt;
   &amp;lt;/getDAS&amp;gt;&lt;br /&gt;
&amp;lt;/response&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which basically tells us the problem: we tried to specify an attribute with the same name as the Grid, but &#039;&#039;&#039;dsp_band_1&#039;&#039;&#039; is a variable already with that name.  It is illegal for an attribute and variable at the same scope to have the same name.&lt;br /&gt;
&lt;br /&gt;
Next, we want to add the &amp;quot;units&amp;quot; attribute that is on the Grid itself to the actual data Array inside the Grid (say we know we will be projecting it out with a constraint and don&#039;t want to lose this metadata).  The NcML now becomes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Traverse into the HDF_GLOBAL attribute Structure (container) --&amp;gt;&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;HDF_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!-- Traverse into the dsp_band_1 variable Structure (actually a Grid) --&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;dsp_band_1&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in the Grid&#039;s attribute table --&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;!-- While remaining in the Grid, traverse into the Array dsp_band_1: --&amp;gt;&lt;br /&gt;
   &amp;lt;variable name=&amp;quot;dsp_band_1&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;!-- And add the attribute there.  Fully qualified name of this scope is &amp;quot;dsp_band_1.dsp_band_1&amp;quot; --&amp;gt;&lt;br /&gt;
3)   &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;Temp&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/variable&amp;gt; &amp;lt;!-- Exit the Array variable scope, back to the Grid level --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our modified DAS is now:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    HDF_GLOBAL {&lt;br /&gt;
       ... *** CLIPPED FOR CLARITY *** ...&lt;br /&gt;
        String ncml_location &amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
        String ncml_location &amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;;&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
3)        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the 3) denotes the newly injected metadata on &#039;&#039;&#039;dsp_band_1.dsp_band_1&#039;&#039;&#039;.  &lt;br /&gt;
&lt;br /&gt;
Next, we will add the units to both of the map vectors in the next version of our NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Traverse into the HDF_GLOBAL attribute Structure (container) --&amp;gt;&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;HDF_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!-- Traverse into the dsp_band_1 variable Structure (actually a Grid) --&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;dsp_band_1&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in the Grid&#039;s attribute table --&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;!-- While remaining in the Grid, traverse into the Array dsp_band_1: --&amp;gt;&lt;br /&gt;
   &amp;lt;variable name=&amp;quot;dsp_band_1&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;!-- And add the attribute there.  Fully qualified name of this scope is &amp;quot;dsp_band_1.dsp_band_1&amp;quot; --&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;Temp&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/variable&amp;gt; &amp;lt;!-- Exit the Array variable scope, back to the Grid level --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;!-- Traverse into the lat map vector variable --&amp;gt;&lt;br /&gt;
   &amp;lt;variable name=&amp;quot;lat&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;!-- Add the units --&amp;gt;&lt;br /&gt;
4)   &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;degrees_north&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/variable&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
   &amp;lt;!-- Traverse into the lon map vector variable --&amp;gt;&lt;br /&gt;
   &amp;lt;variable name=&amp;quot;lon&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;!-- Add the units --&amp;gt;&lt;br /&gt;
5)   &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;degrees_east&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where we denote the changed with 4) and 5).  Here&#039;s the resulting DAS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    HDF_GLOBAL {&lt;br /&gt;
        ... *** CLIPPED FOR CLARITY *** ...&lt;br /&gt;
1)      String ncml_location &amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
2)       String ncml_location &amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;;&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
3)          String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
4)          String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
5)          String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where we have marked all the new metadata we have injected, including the new attributes on the map vectors.&lt;br /&gt;
&lt;br /&gt;
Although we added metadata to the Grid, it is possible to also use the other forms of &amp;lt;attribute&amp;gt; in order to modify existing attributes or remove unwanted or incorrect attributes. &lt;br /&gt;
&lt;br /&gt;
The only place where this syntax varies slightly is in adding metadata to an aggregated Grid.  Please see the tutorial section on aggregating grids for more information.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Grid_Metadata_Tutorial&amp;diff=5599</id>
		<title>Grid Metadata Tutorial</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Grid_Metadata_Tutorial&amp;diff=5599"/>
		<updated>2010-04-20T21:18:40Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* An Example of Adding Metadata to a Grid */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= An Example of Adding Metadata to a Grid =&lt;br /&gt;
[[:Category:NCML]]&lt;br /&gt;
&lt;br /&gt;
We will go through a basic example of adding metadata to all the possible scopes in a Grid variable:&lt;br /&gt;
&lt;br /&gt;
* The top-level Grid Structure itself&lt;br /&gt;
* The data Array in the Grid&lt;br /&gt;
* Each Map vector in the Grid&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start with a &amp;quot;pass-through&amp;quot; NcML file which wraps a Netcdf dataset that Hyrax represents as a Grid.  This will let us see the exact structure of the data we will want to modify (which may be slightly different than the wrapped dataset due to legacy issues with how shared dimensions are represented, etc):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- This space intentionally left blank! --&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This gives the DDS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        UInt32 dsp_band_1[lat = 1024][lon = 1024];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 lat[1024];&lt;br /&gt;
        Float64 lon[1024];&lt;br /&gt;
    } dsp_band_1;&lt;br /&gt;
} grid_attributes_2.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and the (extensive) DAS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    HDF_GLOBAL {&lt;br /&gt;
        UInt16 dsp_SubImageId 0;&lt;br /&gt;
        String dsp_SubImageName &amp;quot;N/A&amp;quot;;&lt;br /&gt;
        Int32 dsp_ModificationDate 20040416;&lt;br /&gt;
        Int32 dsp_ModificationTime 160521;&lt;br /&gt;
        Int32 dsp_SubImageFlag 64;&lt;br /&gt;
        String dsp_SubImageTitle &amp;quot;Ingested by SCRIPP&amp;quot;;&lt;br /&gt;
        Int32 dsp_StartDate 19970701;&lt;br /&gt;
        Float32 dsp_StartTime 70958.5;&lt;br /&gt;
        Int32 dsp_SizeX 1024;&lt;br /&gt;
        Int32 dsp_SizeY 1024;&lt;br /&gt;
        Int32 dsp_OffsetX 0;&lt;br /&gt;
        Int32 dsp_RecordLength 2048;&lt;br /&gt;
        Byte dsp_DataOrganization 64;&lt;br /&gt;
        Byte dsp_NumberOfBands 1;&lt;br /&gt;
        String dsp_ing_tiros_ourid &amp;quot;NO14****C\\217\\345P?\\253\\205\\037&amp;quot;;&lt;br /&gt;
        UInt16 dsp_ing_tiros_numscn 44305;&lt;br /&gt;
        UInt16 dsp_ing_tiros_idsat 2560;&lt;br /&gt;
        UInt16 dsp_ing_tiros_iddata 768;&lt;br /&gt;
        UInt16 dsp_ing_tiros_year 24832;&lt;br /&gt;
        UInt16 dsp_ing_tiros_daysmp 46592;&lt;br /&gt;
        Int32 dsp_ing_tiros_milsec 1235716353;&lt;br /&gt;
        Int32 dsp_ing_tiros_slope 1075636998, 551287046, -426777345, -1339034123, 5871604;&lt;br /&gt;
        Int32 dsp_ing_tiros_intcpt 514263295, 1892553983, -371365632, 9497638, -2140793044;&lt;br /&gt;
        UInt16 dsp_ing_tiros_tabadr 256, 512, 768;&lt;br /&gt;
        UInt16 dsp_ing_tiros_cnlins 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_cncols 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_czncs 8;&lt;br /&gt;
        UInt16 dsp_ing_tiros_line 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_icol 0;&lt;br /&gt;
        String dsp_ing_tiros_date0 &amp;quot;23-MAY-10 13:54:29\\030&amp;quot;;&lt;br /&gt;
        String dsp_ing_tiros_time0 &amp;quot;13:54:29\\030&amp;quot;;&lt;br /&gt;
        UInt16 dsp_ing_tiros_label 14112, 12576, 14137;&lt;br /&gt;
        UInt16 dsp_ing_tiros_nxtblk 1280;&lt;br /&gt;
        UInt16 dsp_ing_tiros_datblk 1280;&lt;br /&gt;
        UInt16 dsp_ing_tiros_itape 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_cbias 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ccoeff 0;&lt;br /&gt;
        Int32 dsp_ing_tiros_pastim 1235716353;&lt;br /&gt;
        UInt16 dsp_ing_tiros_passcn 3840;&lt;br /&gt;
        UInt16 dsp_ing_tiros_lostct 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_lost 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ndrll 1280;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ndrrec 3840, 5376, 6912, 8448, 9984, 0, 0, 0, 0, 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ndrlat 46110, 44318, 42526, 40478, 38686, 0, 0, 0, 0, 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ndrlon 49891, 48611, 47075, 45539, 44259, 0, 0, 0, 0, 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_chncnt 1280;&lt;br /&gt;
        UInt16 dsp_ing_tiros_chndsq 8, 8, 8, 8, 8;&lt;br /&gt;
        UInt16 dsp_ing_tiros_czncs2 4;&lt;br /&gt;
        UInt16 dsp_ing_tiros_wrdsiz 512;&lt;br /&gt;
        UInt16 dsp_ing_tiros_nchbas 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_nchlst 1280;&lt;br /&gt;
        Float32 dsp_ing_tiros_rpmclc 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_numpix 8;&lt;br /&gt;
        UInt16 dsp_ing_tiros_scnden 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_eltden 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_orbtno 23858;&lt;br /&gt;
        Int32 dsp_ing_tiros_slope2 1075636998, 551287046, -426777345, -1339034123, 5871604;&lt;br /&gt;
        Int32 dsp_ing_tiros_intcp2 514263295, 1892553983, -371365632, 9497638, -2140793044;&lt;br /&gt;
        Float32 dsp_ing_tiros_prtemp 3.0811e+10;&lt;br /&gt;
        Float32 dsp_ing_tiros_timerr 5.6611e-20;&lt;br /&gt;
        UInt16 dsp_ing_tiros_timstn 8279;&lt;br /&gt;
        String dsp_nav_xsatid &amp;quot;NO14\\005\\002&amp;quot;;&lt;br /&gt;
        Byte dsp_nav_xsatty 5;&lt;br /&gt;
        Byte dsp_nav_xproty 2;&lt;br /&gt;
        Byte dsp_nav_xmapsl 0;&lt;br /&gt;
        Byte dsp_nav_xtmpch 4;&lt;br /&gt;
        Float32 dsp_nav_ximgdy 97182;&lt;br /&gt;
        Float32 dsp_nav_ximgtm 70954.4;&lt;br /&gt;
        Float32 dsp_nav_xorbit 12893;&lt;br /&gt;
        Float32 dsp_nav_ximgcv 71.1722, 0, 4.88181, 0, -112.11, 0, -27.9583, 0;&lt;br /&gt;
        Float32 dsp_nav_earth_linoff 0;&lt;br /&gt;
        Float32 dsp_nav_earth_pixoff 0;&lt;br /&gt;
        Float32 dsp_nav_earth_scnstr 1;&lt;br /&gt;
        Float32 dsp_nav_earth_scnstp 1024;&lt;br /&gt;
        Float32 dsp_nav_earth_pixstr 1;&lt;br /&gt;
        Float32 dsp_nav_earth_pixstp 1024;&lt;br /&gt;
        Float32 dsp_nav_earth_latorg 0;&lt;br /&gt;
        Float32 dsp_nav_earth_lonorg 0;&lt;br /&gt;
        Float32 dsp_nav_earth_orgrot 0;&lt;br /&gt;
        Float32 dsp_nav_earth_lattop 0;&lt;br /&gt;
        Float32 dsp_nav_earth_latbot 0;&lt;br /&gt;
        Float32 dsp_nav_earth_latcen 38;&lt;br /&gt;
        Float32 dsp_nav_earth_loncen -70;&lt;br /&gt;
        Float32 dsp_nav_earth_height 66.3444;&lt;br /&gt;
        Float32 dsp_nav_earth_width 84.2205;&lt;br /&gt;
        Float32 dsp_nav_earth_level 1;&lt;br /&gt;
        Float32 dsp_nav_earth_xspace 5.99902;&lt;br /&gt;
        Float32 dsp_nav_earth_yspace 5.99902;&lt;br /&gt;
        String dsp_nav_earth_rev &amp;quot; 0.1&amp;quot;;&lt;br /&gt;
        Float32 dsp_nav_earth_dflag 0;&lt;br /&gt;
        Float32 dsp_nav_earth_toplat 71.1722;&lt;br /&gt;
        Float32 dsp_nav_earth_botlat 4.88181;&lt;br /&gt;
        Float32 dsp_nav_earth_leflon -112.11;&lt;br /&gt;
        Float32 dsp_nav_earth_ritlon -27.9583;&lt;br /&gt;
        Float32 dsp_nav_earth_numpix 1024;&lt;br /&gt;
        Float32 dsp_nav_earth_numras 1024;&lt;br /&gt;
        Float32 dsp_nav_earth_magxx 6;&lt;br /&gt;
        Float32 dsp_nav_earth_magyy 6;&lt;br /&gt;
        Int32 dsp_hgt_llnval 18;&lt;br /&gt;
        Int32 dsp_hgt_lltime 25744350;&lt;br /&gt;
        Float32 dsp_hgt_llvect 869.428, 1.14767, 868.659, 1.09635, 867.84, 1.04502, 866.979, 0.9937, 866.084, 0.942374, 865.165, 0.891045, 864.231, 0.839715, 863.292, 0.788383, 862.356, 0.737049, 861.434, 0.685714, 860.536, 0.634378, 859.67, 0.58304, 858.847, 0.531702, 858.075, 0.480362, 857.363, 0.429022, 856.718, 0.377682, 856.148, 0.326341, 855.66, 0.275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;&lt;br /&gt;
        String history &amp;quot;\\001PATHNLC May 23 22:40:54 2000 PATHNLC t,3,269.16,0.125,0.,0.01,271.16,308.16,,,,1,,,2,,,3,,,,,,4,,,,,,,2.,,35.,0.1,5,,,,,,,2.,,35.,0.15,55.,80.,0.005,20,,,-2,6.,t,,,,,,,,,,16,,3.5 allb=0 nlsst=1 in=/pathfdr5//97182070958.N14@INGEST@ in1=/pathfdr10/mask/oi.9727.mean out=/pathfdr4/nlc/f97182070958.FMG@0\\012\\004PATHNLC  NLSST Temp calculation date: April 10, 1996\\012\\001OISST Jan 12 17:53:43 1998 OISST  /usr3/gacsst/maketc/oi/dinp/oi.comp.bias.1997,/usr3/gacsst/maketc/oi/dout/oi.97,-3.,0.15,oi.dates.97,0\\012\\004OISST 26 97 06 22 97 06 28  7        472\\012\\001STATS Jan 12 18:27:34 1998 STATS minpix=1 maxpix=255 in=/usr3/gacsst/maketc/oi/dout//oi.9726 \\011  audit=t, callim=f, cal=f, cloud=f \\011  outm=/usr3/gacsst/etc/oi/oi.9727.mean\\012\\001OISST Jan 12 17:53:43 1998 OISST  /usr3/gacsst/maketc/oi/dinp/oi.comp.bias.1997,/usr3/gacsst/maketc/oi/dout/oi.97,-3.,0.15,oi.dates.97,0\\012\\004OISST 27 97 06 29 97 07 05  7        472\\012\\002STATS /usr3/gacsst/maketc/oi/dout//oi.9727\\012\\001OISST Jan 12 17:53:43 1998 OISST  /usr3/gacsst/maketc/oi/dinp/oi.comp.bias.1997,/usr3/gacsst/maketc/oi/dout/oi.97,-3.,0.15,oi.dates.97,0\\012\\004OISST 27 97 06 29 97 07 05  7        472\\012\\002STATS /usr3/gacsst/maketc/oi/dout//oi.9727\\012\\001OISST Jan 12 17:53:43 1998 OISST  /usr3/gacsst/maketc/oi/dinp/oi.comp.bias.1997,/usr3/gacsst/maketc/oi/dout/oi.97,-3.,0.15,oi.dates.97,0\\012\\004OISST 28 97 07 06 97 07 12  7        472\\012\\002STATS /usr3/gacsst/maketc/oi/dout//oi.9728\\012\\002PATHNLC /pathfdr10/mask/oi.9727.mean\\012\\004PATHNLC  45d coeffs used (1) =    0.759   0.947   0.110   1.460   0.000\\012\\004PATHNLC  45d coeffs used (2) =    1.320   0.952   0.071   0.882   0.000\\012\\004PATHNLC  45d coeffs used (3) =    0.000   0.000   0.000   0.000   0.000\\012\\004PATHNLC  GETOZONE I     0.0900    0.0000\\012\\001REMAP Jun  4 07:59:42 2000 REMAP in=/coral/miami/remaps/sst_8r/file_uZ.FMG out=/coral/miami/remaps/sst_8r/f97182070958.nwa16\\012\\004REMAP Output image pixel, line size =    6144,    6144\\012\\004REMAP Grid spacing (X,Y) = (        6.00,        6.00), Projection Code=     1\\012\\004REMAP center lon,lat,dlon,dlat =       -70.00       38.00        0.01        0.01\\012\\001merge_sb Apr 16 16:05:09 2004 merge_sb in=(file=/NOPP/carlw/atlantic/remaps/nwa16/f97182070958.nwa16, filecheck=/RAID2/sbaker/atlantic/bslines97/f97182070958.nwa16) val=0 valcheck=0 tag=0 out=(file1=/RAID2/sbaker/nwa1024d/NDC/dsp_data/f97182070958.tmp_m2)\\012\\001merge_sb Apr 16 16:05:18 2004 merge_sb in=(file=/RAID2/sbaker/nwa1024d/NDC/dsp_data/f97182070958.tmp_m2, filecheck=/RAID/sbaker/DECLOUD/landmask16.img) val=1 valcheck=2 tag=0 out=(file1=/RAID2/sbaker/nwa6144d/NDC/dsp_data/f97182070958.nwa16)\\012\\001CONVRT Apr 16 16:05:21 2004 CONVRT 1024,1024,0,0,6,6,0,0,f,f,t,16,,SUB,1 in=/RAID2/sbaker/nwa6144d/NDC/dsp_data/f97182070958.nwa16   out=/RAID2/sbaker/nwa1024d/NDC/dsp_data/f97182070958.nwa16\\012\\012@\\000\\000\\000&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to add the following attributes:&lt;br /&gt;
&lt;br /&gt;
# Add an attribute to the HDF_GLOBAL attribute container called &amp;quot;ncml_location&amp;quot; since the file is wrapped by our NcML and the original location being wrapped might not be obvious.  &lt;br /&gt;
# Add the same attribute to the &#039;&#039;&#039;dsp_band_1&#039;&#039;&#039; Grid itself so it&#039;s easier to see and in case of projections &lt;br /&gt;
# Add &amp;quot;units&amp;quot; to the Array member variable &#039;&#039;&#039;dsp_band_1&#039;&#039;&#039; of the Grid that matches the containing Grid&#039;s &amp;quot;units&amp;quot; attribute with value &amp;quot;Temp&amp;quot;&lt;br /&gt;
# Add &amp;quot;units&amp;quot; to the &#039;&#039;&#039;lat&#039;&#039;&#039; map vector as a String with value &amp;quot;degrees_north&amp;quot;&lt;br /&gt;
# Add &amp;quot;units&amp;quot; to the &#039;&#039;&#039;lon&#039;&#039;&#039; map vector as a String with value &amp;quot;degrees_east&amp;quot;&lt;br /&gt;
&lt;br /&gt;
First, let&#039;s add the &amp;quot;ncml_location&amp;quot; into the HDF_GLOBAL attribute container.  To do this, we need to specify the &amp;quot;scope&amp;quot; of the HDF_GLOBAL attribute container (called a Structure in NcML):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Traverse into the HDF_GLOBAL attribute Structure (container) --&amp;gt;&lt;br /&gt;
  &amp;lt;attribute name=&amp;quot;HDF_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
1)  &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/attribute&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
This results in the following (clipped for clarity) DAS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    HDF_GLOBAL {&lt;br /&gt;
        UInt16 dsp_SubImageId 0;&lt;br /&gt;
        ... *** CLIPPED FOR CLARITY ***  ...&lt;br /&gt;
1)    String ncml_location &amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can see at the 1) where the new attribute has been added to HDF_GLOBAL as desired.&lt;br /&gt;
&lt;br /&gt;
Next, we want to add the same attribute to the top-level &#039;&#039;&#039;dsp_band_1&#039;&#039;&#039; Grid variable.  Here&#039;s the NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Traverse into the HDF_GLOBAL attribute Structure (container) --&amp;gt;&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;HDF_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!-- Traverse into the dsp_band_1 variable Structure (actually a Grid) --&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;dsp_band_1&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
2) &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which gives the (clipped again) DAS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    HDF_GLOBAL {&lt;br /&gt;
       ... *** CLIPPED FOR CLARITY *** ...&lt;br /&gt;
        String ncml_location &amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
2)    String ncml_location &amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;;&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have denoted the injected metadata with a 2).  &lt;br /&gt;
&lt;br /&gt;
As a learning exercise, let&#039;s say we made a mistake and tried to use &amp;lt;attribute&amp;gt; to specify the &#039;&#039;&#039;dsp_band_1&#039;&#039;&#039; attribute table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Traverse into the HDF_GLOBAL attribute Structure (container) --&amp;gt;&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;HDF_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!-- THIS IS AN ERROR! --&amp;gt;&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;dsp_band_1&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/attribute&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then we get a Parse Error:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;ISO-8859-1&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;response xmlns=&amp;quot;http://xml.opendap.org/ns/bes/1.0#&amp;quot; reqID=&amp;quot;some_unique_value&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;getDAS&amp;gt;&lt;br /&gt;
      &amp;lt;BESError&amp;gt;&amp;lt;Type&amp;gt;3&amp;lt;/Type&amp;gt;&lt;br /&gt;
           &amp;lt;Message&amp;gt;NCMLModule ParseError: at line 11: Cannot create a new attribute container with name=dsp_band_1 at current scope since a variable with that name already exists.  Scope=&amp;lt;/Message&amp;gt;&lt;br /&gt;
           &amp;lt;Administrator&amp;gt;admin.email.address@your.domain.name&amp;lt;/Administrator&amp;gt;&amp;lt;Location&amp;gt;&amp;lt;File&amp;gt;AttributeElement.cc&amp;lt;/File&amp;gt;&amp;lt;Line&amp;gt;277&amp;lt;/Line&amp;gt;&amp;lt;/Location&amp;gt;&lt;br /&gt;
      &amp;lt;/BESError&amp;gt;&lt;br /&gt;
   &amp;lt;/getDAS&amp;gt;&lt;br /&gt;
&amp;lt;/response&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which basically tells us the problem: we tried to specify an attribute with the same name as the Grid, but &#039;&#039;&#039;dsp_band_1&#039;&#039;&#039; is a variable already with that name.  It is illegal for an attribute and variable at the same scope to have the same name.&lt;br /&gt;
&lt;br /&gt;
Next, we want to add the &amp;quot;units&amp;quot; attribute that is on the Grid itself to the actual data Array inside the Grid (say we know we will be projecting it out with a constraint and don&#039;t want to lose this metadata).  The NcML now becomes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Traverse into the HDF_GLOBAL attribute Structure (container) --&amp;gt;&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;HDF_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!-- Traverse into the dsp_band_1 variable Structure (actually a Grid) --&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;dsp_band_1&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in the Grid&#039;s attribute table --&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;!-- While remaining in the Grid, traverse into the Array dsp_band_1: --&amp;gt;&lt;br /&gt;
   &amp;lt;variable name=&amp;quot;dsp_band_1&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;!-- And add the attribute there.  Fully qualified name of this scope is &amp;quot;dsp_band_1.dsp_band_1&amp;quot; --&amp;gt;&lt;br /&gt;
3)   &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;Temp&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/variable&amp;gt; &amp;lt;!-- Exit the Array variable scope, back to the Grid level --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Our modified DAS is now:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    HDF_GLOBAL {&lt;br /&gt;
       ... *** CLIPPED FOR CLARITY *** ...&lt;br /&gt;
        String ncml_location &amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
        String ncml_location &amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;;&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
3)        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the 3) denotes the newly injected metadata on &#039;&#039;&#039;dsp_band_1.dsp_band_1&#039;&#039;&#039;.  &lt;br /&gt;
&lt;br /&gt;
Next, we will add the units to both of the map vectors in the next version of our NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Traverse into the HDF_GLOBAL attribute Structure (container) --&amp;gt;&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;HDF_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!-- Traverse into the dsp_band_1 variable Structure (actually a Grid) --&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;dsp_band_1&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in the Grid&#039;s attribute table --&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;!-- While remaining in the Grid, traverse into the Array dsp_band_1: --&amp;gt;&lt;br /&gt;
   &amp;lt;variable name=&amp;quot;dsp_band_1&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;!-- And add the attribute there.  Fully qualified name of this scope is &amp;quot;dsp_band_1.dsp_band_1&amp;quot; --&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;Temp&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/variable&amp;gt; &amp;lt;!-- Exit the Array variable scope, back to the Grid level --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;!-- Traverse into the lat map vector variable --&amp;gt;&lt;br /&gt;
   &amp;lt;variable name=&amp;quot;lat&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;!-- Add the units --&amp;gt;&lt;br /&gt;
4)   &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;degrees_north&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/variable&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
   &amp;lt;!-- Traverse into the lon map vector variable --&amp;gt;&lt;br /&gt;
   &amp;lt;variable name=&amp;quot;lon&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;!-- Add the units --&amp;gt;&lt;br /&gt;
5)   &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;degrees_east&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where we denote the changed with 4) and 5).  Here&#039;s the resulting DAS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    HDF_GLOBAL {&lt;br /&gt;
        ... *** CLIPPED FOR CLARITY *** ...&lt;br /&gt;
1)      String ncml_location &amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
2)       String ncml_location &amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;;&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
3)          String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
4)          String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
5)          String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where we have marked all the new metadata we have injected, including the new attributes on the map vectors.&lt;br /&gt;
&lt;br /&gt;
Although we added metadata to the Grid, it is possible to also use the other forms of &amp;lt;attribute&amp;gt; in order to modify existing attributes or remove unwanted or incorrect attributes. &lt;br /&gt;
&lt;br /&gt;
The only place where this syntax varies slightly is in adding metadata to an aggregated Grid.  Please see the tutorial section on aggregating grids for more information.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Grid_Metadata_Tutorial&amp;diff=5598</id>
		<title>Grid Metadata Tutorial</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Grid_Metadata_Tutorial&amp;diff=5598"/>
		<updated>2010-04-20T21:02:41Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* An Example of Adding Metadata to a Grid */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= An Example of Adding Metadata to a Grid =&lt;br /&gt;
[[:Category:NCML]]&lt;br /&gt;
&lt;br /&gt;
We will go through a basic example of adding metadata to all the possible scopes in a Grid variable:&lt;br /&gt;
&lt;br /&gt;
* The top-level Grid Structure itself&lt;br /&gt;
* The data Array in the Grid&lt;br /&gt;
* Each Map vector in the Grid&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start with a &amp;quot;pass-through&amp;quot; NcML file which wraps a Netcdf dataset that Hyrax represents as a Grid.  This will let us see the exact structure of the data we will want to modify (which may be slightly different than the wrapped dataset due to legacy issues with how shared dimensions are represented, etc):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- This space intentionally left blank! --&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This gives the DDS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        UInt32 dsp_band_1[lat = 1024][lon = 1024];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 lat[1024];&lt;br /&gt;
        Float64 lon[1024];&lt;br /&gt;
    } dsp_band_1;&lt;br /&gt;
} grid_attributes_2.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and the (extensive) DAS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    HDF_GLOBAL {&lt;br /&gt;
        UInt16 dsp_SubImageId 0;&lt;br /&gt;
        String dsp_SubImageName &amp;quot;N/A&amp;quot;;&lt;br /&gt;
        Int32 dsp_ModificationDate 20040416;&lt;br /&gt;
        Int32 dsp_ModificationTime 160521;&lt;br /&gt;
        Int32 dsp_SubImageFlag 64;&lt;br /&gt;
        String dsp_SubImageTitle &amp;quot;Ingested by SCRIPP&amp;quot;;&lt;br /&gt;
        Int32 dsp_StartDate 19970701;&lt;br /&gt;
        Float32 dsp_StartTime 70958.5;&lt;br /&gt;
        Int32 dsp_SizeX 1024;&lt;br /&gt;
        Int32 dsp_SizeY 1024;&lt;br /&gt;
        Int32 dsp_OffsetX 0;&lt;br /&gt;
        Int32 dsp_RecordLength 2048;&lt;br /&gt;
        Byte dsp_DataOrganization 64;&lt;br /&gt;
        Byte dsp_NumberOfBands 1;&lt;br /&gt;
        String dsp_ing_tiros_ourid &amp;quot;NO14****C\\217\\345P?\\253\\205\\037&amp;quot;;&lt;br /&gt;
        UInt16 dsp_ing_tiros_numscn 44305;&lt;br /&gt;
        UInt16 dsp_ing_tiros_idsat 2560;&lt;br /&gt;
        UInt16 dsp_ing_tiros_iddata 768;&lt;br /&gt;
        UInt16 dsp_ing_tiros_year 24832;&lt;br /&gt;
        UInt16 dsp_ing_tiros_daysmp 46592;&lt;br /&gt;
        Int32 dsp_ing_tiros_milsec 1235716353;&lt;br /&gt;
        Int32 dsp_ing_tiros_slope 1075636998, 551287046, -426777345, -1339034123, 5871604;&lt;br /&gt;
        Int32 dsp_ing_tiros_intcpt 514263295, 1892553983, -371365632, 9497638, -2140793044;&lt;br /&gt;
        UInt16 dsp_ing_tiros_tabadr 256, 512, 768;&lt;br /&gt;
        UInt16 dsp_ing_tiros_cnlins 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_cncols 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_czncs 8;&lt;br /&gt;
        UInt16 dsp_ing_tiros_line 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_icol 0;&lt;br /&gt;
        String dsp_ing_tiros_date0 &amp;quot;23-MAY-10 13:54:29\\030&amp;quot;;&lt;br /&gt;
        String dsp_ing_tiros_time0 &amp;quot;13:54:29\\030&amp;quot;;&lt;br /&gt;
        UInt16 dsp_ing_tiros_label 14112, 12576, 14137;&lt;br /&gt;
        UInt16 dsp_ing_tiros_nxtblk 1280;&lt;br /&gt;
        UInt16 dsp_ing_tiros_datblk 1280;&lt;br /&gt;
        UInt16 dsp_ing_tiros_itape 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_cbias 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ccoeff 0;&lt;br /&gt;
        Int32 dsp_ing_tiros_pastim 1235716353;&lt;br /&gt;
        UInt16 dsp_ing_tiros_passcn 3840;&lt;br /&gt;
        UInt16 dsp_ing_tiros_lostct 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_lost 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ndrll 1280;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ndrrec 3840, 5376, 6912, 8448, 9984, 0, 0, 0, 0, 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ndrlat 46110, 44318, 42526, 40478, 38686, 0, 0, 0, 0, 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ndrlon 49891, 48611, 47075, 45539, 44259, 0, 0, 0, 0, 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_chncnt 1280;&lt;br /&gt;
        UInt16 dsp_ing_tiros_chndsq 8, 8, 8, 8, 8;&lt;br /&gt;
        UInt16 dsp_ing_tiros_czncs2 4;&lt;br /&gt;
        UInt16 dsp_ing_tiros_wrdsiz 512;&lt;br /&gt;
        UInt16 dsp_ing_tiros_nchbas 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_nchlst 1280;&lt;br /&gt;
        Float32 dsp_ing_tiros_rpmclc 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_numpix 8;&lt;br /&gt;
        UInt16 dsp_ing_tiros_scnden 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_eltden 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_orbtno 23858;&lt;br /&gt;
        Int32 dsp_ing_tiros_slope2 1075636998, 551287046, -426777345, -1339034123, 5871604;&lt;br /&gt;
        Int32 dsp_ing_tiros_intcp2 514263295, 1892553983, -371365632, 9497638, -2140793044;&lt;br /&gt;
        Float32 dsp_ing_tiros_prtemp 3.0811e+10;&lt;br /&gt;
        Float32 dsp_ing_tiros_timerr 5.6611e-20;&lt;br /&gt;
        UInt16 dsp_ing_tiros_timstn 8279;&lt;br /&gt;
        String dsp_nav_xsatid &amp;quot;NO14\\005\\002&amp;quot;;&lt;br /&gt;
        Byte dsp_nav_xsatty 5;&lt;br /&gt;
        Byte dsp_nav_xproty 2;&lt;br /&gt;
        Byte dsp_nav_xmapsl 0;&lt;br /&gt;
        Byte dsp_nav_xtmpch 4;&lt;br /&gt;
        Float32 dsp_nav_ximgdy 97182;&lt;br /&gt;
        Float32 dsp_nav_ximgtm 70954.4;&lt;br /&gt;
        Float32 dsp_nav_xorbit 12893;&lt;br /&gt;
        Float32 dsp_nav_ximgcv 71.1722, 0, 4.88181, 0, -112.11, 0, -27.9583, 0;&lt;br /&gt;
        Float32 dsp_nav_earth_linoff 0;&lt;br /&gt;
        Float32 dsp_nav_earth_pixoff 0;&lt;br /&gt;
        Float32 dsp_nav_earth_scnstr 1;&lt;br /&gt;
        Float32 dsp_nav_earth_scnstp 1024;&lt;br /&gt;
        Float32 dsp_nav_earth_pixstr 1;&lt;br /&gt;
        Float32 dsp_nav_earth_pixstp 1024;&lt;br /&gt;
        Float32 dsp_nav_earth_latorg 0;&lt;br /&gt;
        Float32 dsp_nav_earth_lonorg 0;&lt;br /&gt;
        Float32 dsp_nav_earth_orgrot 0;&lt;br /&gt;
        Float32 dsp_nav_earth_lattop 0;&lt;br /&gt;
        Float32 dsp_nav_earth_latbot 0;&lt;br /&gt;
        Float32 dsp_nav_earth_latcen 38;&lt;br /&gt;
        Float32 dsp_nav_earth_loncen -70;&lt;br /&gt;
        Float32 dsp_nav_earth_height 66.3444;&lt;br /&gt;
        Float32 dsp_nav_earth_width 84.2205;&lt;br /&gt;
        Float32 dsp_nav_earth_level 1;&lt;br /&gt;
        Float32 dsp_nav_earth_xspace 5.99902;&lt;br /&gt;
        Float32 dsp_nav_earth_yspace 5.99902;&lt;br /&gt;
        String dsp_nav_earth_rev &amp;quot; 0.1&amp;quot;;&lt;br /&gt;
        Float32 dsp_nav_earth_dflag 0;&lt;br /&gt;
        Float32 dsp_nav_earth_toplat 71.1722;&lt;br /&gt;
        Float32 dsp_nav_earth_botlat 4.88181;&lt;br /&gt;
        Float32 dsp_nav_earth_leflon -112.11;&lt;br /&gt;
        Float32 dsp_nav_earth_ritlon -27.9583;&lt;br /&gt;
        Float32 dsp_nav_earth_numpix 1024;&lt;br /&gt;
        Float32 dsp_nav_earth_numras 1024;&lt;br /&gt;
        Float32 dsp_nav_earth_magxx 6;&lt;br /&gt;
        Float32 dsp_nav_earth_magyy 6;&lt;br /&gt;
        Int32 dsp_hgt_llnval 18;&lt;br /&gt;
        Int32 dsp_hgt_lltime 25744350;&lt;br /&gt;
        Float32 dsp_hgt_llvect 869.428, 1.14767, 868.659, 1.09635, 867.84, 1.04502, 866.979, 0.9937, 866.084, 0.942374, 865.165, 0.891045, 864.231, 0.839715, 863.292, 0.788383, 862.356, 0.737049, 861.434, 0.685714, 860.536, 0.634378, 859.67, 0.58304, 858.847, 0.531702, 858.075, 0.480362, 857.363, 0.429022, 856.718, 0.377682, 856.148, 0.326341, 855.66, 0.275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;&lt;br /&gt;
        String history &amp;quot;\\001PATHNLC May 23 22:40:54 2000 PATHNLC t,3,269.16,0.125,0.,0.01,271.16,308.16,,,,1,,,2,,,3,,,,,,4,,,,,,,2.,,35.,0.1,5,,,,,,,2.,,35.,0.15,55.,80.,0.005,20,,,-2,6.,t,,,,,,,,,,16,,3.5 allb=0 nlsst=1 in=/pathfdr5//97182070958.N14@INGEST@ in1=/pathfdr10/mask/oi.9727.mean out=/pathfdr4/nlc/f97182070958.FMG@0\\012\\004PATHNLC  NLSST Temp calculation date: April 10, 1996\\012\\001OISST Jan 12 17:53:43 1998 OISST  /usr3/gacsst/maketc/oi/dinp/oi.comp.bias.1997,/usr3/gacsst/maketc/oi/dout/oi.97,-3.,0.15,oi.dates.97,0\\012\\004OISST 26 97 06 22 97 06 28  7        472\\012\\001STATS Jan 12 18:27:34 1998 STATS minpix=1 maxpix=255 in=/usr3/gacsst/maketc/oi/dout//oi.9726 \\011  audit=t, callim=f, cal=f, cloud=f \\011  outm=/usr3/gacsst/etc/oi/oi.9727.mean\\012\\001OISST Jan 12 17:53:43 1998 OISST  /usr3/gacsst/maketc/oi/dinp/oi.comp.bias.1997,/usr3/gacsst/maketc/oi/dout/oi.97,-3.,0.15,oi.dates.97,0\\012\\004OISST 27 97 06 29 97 07 05  7        472\\012\\002STATS /usr3/gacsst/maketc/oi/dout//oi.9727\\012\\001OISST Jan 12 17:53:43 1998 OISST  /usr3/gacsst/maketc/oi/dinp/oi.comp.bias.1997,/usr3/gacsst/maketc/oi/dout/oi.97,-3.,0.15,oi.dates.97,0\\012\\004OISST 27 97 06 29 97 07 05  7        472\\012\\002STATS /usr3/gacsst/maketc/oi/dout//oi.9727\\012\\001OISST Jan 12 17:53:43 1998 OISST  /usr3/gacsst/maketc/oi/dinp/oi.comp.bias.1997,/usr3/gacsst/maketc/oi/dout/oi.97,-3.,0.15,oi.dates.97,0\\012\\004OISST 28 97 07 06 97 07 12  7        472\\012\\002STATS /usr3/gacsst/maketc/oi/dout//oi.9728\\012\\002PATHNLC /pathfdr10/mask/oi.9727.mean\\012\\004PATHNLC  45d coeffs used (1) =    0.759   0.947   0.110   1.460   0.000\\012\\004PATHNLC  45d coeffs used (2) =    1.320   0.952   0.071   0.882   0.000\\012\\004PATHNLC  45d coeffs used (3) =    0.000   0.000   0.000   0.000   0.000\\012\\004PATHNLC  GETOZONE I     0.0900    0.0000\\012\\001REMAP Jun  4 07:59:42 2000 REMAP in=/coral/miami/remaps/sst_8r/file_uZ.FMG out=/coral/miami/remaps/sst_8r/f97182070958.nwa16\\012\\004REMAP Output image pixel, line size =    6144,    6144\\012\\004REMAP Grid spacing (X,Y) = (        6.00,        6.00), Projection Code=     1\\012\\004REMAP center lon,lat,dlon,dlat =       -70.00       38.00        0.01        0.01\\012\\001merge_sb Apr 16 16:05:09 2004 merge_sb in=(file=/NOPP/carlw/atlantic/remaps/nwa16/f97182070958.nwa16, filecheck=/RAID2/sbaker/atlantic/bslines97/f97182070958.nwa16) val=0 valcheck=0 tag=0 out=(file1=/RAID2/sbaker/nwa1024d/NDC/dsp_data/f97182070958.tmp_m2)\\012\\001merge_sb Apr 16 16:05:18 2004 merge_sb in=(file=/RAID2/sbaker/nwa1024d/NDC/dsp_data/f97182070958.tmp_m2, filecheck=/RAID/sbaker/DECLOUD/landmask16.img) val=1 valcheck=2 tag=0 out=(file1=/RAID2/sbaker/nwa6144d/NDC/dsp_data/f97182070958.nwa16)\\012\\001CONVRT Apr 16 16:05:21 2004 CONVRT 1024,1024,0,0,6,6,0,0,f,f,t,16,,SUB,1 in=/RAID2/sbaker/nwa6144d/NDC/dsp_data/f97182070958.nwa16   out=/RAID2/sbaker/nwa1024d/NDC/dsp_data/f97182070958.nwa16\\012\\012@\\000\\000\\000&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to add the following attributes:&lt;br /&gt;
&lt;br /&gt;
# Add an attribute to the HDF_GLOBAL attribute container called &amp;quot;ncml_location&amp;quot; since the file is wrapped by our NcML and the original location being wrapped might not be obvious.  &lt;br /&gt;
# Add the same attribute to the &#039;&#039;&#039;dsp_band_1&#039;&#039;&#039; Grid itself so it&#039;s easier to see and in case of projections &lt;br /&gt;
# Add &amp;quot;units&amp;quot; to the Array member variable &#039;&#039;&#039;dsp_band_1&#039;&#039;&#039; of the Grid that matches the containing Grid&#039;s &amp;quot;units&amp;quot; attribute with value &amp;quot;Temp&amp;quot;&lt;br /&gt;
# Add &amp;quot;units&amp;quot; to the &#039;&#039;&#039;lat&#039;&#039;&#039; map vector as a String with value &amp;quot;degrees_north&amp;quot;&lt;br /&gt;
# Add &amp;quot;units&amp;quot; to the &#039;&#039;&#039;lon&#039;&#039;&#039; map vector as a String with value &amp;quot;degrees_east&amp;quot;&lt;br /&gt;
&lt;br /&gt;
First, let&#039;s add the &amp;quot;ncml_location&amp;quot; into the HDF_GLOBAL attribute container.  To do this, we need to specify the &amp;quot;scope&amp;quot; of the HDF_GLOBAL attribute container (called a Structure in NcML):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Traverse into the HDF_GLOBAL attribute Structure (container) --&amp;gt;&lt;br /&gt;
  &amp;lt;attribute name=&amp;quot;HDF_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/attribute&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
This results in the following (clipped for clarity) DAS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    HDF_GLOBAL {&lt;br /&gt;
        UInt16 dsp_SubImageId 0;&lt;br /&gt;
        ... *** CLIPPED FOR CLARITY ***  ...&lt;br /&gt;
1)    String ncml_location &amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can see at the 1) where the new attribute has been added to HDF_GLOBAL as desired.&lt;br /&gt;
&lt;br /&gt;
Next, we want to add the same attribute to the top-level &#039;&#039;&#039;dsp_band_1&#039;&#039;&#039; Grid variable.  Here&#039;s the NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Traverse into the HDF_GLOBAL attribute Structure (container) --&amp;gt;&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;HDF_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!-- Traverse into the dsp_band_1 variable Structure (actually a Grid) --&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;dsp_band_1&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which gives the (clipped again) DAS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    HDF_GLOBAL {&lt;br /&gt;
       ... *** CLIPPED FOR CLARITY *** ...&lt;br /&gt;
        String ncml_location &amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
2)    String ncml_location &amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;;&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have denoted the injected metadata with a 2).  &lt;br /&gt;
&lt;br /&gt;
As a learning exercise, let&#039;s say we made a mistake and tried to use &amp;lt;attribute&amp;gt; to specify the &#039;&#039;&#039;dsp_band_1&#039;&#039;&#039; attribute table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Traverse into the HDF_GLOBAL attribute Structure (container) --&amp;gt;&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;HDF_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!-- THIS IS AN ERROR! --&amp;gt;&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;dsp_band_1&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;!-- Specify the new attribute in that scope --&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;ncml_location&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/attribute&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then we get a Parse Error:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;ISO-8859-1&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;response xmlns=&amp;quot;http://xml.opendap.org/ns/bes/1.0#&amp;quot; reqID=&amp;quot;some_unique_value&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;getDAS&amp;gt;&lt;br /&gt;
      &amp;lt;BESError&amp;gt;&amp;lt;Type&amp;gt;3&amp;lt;/Type&amp;gt;&lt;br /&gt;
           &amp;lt;Message&amp;gt;NCMLModule ParseError: at line 11: Cannot create a new attribute container with name=dsp_band_1 at current scope since a variable with that name already exists.  Scope=&amp;lt;/Message&amp;gt;&lt;br /&gt;
           &amp;lt;Administrator&amp;gt;admin.email.address@your.domain.name&amp;lt;/Administrator&amp;gt;&amp;lt;Location&amp;gt;&amp;lt;File&amp;gt;AttributeElement.cc&amp;lt;/File&amp;gt;&amp;lt;Line&amp;gt;277&amp;lt;/Line&amp;gt;&amp;lt;/Location&amp;gt;&lt;br /&gt;
      &amp;lt;/BESError&amp;gt;&lt;br /&gt;
   &amp;lt;/getDAS&amp;gt;&lt;br /&gt;
&amp;lt;/response&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which basically tells us the problem: we tried to specify an attribute with the same name as the Grid, but &#039;&#039;&#039;dsp_band_1&#039;&#039;&#039; is a variable already with that name.  It is illegal for an attribute and variable at the same scope to have the same name.&lt;br /&gt;
&lt;br /&gt;
Next, we want to add the &amp;quot;units&amp;quot; attribute that is on the Grid itself to the actual data Array inside the Grid (say we know we will be projecting it out with a constraint and don&#039;t want to lose this metadata).  The NcML now becomes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Grid_Metadata_Tutorial&amp;diff=5597</id>
		<title>Grid Metadata Tutorial</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Grid_Metadata_Tutorial&amp;diff=5597"/>
		<updated>2010-04-20T20:25:37Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* An Example of Adding Metadata to a Grid */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= An Example of Adding Metadata to a Grid =&lt;br /&gt;
[[:Category:NCML]]&lt;br /&gt;
&lt;br /&gt;
We will go through a basic example of adding metadata to all the possible scopes in a Grid variable:&lt;br /&gt;
&lt;br /&gt;
* The top-level Grid Structure itself&lt;br /&gt;
* The data Array in the Grid&lt;br /&gt;
* Each Map vector in the Grid&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start with a &amp;quot;pass-through&amp;quot; NcML file which wraps a Netcdf dataset that Hyrax represents as a Grid.  This will let us see the exact structure of the data we will want to modify (which may be slightly different than the wrapped dataset due to legacy issues with how shared dimensions are represented, etc):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- This space intentionally left blank! --&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This gives the DDS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        UInt32 dsp_band_1[lat = 1024][lon = 1024];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 lat[1024];&lt;br /&gt;
        Float64 lon[1024];&lt;br /&gt;
    } dsp_band_1;&lt;br /&gt;
} grid_attributes_2.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and the (extensive) DAS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    HDF_GLOBAL {&lt;br /&gt;
        UInt16 dsp_SubImageId 0;&lt;br /&gt;
        String dsp_SubImageName &amp;quot;N/A&amp;quot;;&lt;br /&gt;
        Int32 dsp_ModificationDate 20040416;&lt;br /&gt;
        Int32 dsp_ModificationTime 160521;&lt;br /&gt;
        Int32 dsp_SubImageFlag 64;&lt;br /&gt;
        String dsp_SubImageTitle &amp;quot;Ingested by SCRIPP&amp;quot;;&lt;br /&gt;
        Int32 dsp_StartDate 19970701;&lt;br /&gt;
        Float32 dsp_StartTime 70958.5;&lt;br /&gt;
        Int32 dsp_SizeX 1024;&lt;br /&gt;
        Int32 dsp_SizeY 1024;&lt;br /&gt;
        Int32 dsp_OffsetX 0;&lt;br /&gt;
        Int32 dsp_RecordLength 2048;&lt;br /&gt;
        Byte dsp_DataOrganization 64;&lt;br /&gt;
        Byte dsp_NumberOfBands 1;&lt;br /&gt;
        String dsp_ing_tiros_ourid &amp;quot;NO14****C\\217\\345P?\\253\\205\\037&amp;quot;;&lt;br /&gt;
        UInt16 dsp_ing_tiros_numscn 44305;&lt;br /&gt;
        UInt16 dsp_ing_tiros_idsat 2560;&lt;br /&gt;
        UInt16 dsp_ing_tiros_iddata 768;&lt;br /&gt;
        UInt16 dsp_ing_tiros_year 24832;&lt;br /&gt;
        UInt16 dsp_ing_tiros_daysmp 46592;&lt;br /&gt;
        Int32 dsp_ing_tiros_milsec 1235716353;&lt;br /&gt;
        Int32 dsp_ing_tiros_slope 1075636998, 551287046, -426777345, -1339034123, 5871604;&lt;br /&gt;
        Int32 dsp_ing_tiros_intcpt 514263295, 1892553983, -371365632, 9497638, -2140793044;&lt;br /&gt;
        UInt16 dsp_ing_tiros_tabadr 256, 512, 768;&lt;br /&gt;
        UInt16 dsp_ing_tiros_cnlins 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_cncols 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_czncs 8;&lt;br /&gt;
        UInt16 dsp_ing_tiros_line 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_icol 0;&lt;br /&gt;
        String dsp_ing_tiros_date0 &amp;quot;23-MAY-10 13:54:29\\030&amp;quot;;&lt;br /&gt;
        String dsp_ing_tiros_time0 &amp;quot;13:54:29\\030&amp;quot;;&lt;br /&gt;
        UInt16 dsp_ing_tiros_label 14112, 12576, 14137;&lt;br /&gt;
        UInt16 dsp_ing_tiros_nxtblk 1280;&lt;br /&gt;
        UInt16 dsp_ing_tiros_datblk 1280;&lt;br /&gt;
        UInt16 dsp_ing_tiros_itape 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_cbias 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ccoeff 0;&lt;br /&gt;
        Int32 dsp_ing_tiros_pastim 1235716353;&lt;br /&gt;
        UInt16 dsp_ing_tiros_passcn 3840;&lt;br /&gt;
        UInt16 dsp_ing_tiros_lostct 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_lost 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ndrll 1280;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ndrrec 3840, 5376, 6912, 8448, 9984, 0, 0, 0, 0, 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ndrlat 46110, 44318, 42526, 40478, 38686, 0, 0, 0, 0, 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_ndrlon 49891, 48611, 47075, 45539, 44259, 0, 0, 0, 0, 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_chncnt 1280;&lt;br /&gt;
        UInt16 dsp_ing_tiros_chndsq 8, 8, 8, 8, 8;&lt;br /&gt;
        UInt16 dsp_ing_tiros_czncs2 4;&lt;br /&gt;
        UInt16 dsp_ing_tiros_wrdsiz 512;&lt;br /&gt;
        UInt16 dsp_ing_tiros_nchbas 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_nchlst 1280;&lt;br /&gt;
        Float32 dsp_ing_tiros_rpmclc 0;&lt;br /&gt;
        UInt16 dsp_ing_tiros_numpix 8;&lt;br /&gt;
        UInt16 dsp_ing_tiros_scnden 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_eltden 256;&lt;br /&gt;
        UInt16 dsp_ing_tiros_orbtno 23858;&lt;br /&gt;
        Int32 dsp_ing_tiros_slope2 1075636998, 551287046, -426777345, -1339034123, 5871604;&lt;br /&gt;
        Int32 dsp_ing_tiros_intcp2 514263295, 1892553983, -371365632, 9497638, -2140793044;&lt;br /&gt;
        Float32 dsp_ing_tiros_prtemp 3.0811e+10;&lt;br /&gt;
        Float32 dsp_ing_tiros_timerr 5.6611e-20;&lt;br /&gt;
        UInt16 dsp_ing_tiros_timstn 8279;&lt;br /&gt;
        String dsp_nav_xsatid &amp;quot;NO14\\005\\002&amp;quot;;&lt;br /&gt;
        Byte dsp_nav_xsatty 5;&lt;br /&gt;
        Byte dsp_nav_xproty 2;&lt;br /&gt;
        Byte dsp_nav_xmapsl 0;&lt;br /&gt;
        Byte dsp_nav_xtmpch 4;&lt;br /&gt;
        Float32 dsp_nav_ximgdy 97182;&lt;br /&gt;
        Float32 dsp_nav_ximgtm 70954.4;&lt;br /&gt;
        Float32 dsp_nav_xorbit 12893;&lt;br /&gt;
        Float32 dsp_nav_ximgcv 71.1722, 0, 4.88181, 0, -112.11, 0, -27.9583, 0;&lt;br /&gt;
        Float32 dsp_nav_earth_linoff 0;&lt;br /&gt;
        Float32 dsp_nav_earth_pixoff 0;&lt;br /&gt;
        Float32 dsp_nav_earth_scnstr 1;&lt;br /&gt;
        Float32 dsp_nav_earth_scnstp 1024;&lt;br /&gt;
        Float32 dsp_nav_earth_pixstr 1;&lt;br /&gt;
        Float32 dsp_nav_earth_pixstp 1024;&lt;br /&gt;
        Float32 dsp_nav_earth_latorg 0;&lt;br /&gt;
        Float32 dsp_nav_earth_lonorg 0;&lt;br /&gt;
        Float32 dsp_nav_earth_orgrot 0;&lt;br /&gt;
        Float32 dsp_nav_earth_lattop 0;&lt;br /&gt;
        Float32 dsp_nav_earth_latbot 0;&lt;br /&gt;
        Float32 dsp_nav_earth_latcen 38;&lt;br /&gt;
        Float32 dsp_nav_earth_loncen -70;&lt;br /&gt;
        Float32 dsp_nav_earth_height 66.3444;&lt;br /&gt;
        Float32 dsp_nav_earth_width 84.2205;&lt;br /&gt;
        Float32 dsp_nav_earth_level 1;&lt;br /&gt;
        Float32 dsp_nav_earth_xspace 5.99902;&lt;br /&gt;
        Float32 dsp_nav_earth_yspace 5.99902;&lt;br /&gt;
        String dsp_nav_earth_rev &amp;quot; 0.1&amp;quot;;&lt;br /&gt;
        Float32 dsp_nav_earth_dflag 0;&lt;br /&gt;
        Float32 dsp_nav_earth_toplat 71.1722;&lt;br /&gt;
        Float32 dsp_nav_earth_botlat 4.88181;&lt;br /&gt;
        Float32 dsp_nav_earth_leflon -112.11;&lt;br /&gt;
        Float32 dsp_nav_earth_ritlon -27.9583;&lt;br /&gt;
        Float32 dsp_nav_earth_numpix 1024;&lt;br /&gt;
        Float32 dsp_nav_earth_numras 1024;&lt;br /&gt;
        Float32 dsp_nav_earth_magxx 6;&lt;br /&gt;
        Float32 dsp_nav_earth_magyy 6;&lt;br /&gt;
        Int32 dsp_hgt_llnval 18;&lt;br /&gt;
        Int32 dsp_hgt_lltime 25744350;&lt;br /&gt;
        Float32 dsp_hgt_llvect 869.428, 1.14767, 868.659, 1.09635, 867.84, 1.04502, 866.979, 0.9937, 866.084, 0.942374, 865.165, 0.891045, 864.231, 0.839715, 863.292, 0.788383, 862.356, 0.737049, 861.434, 0.685714, 860.536, 0.634378, 859.67, 0.58304, 858.847, 0.531702, 858.075, 0.480362, 857.363, 0.429022, 856.718, 0.377682, 856.148, 0.326341, 855.66, 0.275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;&lt;br /&gt;
        String history &amp;quot;\\001PATHNLC May 23 22:40:54 2000 PATHNLC t,3,269.16,0.125,0.,0.01,271.16,308.16,,,,1,,,2,,,3,,,,,,4,,,,,,,2.,,35.,0.1,5,,,,,,,2.,,35.,0.15,55.,80.,0.005,20,,,-2,6.,t,,,,,,,,,,16,,3.5 allb=0 nlsst=1 in=/pathfdr5//97182070958.N14@INGEST@ in1=/pathfdr10/mask/oi.9727.mean out=/pathfdr4/nlc/f97182070958.FMG@0\\012\\004PATHNLC  NLSST Temp calculation date: April 10, 1996\\012\\001OISST Jan 12 17:53:43 1998 OISST  /usr3/gacsst/maketc/oi/dinp/oi.comp.bias.1997,/usr3/gacsst/maketc/oi/dout/oi.97,-3.,0.15,oi.dates.97,0\\012\\004OISST 26 97 06 22 97 06 28  7        472\\012\\001STATS Jan 12 18:27:34 1998 STATS minpix=1 maxpix=255 in=/usr3/gacsst/maketc/oi/dout//oi.9726 \\011  audit=t, callim=f, cal=f, cloud=f \\011  outm=/usr3/gacsst/etc/oi/oi.9727.mean\\012\\001OISST Jan 12 17:53:43 1998 OISST  /usr3/gacsst/maketc/oi/dinp/oi.comp.bias.1997,/usr3/gacsst/maketc/oi/dout/oi.97,-3.,0.15,oi.dates.97,0\\012\\004OISST 27 97 06 29 97 07 05  7        472\\012\\002STATS /usr3/gacsst/maketc/oi/dout//oi.9727\\012\\001OISST Jan 12 17:53:43 1998 OISST  /usr3/gacsst/maketc/oi/dinp/oi.comp.bias.1997,/usr3/gacsst/maketc/oi/dout/oi.97,-3.,0.15,oi.dates.97,0\\012\\004OISST 27 97 06 29 97 07 05  7        472\\012\\002STATS /usr3/gacsst/maketc/oi/dout//oi.9727\\012\\001OISST Jan 12 17:53:43 1998 OISST  /usr3/gacsst/maketc/oi/dinp/oi.comp.bias.1997,/usr3/gacsst/maketc/oi/dout/oi.97,-3.,0.15,oi.dates.97,0\\012\\004OISST 28 97 07 06 97 07 12  7        472\\012\\002STATS /usr3/gacsst/maketc/oi/dout//oi.9728\\012\\002PATHNLC /pathfdr10/mask/oi.9727.mean\\012\\004PATHNLC  45d coeffs used (1) =    0.759   0.947   0.110   1.460   0.000\\012\\004PATHNLC  45d coeffs used (2) =    1.320   0.952   0.071   0.882   0.000\\012\\004PATHNLC  45d coeffs used (3) =    0.000   0.000   0.000   0.000   0.000\\012\\004PATHNLC  GETOZONE I     0.0900    0.0000\\012\\001REMAP Jun  4 07:59:42 2000 REMAP in=/coral/miami/remaps/sst_8r/file_uZ.FMG out=/coral/miami/remaps/sst_8r/f97182070958.nwa16\\012\\004REMAP Output image pixel, line size =    6144,    6144\\012\\004REMAP Grid spacing (X,Y) = (        6.00,        6.00), Projection Code=     1\\012\\004REMAP center lon,lat,dlon,dlat =       -70.00       38.00        0.01        0.01\\012\\001merge_sb Apr 16 16:05:09 2004 merge_sb in=(file=/NOPP/carlw/atlantic/remaps/nwa16/f97182070958.nwa16, filecheck=/RAID2/sbaker/atlantic/bslines97/f97182070958.nwa16) val=0 valcheck=0 tag=0 out=(file1=/RAID2/sbaker/nwa1024d/NDC/dsp_data/f97182070958.tmp_m2)\\012\\001merge_sb Apr 16 16:05:18 2004 merge_sb in=(file=/RAID2/sbaker/nwa1024d/NDC/dsp_data/f97182070958.tmp_m2, filecheck=/RAID/sbaker/DECLOUD/landmask16.img) val=1 valcheck=2 tag=0 out=(file1=/RAID2/sbaker/nwa6144d/NDC/dsp_data/f97182070958.nwa16)\\012\\001CONVRT Apr 16 16:05:21 2004 CONVRT 1024,1024,0,0,6,6,0,0,f,f,t,16,,SUB,1 in=/RAID2/sbaker/nwa6144d/NDC/dsp_data/f97182070958.nwa16   out=/RAID2/sbaker/nwa1024d/NDC/dsp_data/f97182070958.nwa16\\012\\012@\\000\\000\\000&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Grid_Metadata_Tutorial&amp;diff=5596</id>
		<title>Grid Metadata Tutorial</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Grid_Metadata_Tutorial&amp;diff=5596"/>
		<updated>2010-04-20T20:19:54Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Grid Metadata Tutorial */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= An Example of Adding Metadata to a Grid =&lt;br /&gt;
[[:Category:NCML]]&lt;br /&gt;
&lt;br /&gt;
We will go through a basic example of adding metadata to all the possible scopes in a Grid variable:&lt;br /&gt;
&lt;br /&gt;
* The top-level Grid Structure itself&lt;br /&gt;
* The data Array in the Grid&lt;br /&gt;
* Each Map vector in the Grid&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start with a &amp;quot;pass-through&amp;quot; NcML file which wraps a Netcdf dataset that Hyrax represents as a Grid.  This will let us see the exact structure of the data we will want to modify (which may be slightly different than the wrapped dataset due to legacy issues with how shared dimensions are represented, etc):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- This space intentionally left blank! --&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This gives the DDS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and the DAS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Grid_Metadata_Tutorial&amp;diff=5595</id>
		<title>Grid Metadata Tutorial</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Grid_Metadata_Tutorial&amp;diff=5595"/>
		<updated>2010-04-20T19:59:48Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: New page: = Grid Metadata Tutorial = :Category:NCML&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Grid Metadata Tutorial =&lt;br /&gt;
[[:Category:NCML]]&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=BES_-_Modules_-_NcML_Module&amp;diff=5594</id>
		<title>BES - Modules - NcML Module</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=BES_-_Modules_-_NcML_Module&amp;diff=5594"/>
		<updated>2010-04-20T19:59:03Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
[[Category:NCML]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Welcome to the OPeNDAP NcML Data Handler Module v1.0.1 for Hyrax 1.6!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[Updated for NcML Module v1.0.1 for Hyrax 1.6.0 beta --  8 April 2010]&lt;br /&gt;
&lt;br /&gt;
This module may be added to a Hyrax 1.6 server to extend its data&lt;br /&gt;
serving capability to NcML 2.2 files (see&lt;br /&gt;
http://www.unidata.ucar.edu/software/netcdf/ncml/).  NcML provides support for modifying other datasets in various ways, such as adding metadata and data and aggregating multiple datasets in several ways.&lt;br /&gt;
&lt;br /&gt;
We refer the reader to the Unidata NcML tutorial: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Tutorial.html which will give the basics of using NcML.  We then give a reference manual for the various elements and their attributes.  Additionally we have provided a more extensive tutorial on NcML aggregation.  Please see [[#Aggregation Tutorials]].&lt;br /&gt;
&lt;br /&gt;
Since the DAP Grid is a common case, we will also give a simple example for adding metadata to the various parts of a Grid dataset using NcML.  Please see [[Grid_Metadata_Tutorial]].&lt;br /&gt;
&lt;br /&gt;
==Features==         &lt;br /&gt;
   &lt;br /&gt;
This current version (v1.0.1) currently implements a subset of NcML 2.2&lt;br /&gt;
functionality, along with some OPeNDAP extensions:&lt;br /&gt;
&lt;br /&gt;
* Metadata Manipulation&lt;br /&gt;
** Addition, Removal, and Modification of attributes to other datasets (NetCDF, HDF4, HD5, etc.) served by the same Hyrax 1.6 server&lt;br /&gt;
** Extends NcML 2.2 to allow for common nested &amp;quot;attribute containers&amp;quot; &lt;br /&gt;
** Attributes can be DAP2 types as well as the NcML types &lt;br /&gt;
** Attributes can be of the special &amp;quot;OtherXML&amp;quot; type for injecting arbitrary XML into a DDX response&lt;br /&gt;
* Data Manipulation&lt;br /&gt;
** Addition of new data variables (scalars or arrays of basic types as well as structures) &lt;br /&gt;
** Variables may be removed from the wrapped dataset&lt;br /&gt;
** Allows the creation of &amp;quot;pure virtual&amp;quot; datasets which do not wrap another dataset&lt;br /&gt;
* Aggregations: JoinNew and Union [[#Aggregation Tutorials]]&lt;br /&gt;
** JoinNew Aggregation ([[NCML_Module_Aggregation_JoinNew]])&lt;br /&gt;
*** Allows multiple datasets to be &amp;quot;joined&amp;quot; by creating a new outer dimension for the aggregated variable&lt;br /&gt;
*** Aggregation member datasets can be listed explicitly with explicit coordinates for the new dimension for each member&lt;br /&gt;
*** Scan: Aggregations can be specified &amp;quot;automatically&amp;quot; by scanning a directory for files matching certain criteria, such as a suffix or regular expression.&lt;br /&gt;
*** Metadata may be added to the new coordinate variable for the new dimension&lt;br /&gt;
** Union Aggregation ([[NCML_Module_Aggregation_Union]])&lt;br /&gt;
*** Merges all member datasets into one by taking the first named instance of variables and metadata from the members&lt;br /&gt;
*** Useful for combining two or more datasets with different variables into a single set&lt;br /&gt;
&lt;br /&gt;
== Installation from Source ==&lt;br /&gt;
For information on how to build and install the NcML Data Module, please see the INSTALL file that came with the source distribution.&lt;br /&gt;
&lt;br /&gt;
= Installation Overview =&lt;br /&gt;
&lt;br /&gt;
The NcML Module requires a working Hyrax 1.6 installation.  It is a module&lt;br /&gt;
that is dynamically loaded into the Hyrax BES (Back End Server) to&lt;br /&gt;
allow it to handle NcML files.  &lt;br /&gt;
&lt;br /&gt;
Please see the file INSTALL for full build and install instructions as&lt;br /&gt;
well as requirements.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; After installation, you MUST restart Hyrax by restarting the BES and&lt;br /&gt;
OLFS so the NcML Module is loaded!&lt;br /&gt;
&lt;br /&gt;
== Requirement: International Components for Unicode (ICU) Library == &lt;br /&gt;
&lt;br /&gt;
The most important external requirement is an installation of the International Components for Unicode (ICU) version 3.6 or higher (tested up to 4.2.1).   The source distributions (as well as some binaries) may be found at the site: http://site.icu-project.org/download&lt;br /&gt;
&lt;br /&gt;
If you are using Linux RPM&#039;s to run Hyrax, you can get an RPM for ICU as well.  Search for the RPM named &amp;quot;libicu&amp;quot; using a package manager or yum, e.g.   If you are compiling the module from source, you will also need the RPM &amp;quot;libicu-devel&amp;quot; to get the headers installed.  &lt;br /&gt;
&lt;br /&gt;
If you install in the default locations, the ncml_module should find the libraries and headers.  Otherwise, please consult the INSTALL file for more information about installing ICU to a non-standard location.&lt;br /&gt;
&lt;br /&gt;
== Testing Installation ==&lt;br /&gt;
&lt;br /&gt;
Test data is provided to see if the installation was successful.  The file sample_virtual_dataset.ncml is a dataset purely created in NcML and doesn&#039;t contain an underlying dataset.  &lt;br /&gt;
You may also view fnoc1_improved.ncml to test adding attributes to an existing netCDF dataset (fnoc1.nc), but this requires the netCDF data handler to be&lt;br /&gt;
installed first!  Several other examples installed also use the HDF4 and HDF5 handlers.&lt;br /&gt;
&lt;br /&gt;
= Functionality =&lt;br /&gt;
&lt;br /&gt;
This version of the NcML Module implements a subset of NcML 2.2&lt;br /&gt;
functionality.  The reader is directed to http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/ for more information on NcML.&lt;br /&gt;
&lt;br /&gt;
Our module can currently:&lt;br /&gt;
&lt;br /&gt;
*Refer only to files being served locally (not remotely)&lt;br /&gt;
*Add, modify, and remove attribute metadata to a dataset&lt;br /&gt;
*Create a purely virtual dataset using just NcML and no underlying dataset&lt;br /&gt;
*Create new scalar variables of any simple NcML type or simple DAP type&lt;br /&gt;
*Create new Structure variables (which can contain new child variables)&lt;br /&gt;
*Create new N-dimensional arrays of simple types (NcML or DAP)&lt;br /&gt;
*Remove existing variables from a wrapped dataset&lt;br /&gt;
*Rename existing variables in a wrapped dataset&lt;br /&gt;
*Name dimensions as a mnemonic for specifying Array shapes&lt;br /&gt;
*Perform union aggregations on multiple datasets, virtual or wrapped or both&lt;br /&gt;
*Perform joinNew aggregations to merge a variable across multiple datasets by creating a new outer dimension&lt;br /&gt;
*Specify aggregation member datasets by scanning directories for files matching certain criteria&lt;br /&gt;
&lt;br /&gt;
We describe each supported NcML element in detail below.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;netcdf&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;netcdf&amp;gt; element is used to define a dataset, either a wrapped dataset that is to be modified, a pure virtual dataset, or a member dataset of an aggregation.  The &amp;lt;netcdf&amp;gt; element is assumed to be the topmost node, or as a child of an aggregation element.&lt;br /&gt;
&lt;br /&gt;
=== Local vs. Remote Datasets ===&lt;br /&gt;
&lt;br /&gt;
We assume that the location attribute (&#039;&#039;netcdf@location&#039;&#039;) refers to the full path (with respect to the BES data root directory) of a &#039;&#039;&#039;&#039;&#039;local&#039;&#039;&#039;&#039;&#039; dataset (served by the same Hyrax server).  The current version of the module cannot be used to modify remote datasets.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;netcdf@location&#039;&#039; is the empty string (or unspecified, as empty is the default), the dataset is a pure virtual dataset, fully specified within the NcML file itself.  Attributes and variables may be fully described and accessed with constraints just as normal datasets in this manner.  The installed sample datafile &amp;quot;sample_virtual_dataset.ncml&amp;quot; is an example test case for this functionality.&lt;br /&gt;
&lt;br /&gt;
=== Unsupported Attributes ===&lt;br /&gt;
&lt;br /&gt;
The current version does not support the following attributes of &amp;lt;netcdf&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
*enhance&lt;br /&gt;
*addRecords&lt;br /&gt;
*fmrcDefinition (will be supported when FMRC aggregation is added)&lt;br /&gt;
*ncoords (will be supported when joinExisting is added)&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;readMetadata&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;readMetadata/&amp;gt; element is the default, so is effectively not needed.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;explicit&amp;gt; element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;explicit/&amp;gt; element simply clears all attribute tables in the referred to netcdf@location before applying the rest of the &lt;br /&gt;
NcML transformations to the metadata.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;dimension&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;dimension&amp;gt; element has limited functionality in this release since the DAP2 doesn&#039;t support dimensions as more than mnemonics at this time.  The limitations are:&lt;br /&gt;
&lt;br /&gt;
* We only parse the &#039;&#039;dimension@name&#039;&#039; and &#039;&#039;dimension@length&#039;&#039; attributes.  &lt;br /&gt;
* Dimensions can only be specified as a direct child of a &amp;lt;netcdf&amp;gt; element prior to any reference to them&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt; &lt;br /&gt;
  &amp;lt;dimension name=&amp;quot;station&amp;quot; length=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;dimension name=&amp;quot;samples&amp;quot; length=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;!-- Some variable elements refer to the dimensions here --&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The dimension element sets up a mapping from the &#039;&#039;name&#039;&#039; to the unsigned integer &#039;&#039;length&#039;&#039; and can be used in a &#039;&#039;variable@shape&#039;&#039; to specify a length for an array dimension (see the section on &amp;lt;variable&amp;gt; below).  The dimension map is cleared when &amp;lt;/netcdf&amp;gt; is encountered (though this doesn&#039;t matter currently since we allow only one right now, but it will matter for aggregation, potentially).  We also do not support &amp;lt;group&amp;gt;, which is the only other legal place in NcML 2.2 for a dimension element.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* If the name and length are not both specified.&lt;br /&gt;
* If the dimension name already exists in the current scope&lt;br /&gt;
* If the length is not an unsigned integer&lt;br /&gt;
* If any of the other attributes specified in NcML 2.2 are used.  We do not handle them, so we consider them errors now.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;variable&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;variable&amp;gt; element is used to:&lt;br /&gt;
&lt;br /&gt;
* Provide lexical scope for a contained &amp;lt;attribute&amp;gt; or &amp;lt;variable&amp;gt; element&lt;br /&gt;
* Rename existing variables &lt;br /&gt;
* Add new scalar variables of simple types&lt;br /&gt;
* Add new Structure variables&lt;br /&gt;
* Add new N-dimensional Array&#039;s of simple types&lt;br /&gt;
* Specify the coordinate variable for the new dimension in a joinNew aggregation &lt;br /&gt;
&lt;br /&gt;
We describe each in turn in more detail.&lt;br /&gt;
&lt;br /&gt;
=== Specifying Lexical Scope with &amp;lt;variable type=&amp;quot;&amp;quot;&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Consider the following example:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;variable name=&amp;quot;u&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Metadata&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;This is metadata!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code assumes that a variable named &amp;quot;u&amp;quot; exists (of any type since we do not specify) and provides the lexical scope for the&lt;br /&gt;
attribute &amp;quot;Metadata&amp;quot; which will be added or modified within the attribute table for the variable &amp;quot;u&amp;quot; (it&#039;s qualified name would be &amp;quot;u.Metadata&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
==== Nested DAP Structure and Grid Scopes ====&lt;br /&gt;
&lt;br /&gt;
Scoping variable elements may be nested if the containing variable is a Structure (this includes the special case of Grid)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;DATA_GRANULE&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;PlanetaryGrid&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;variable name=&amp;quot;percipitate&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;inches&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This adds a &amp;quot;unit&amp;quot; attribute to the variable &amp;quot;percipitate&amp;quot; within the nested Structure&#039;s &lt;br /&gt;
(&amp;quot;DATA_GRANULE.PlanetaryGrid.percipitate&amp;quot; as fully qualified name).  &lt;br /&gt;
Note that we &#039;&#039;&#039;must&#039;&#039;&#039; refer to the type explicitly as a &amp;quot;Structure&amp;quot; so the parser knows&lt;br /&gt;
to traverse the tree.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; the variable might be of type Grid, but the type &amp;quot;Structure&amp;quot; must be used in the NcML to traverse it.&lt;br /&gt;
&lt;br /&gt;
==== Adding Multiple Attributes to the Same Variable ====&lt;br /&gt;
&lt;br /&gt;
Once the variable&#039;s scope is set by the opening &amp;lt;variable&amp;gt; element, more than one attribute can be specified within it.  This will make the NcML more readable and also will make the parsing more efficient since the variable will only need to be looked up once.&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_1&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Hello&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_2&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;World!&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
should be preferred over:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_1&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Hello&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_2&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;World!&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
although they produce the same result.  Any number of attributes can be specified before the variable is closed.&lt;br /&gt;
&lt;br /&gt;
=== Renaming Existing Variables ===&lt;br /&gt;
&lt;br /&gt;
The attribute &#039;&#039;variable@orgName&#039;&#039; is used to rename an existing variable. &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;NewName&amp;quot; orgName=&amp;quot;OldName&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing variable at the current scope named &amp;quot;OldName&amp;quot; to &amp;quot;NewName&amp;quot;.  After this point in the NcML file (such as in constraints specified for the DAP request), the variable is known by &amp;quot;NewName&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note that the type is not required here --- the variable is assumed to exist and its existing type is used.  It is not possible to change the type of an existing variable at this time!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:  &lt;br /&gt;
* If a variable with &#039;&#039;variable@orgName&#039;&#039; doesn&#039;t exist in the current scope&lt;br /&gt;
* If the new name &#039;&#039;variable@name&#039;&#039; is already taken in the current scope&lt;br /&gt;
* If a new variable is created but does not have exactly one values element&lt;br /&gt;
&lt;br /&gt;
=== Adding a New Scalar Variable ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;variable&amp;gt; element can be used to create a new scalar variable of a simple type (i.e. an atomic NcML type such as &amp;quot;int&amp;quot; or &amp;quot;float&amp;quot;, or any DAP atomic type, such as &amp;quot;UInt32&amp;quot; or &amp;quot;URL&amp;quot;) by specifying an empty &#039;&#039;variable@shape&#039;&#039; (which is the default), a simple type for &#039;&#039;variable@type&#039;&#039;, and a contained &amp;lt;values&amp;gt; element with the one value of correct type. &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;TheAnswerToLifeTheUniverseAndEverything&amp;quot; type=&amp;quot;double&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;SolvedBy&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;Deep Thought&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;values&amp;gt;42.000&amp;lt;/values&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create a new variable named &amp;quot;TheAnswerToLifeTheUniverseAndEverything&amp;quot; at the current scope.  It has no shape so will be a scalar of type &amp;quot;double&amp;quot; and will have the value 42.0.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* It is a parse error to not specify a &amp;lt;values&amp;gt; element with exactly one proper value of the variable type.&lt;br /&gt;
* It is a parse error to specify a malformed or out of bounds value for the data type&lt;br /&gt;
&lt;br /&gt;
=== Adding a New Structure Variable ===&lt;br /&gt;
&lt;br /&gt;
A new Structure variable can be specified at the global scope or within another Structure.  It is illegal for an array to have type structure, so the shape must be empty.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;MyNewStructure&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;MetaData&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;This is metadata!&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;ContainedScalar1&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&amp;lt;values&amp;gt;I live in a new structure!&amp;lt;/values&amp;gt;&amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;ContainedInt1&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;&amp;lt;values&amp;gt;42&amp;lt;/values&amp;gt;&amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
specifies a new structure called &amp;quot;MyNewStructure&amp;quot; which contains two scalar variable fields &amp;quot;ContainedScalar1&amp;quot; and &amp;quot;ContainedInt1&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
Nested structures are allowed as well.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Error&#039;&#039;&#039;: &lt;br /&gt;
* If another variable or attribute exists at the current scope with the new name.  &lt;br /&gt;
* If a &amp;lt;values&amp;gt; element is specified as a direct child of a new Structure --- structures cannot contain values, only attributes and other variables.&lt;br /&gt;
&lt;br /&gt;
=== Adding a New N-dimensional Array ===&lt;br /&gt;
&lt;br /&gt;
An N-dimensional array of a simple type may be created virtually as well by specifying a non-empty &#039;&#039;variable@shape&#039;&#039;.  The shape contains the array dimensions in left-to-right order of slowest varying dimension first.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;FloatArray&amp;quot; type=&amp;quot;float&amp;quot; shape=&amp;quot;2 5&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;!-- values specified in row major order (leftmost dimension in shape varies slowest) &lt;br /&gt;
	Any whitespace is a valid separator by default, so we can use newlines to pretty print 2D matrices.&lt;br /&gt;
	--&amp;gt;&lt;br /&gt;
      &amp;lt;values&amp;gt;&lt;br /&gt;
	0.1 0.2 0.3 0.4 0.5&lt;br /&gt;
	1.1 1.1 1.3 1.4 1.5&lt;br /&gt;
      &amp;lt;/values&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will specify a 2x5 dimension array of float values called &amp;quot;FloatArray&amp;quot;.  The &amp;lt;values&amp;gt; element must contain 2x5=10 values in row major order (slowest varying dimension first).  Since whitespace is the default separator, we use a newline to show the dimension boundary for the values, which is easy to see for a 2D matrix such as this.&lt;br /&gt;
&lt;br /&gt;
A dimension name may also be used to refer mnemonically to a length.  The DAP response will use this mnemonic in its output, but it is not currently used for shared dimensions, only as a mnemonic.   See the section on the &amp;lt;dimension&amp;gt; element for more information.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt;&lt;br /&gt;
 &amp;lt;dimension name=&amp;quot;station&amp;quot; length=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;dimension name=&amp;quot;sample&amp;quot; length=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;FloatArray&amp;quot; type=&amp;quot;float&amp;quot; shape=&amp;quot;station sample&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;values&amp;gt;&lt;br /&gt;
	0.1 0.2 0.3 0.4 0.5&lt;br /&gt;
	1.1 1.1 1.3 1.4 1.5&lt;br /&gt;
      &amp;lt;/values&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will produce the same 2x5 array, but will incorporate the dimension mnemonics into the response.  For example, here&#039;s the DDS response:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
     Float32 FloatArray[station = 2][samples = 5];&lt;br /&gt;
} sample_virtual_dataset.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;values&amp;gt; element respects the &#039;&#039;values@separator&#039;&#039; attribute if whitespace isn&#039;t correct.  This is very useful for arrays of strings with whitespace, for example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;StringArray&amp;quot; type=&amp;quot;string&amp;quot; shape=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;values separator=&amp;quot;*&amp;quot;&amp;gt;String 1*String 2*String 3&amp;lt;/values&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
creates a length 3 array of string StringArray = {&amp;quot;String 1&amp;quot;, &amp;quot;String 2&amp;quot;, &amp;quot;String 3&amp;quot;}.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:  &lt;br /&gt;
* It is an error to specify the incorrect number of values&lt;br /&gt;
* It is an error if any value is malformed or out of range for the data type.&lt;br /&gt;
* It is an error to specify a named dimension which does not exist in the current &amp;lt;netcdf&amp;gt; scope.&lt;br /&gt;
* It is an error to specify an Array whose flattened size (product of dimensions) is &amp;gt; 2^31-1.&lt;br /&gt;
&lt;br /&gt;
=== Specifying the new coordinate variable for a joinNew aggregation ===&lt;br /&gt;
&lt;br /&gt;
In the special case of a joinNew aggregation, the new coordinate variable may be specified with the &amp;lt;variable&amp;gt; element.  The new coordinate variable is &#039;&#039;defined&#039;&#039; to have the same name as the new dimension.  This allows for several things:&lt;br /&gt;
&lt;br /&gt;
*Explicit specification of the variable type and coordinates for the new dimension&lt;br /&gt;
*Specification of the metadata for the new coordinate variable &lt;br /&gt;
&lt;br /&gt;
In the first case, the author can specify explicitly the type of the new coordinate variable and the actual values for each dataset.  In this case, the variable &#039;&#039;must&#039;&#039; be specified &#039;&#039;after&#039;&#039; the aggregation element in the file so the new dimension&#039;s size (number of member datasets) may be known and error checking performed.  Metadata can also be added to the variable here.&lt;br /&gt;
&lt;br /&gt;
In the second case, the author may just specify the variable name, which allows one to specify the metadata for a coordinate variable that is automatically generated by the aggregation itself.  This is the only allowable case for a variable element to &#039;&#039;not&#039;&#039; contain a values element!  Coordinate variables are generated automatically in two cases:&lt;br /&gt;
&lt;br /&gt;
*The author has specified an explicit list of member datasets, with or without explicit coordVal attributes.  &lt;br /&gt;
*The author has used a &amp;lt;scan&amp;gt; element to specify the member datasets via a directory scan&lt;br /&gt;
&lt;br /&gt;
In this case, the &amp;lt;variable&amp;gt; element may come before or after the &amp;lt;aggregation&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*If an explicit variable is declared for the new coordinate variable:&lt;br /&gt;
** And it contains explicit values, the number of values must be equal to the number of member datasets in the aggregation.&lt;br /&gt;
** It must be specifed &#039;&#039;after&#039;&#039; the &amp;lt;aggregation&amp;gt; element&lt;br /&gt;
&lt;br /&gt;
* If a numeric coordVal is used to specify the first member dataset&#039;s coordinate, then &#039;&#039;all&#039;&#039; datasets must contain a numerical coordinate.&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variable (variableAgg) is not found in &#039;&#039;all&#039;&#039; member datasets.&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variable is not of the same type in &#039;&#039;all&#039;&#039; member datasets.  Coercion is &#039;&#039;not&#039;&#039; performed!&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variables in all member datasets do not have the same shape&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if an explicit coordinate variable is specified with a shape that is &#039;&#039;not&#039;&#039; the same as the new dimension name (and the variable name itself).&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;values&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;values&amp;gt; element can only be used in the context of a &#039;&#039;&#039;new&#039;&#039;&#039; variable of scalar or array type.  We cannot change the values for existing variables in this version of the handler. &lt;br /&gt;
The characters content of a &amp;lt;values&amp;gt; element is considered to be a separated list of value tokens valid for the type of the variable of the parent element.  The number of specified tokens in the content &#039;&#039;must&#039;&#039; equal the product of the dimensions of the enclosing &#039;&#039;variable@shape&#039;&#039;, or be one value for a scalar.  It is an error to &#039;&#039;not&#039;&#039; specify a &amp;lt;values&amp;gt; element for a declared new variable as well.  &lt;br /&gt;
&lt;br /&gt;
=== Changing the Separator Tokens === &lt;br /&gt;
&lt;br /&gt;
The author may specify values@separator to change the default value token separator from the default whitespace.  This is very useful for specifying arrays of strings with whitespace in them, or if data in CSV form is being pasted in.  &lt;br /&gt;
&lt;br /&gt;
=== Autogeneration of Uniform Arrays ===&lt;br /&gt;
&lt;br /&gt;
We also can parse &#039;&#039;values@start&#039;&#039; and &#039;&#039;values@increment&#039;&#039; INSTEAD OF tokens in the content.  This will &amp;quot;autogenerate&amp;quot; a uniform array of values of the given product of dimensions length for the containing variable.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Evens&amp;quot; type=&amp;quot;int&amp;quot; shape=&amp;quot;100&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;values start=&amp;quot;0&amp;quot; increment=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will specify an array of the first 100 even numbers (including 0).  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* If the incorrect number of tokens are specified for the containing variable&#039;s shape&lt;br /&gt;
* If any value token cannot be parsed as a valid value for the containing variable&#039;s type&lt;br /&gt;
* If content is specified in addition to start and increment&lt;br /&gt;
* If only one of start or increment is specified&lt;br /&gt;
* If the values element is placed anywhere except within a NEW variable.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;attribute&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
As an overview, whenever the parser encounters an &amp;lt;attribute&amp;gt; with a non-existing name (at the current scope),&lt;br /&gt;
it creates a new one, whether a container or atomic attribute (see below).  If the attribute exists,&lt;br /&gt;
its value and/or type is modified to those specified in the &amp;lt;attribute&amp;gt; element.  If an attribute&lt;br /&gt;
structure (container) exists, it is used to define a nested lexical scope for child attributes.  &lt;br /&gt;
&lt;br /&gt;
Attributes may be scalar (one value) or one dimensional arrays.  Arrays are specified by using whitespace (default) to separate the different values.  The attribute@separator may also be set in order to specify a different separator, such as CSV format or to specify a non-whitespace separator so strings with whitespace are not tokenized.  We will give examples of creating array attributes below.&lt;br /&gt;
&lt;br /&gt;
=== Adding New Attributes or Modifying an Existing Attribute ===&lt;br /&gt;
&lt;br /&gt;
If a specified attribute with the attribute@name does not exist at the current lexical scope, &lt;br /&gt;
a new one is created with the given type and value.  For example, assume &amp;quot;new_metadata&amp;quot; doesn&#039;t&lt;br /&gt;
exist at the current parse scope.  Then:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;new_metadata&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;This is a new entry!&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create the attribute at that scope.  Note that value can be specified in the content of the &lt;br /&gt;
element as well.  This is identical to the above:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;new_metadata&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;This is a new entry!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the attribute@name already exists at the scope, it is modified to contain the specified type and value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Arrays ====&lt;br /&gt;
&lt;br /&gt;
As in NcML, for numerical types an array can be specified by separating the tokens by whitespace (default) or be&lt;br /&gt;
specifying the token separator with attribute@separator.  For example,&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;myArray&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 2 3&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;myArray&amp;quot; type=&amp;quot;int&amp;quot; separator=&amp;quot;,&amp;quot;&amp;gt;1,2,3&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
both specify the same array of three integers named &amp;quot;myArray&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
TODO Add more information on splitting with a separator!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Structures (Containers) ====&lt;br /&gt;
&lt;br /&gt;
We use attribute@type=&amp;quot;Structure&amp;quot; to define a new (or existing) attribute container.   So if we&lt;br /&gt;
wanted to add a new attribute structure, we&#039;d use something like this: &lt;br /&gt;
&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;MySamples&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Location&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Station 1&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Samples&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 4 6&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assuming &amp;quot;MySamples&amp;quot; doesn&#039;t already exist, an attribute container will be created at the current scope&lt;br /&gt;
and the &amp;quot;Location&amp;quot; and &amp;quot;Samples&amp;quot; attributes will be added to it.&lt;br /&gt;
&lt;br /&gt;
Note that we can create nested attribute structures to arbitrary depth this way as well.&lt;br /&gt;
&lt;br /&gt;
If the attribute container with the given name already exists at the current scope, &lt;br /&gt;
then the attribute@type=&amp;quot;Structure&amp;quot; form is used to define&lt;br /&gt;
the lexical scope for the container.  In other words, child &amp;lt;attribute&amp;gt; elements will&lt;br /&gt;
be processed within the scope of the container.   For example, in the above example, if&lt;br /&gt;
&amp;quot;MySamples&amp;quot; already exists, then the &amp;quot;Location&amp;quot; and &amp;quot;Samples&amp;quot; will be processed within the&lt;br /&gt;
existing container (they may or may not already exist as well).&lt;br /&gt;
&lt;br /&gt;
==== Renaming an Existing Attribute or Attribute Container ====&lt;br /&gt;
&lt;br /&gt;
We also support the attribute@orgName attribute for renaming attributes.   &lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;NewName&amp;quot; orgName=&amp;quot;OldName&amp;quot; type=&amp;quot;string&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing attribute &amp;quot;OldName&amp;quot; to &amp;quot;NewName&amp;quot; while leaving its value alone.&lt;br /&gt;
If attribute@value is also specified, then the attribute is renamed &#039;&#039;and&#039;&#039; has its value modified.&lt;br /&gt;
&lt;br /&gt;
This works for renaming attribute containers as well:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;MyNewContainer&amp;quot; orgName=&amp;quot;MyOldContainer&amp;quot; type=&amp;quot;Structure&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing &amp;quot;MyOldContainer&amp;quot; to &amp;quot;MyNewContainer&amp;quot;.  Note that any children&lt;br /&gt;
of this container will remain in it.&lt;br /&gt;
&lt;br /&gt;
=== DAP &#039;&#039;OtherXML&#039;&#039; Extension ===&lt;br /&gt;
&lt;br /&gt;
The module now allows specification of attributes of the new DAP type &amp;quot;OtherXML&amp;quot;.  This allows the NCML file author to inject arbitrary well-formed XML into an attribute for clients that want XML metadata rather than just string or url.  Internally, the attribute is still a string (and in a DAP DAS response will be quoted inside one string).  However, since it is XML, the NCMLParser still parses it and checks it for well-formedness (but NOT against schemas).  This extension allows the NCMLParser to parse the arbitrary XML within the given attribute without causing errors, since it can be any XML.  &lt;br /&gt;
&lt;br /&gt;
The injected XML is most useful in the DDX response, where it shows up directly in the response as XML.  XSLT and other clients can then parse it.&lt;br /&gt;
&lt;br /&gt;
==== Errors ====&lt;br /&gt;
&lt;br /&gt;
*The XML &#039;&#039;&#039;must&#039;&#039;&#039; be in the content of the &amp;lt;attribute type=&amp;quot;OtherXML&amp;quot;&amp;gt; element.  It is a parser error for &#039;&#039;attribute@value&#039;&#039; to be set if &#039;&#039;attribute@type&#039;&#039; is &amp;quot;OtherXML&amp;quot;.  &lt;br /&gt;
*The XML must also be well-formed since it is parsed.  A parse error will be thrown if the OtherXML is malformed.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of the use of this special case.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf xmlns=&amp;quot;http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2&amp;quot; location=&amp;quot;/coverage/200803061600_HFRadar_USEGC_6km_rtv_SIO.nc&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;someName&amp;quot; type=&amp;quot;OtherXML&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;Domain xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot; &lt;br /&gt;
                xmlns:ows=&amp;quot;http://www.opengis.net/ows/1.1&amp;quot;&lt;br /&gt;
                xmlns:gml=&amp;quot;http://www.opengis.net/gml/3.2&amp;quot;&lt;br /&gt;
                &amp;gt;&lt;br /&gt;
            &amp;lt;SpatialDomain&amp;gt;&lt;br /&gt;
                &amp;lt;ows:BoundingBox crs=&amp;quot;urn:ogc:def:crs:EPSG::4326&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;ows:LowerCorner&amp;gt;-97.8839 21.736&amp;lt;/ows:LowerCorner&amp;gt;&lt;br /&gt;
                    &amp;lt;ows:UpperCorner&amp;gt;-57.2312 46.4944&amp;lt;/ows:UpperCorner&amp;gt;&lt;br /&gt;
                &amp;lt;/ows:BoundingBox&amp;gt;&lt;br /&gt;
            &amp;lt;/SpatialDomain&amp;gt;&lt;br /&gt;
            &amp;lt;TemporalDomain&amp;gt;&lt;br /&gt;
                &amp;lt;gml:timePosition&amp;gt;2008-03-27T16:00:00.000Z&amp;lt;/gml:timePosition&amp;gt;&lt;br /&gt;
            &amp;lt;/TemporalDomain&amp;gt;&lt;br /&gt;
        &amp;lt;/Domain&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedCRS xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;urn:ogc:def:crs:EPSG::4326&amp;lt;/SupportedCRS&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedFormat xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;netcdf-cf1.0&amp;lt;/SupportedFormat&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedFormat xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;dap2.0&amp;lt;/SupportedFormat&amp;gt;&lt;br /&gt;
    &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039; Put the DDX response for the above in here!&lt;br /&gt;
&lt;br /&gt;
====Namespace Closure====&lt;br /&gt;
&lt;br /&gt;
Furthermore, the parser will make the chunk of OtherXML &amp;quot;namespace closed&amp;quot;.  This means any namespaces specified in parent NCML elements of the OtherXML tree will be &amp;quot;brought down&amp;quot; and added to the &#039;&#039;root&#039;&#039; OtherXML elements so that the subtree may be pulled out and added to the DDX and still have its namespaces.  The algorithm doesn&#039;t just bring used prefixes, but brings &#039;&#039;all&#039;&#039; of the lexically scoped closest namespaces in all ancestors.  In other words, it adds unique namespaces (as determined by prefix) in order from the root of the OtherXML tree as it traverses to the root of the NCML document.  &lt;br /&gt;
&lt;br /&gt;
Namespace closure is a syntactic sugar that simplifies the author&#039;s task since they can specify the namespaces just once at the top of the NCML file and expect that when the subtree of XML is added to the DDX that these namespaces will come along with that subtree of XML.  Otherwise they have to explicitly add the namespaces to each attributes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039; Add an example!&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;remove&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;remove&amp;gt; element can remove attributes and variables.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;attribute name=&amp;quot;NC_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;remove name=&amp;quot;base_time&amp;quot; type=&amp;quot;attribute&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will remove the attribute named &amp;quot;base_time&amp;quot; in the attribute structure named &amp;quot;NC_GLOBAL&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Note that this works for attribute containers as well!  We could recursively remove the &#039;&#039;entire&#039;&#039;&lt;br /&gt;
attribute container (i.e. it and all its children) with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;remove name=&amp;quot;NC_GLOBAL&amp;quot; type=&amp;quot;attribute&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It also can be used to remove variables from existing datasets:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
  &amp;lt;remove name=&amp;quot;SomeExistingVariable&amp;quot; type=&amp;quot;variable&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This also recurses on variables of type Structure --- the entire structure including all of its children are removed from the dataset&#039;s response.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* It is a parse error if the given attribute or variable doesn&#039;t exist in the current scope&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;aggregation&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
Aggregation involves combining multiple datasets (&amp;lt;netcdf&amp;gt;) into a virtual &amp;quot;single&amp;quot; dataset in various ways.  For a tutorial on aggregation in NcML 2.2, the reader is referred to the Unidata page: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Aggregation.html&lt;br /&gt;
&lt;br /&gt;
NcML 2.2 supports multiple types of aggregation: union, joinNew, joinExisting, and fmrc (forecast model run collection).  &lt;br /&gt;
&lt;br /&gt;
The current version of the NcML module supports two of these aggregations:&lt;br /&gt;
&lt;br /&gt;
*Union [[NCML_Module_Aggregation_Union]]&lt;br /&gt;
*JoinNew [[NCML_Module_Aggregation_JoinNew]]&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;union&#039;&#039; aggregation specifies that the first instance of a variable or attribute (by name) that is found in the ordered list of datasets will be the one in the output aggregation.   This is useful for combining two dataset files, each which may contain a single variable, into a composite dataset with both variables.&lt;br /&gt;
&lt;br /&gt;
A JoinNew aggregation joins a variable which exists in multiple datasets (usually samples of a datum over time) into a new variable containing the data from &#039;&#039;all&#039;&#039; member datasets by creating a new outer dimension.  The &#039;&#039;i&#039;&#039;th component in the new outer dimension is the variable&#039;s data from the &#039;&#039;i&#039;&#039;th member dataset.  It also adds a new coordinate variable of whose name is the new dimension&#039;s name and whose shape (length) is the new dimension as well.  This new coordinate variable may be explicitly given by the author or may be autogenerated in one of several ways.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;scan&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The scan element can be used within an aggregation context to allow a directory to be searched in various ways in order to specify the members of an aggregation.  This allows a static NcML file to refer to an aggregation which may change over time, such as where a new data file is generated each day.&lt;br /&gt;
&lt;br /&gt;
We describe usage of the &amp;lt;scan&amp;gt; element in detail in the joinNew aggregation tutorial at [[NCML_Module_Aggregation_JoinNew]].&lt;br /&gt;
&lt;br /&gt;
= Errors =&lt;br /&gt;
&lt;br /&gt;
There are three types of error messages that may be returned:&lt;br /&gt;
&lt;br /&gt;
* Internal Error&lt;br /&gt;
* Resource Not Found Error&lt;br /&gt;
* Parse Error&lt;br /&gt;
&lt;br /&gt;
== Internal Errors ==&lt;br /&gt;
&#039;&#039;&#039;Internal errors&#039;&#039;&#039; should be reported to support@opendap.org as they are likely bugs.&lt;br /&gt;
&lt;br /&gt;
== Resource Not Found Errors ==&lt;br /&gt;
&lt;br /&gt;
If the netcdf@location specifies a non-existent local dataset (one that is not being served by&lt;br /&gt;
the same Hyrax server), it will specify the resource was not found.   This may also be returned&lt;br /&gt;
if a handler for the specified dataset is not currently loaded in the BES.  Users should test that the&lt;br /&gt;
dataset to be wrapped already exists and can be viewed on the running server before writing NcML &lt;br /&gt;
to add metadata.  It&#039;s also an error to refer to remote datasets (at this time).&lt;br /&gt;
&lt;br /&gt;
== Parse Errors ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse errors&#039;&#039;&#039; are user errors in the NcML file.  These could be malformed XML, malformed NcML, &lt;br /&gt;
unimplemented features of NcML, or could be errors in referring to the wrapped dataset.  &lt;br /&gt;
&lt;br /&gt;
The error message should specify &lt;br /&gt;
the error condition as well as the &amp;quot;current scope&amp;quot; as a fully qualified DAP name within the &lt;br /&gt;
loaded dataset.  This should be enough information to correct the parse error as new NcML&lt;br /&gt;
files are created.&lt;br /&gt;
&lt;br /&gt;
The parser will generate parse errors in various &lt;br /&gt;
situations where it expects to find certain structure in the underlying dataset.  Some examples:&lt;br /&gt;
&lt;br /&gt;
* A variable of the given name was not found at the current scope&lt;br /&gt;
* attribute@orgName was specified, but the attribute cannot be found at current scope.&lt;br /&gt;
* attribute@orgName was specified, but the new name is already used at current scope.&lt;br /&gt;
* remove specified a non-existing attribute name&lt;br /&gt;
&lt;br /&gt;
= Grid Metadata Tutorial =&lt;br /&gt;
&lt;br /&gt;
Please see the page [[Grid_Metadata_Tutorial]] for an example of adding metadata to the various parts of a DAP Grid variable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Aggregation Tutorials =&lt;br /&gt;
&lt;br /&gt;
The NcML module may also be used to aggregate multiple datasets into one virtual dataset.  We currently support two of the NcML aggregtions:&lt;br /&gt;
&lt;br /&gt;
*Union [[NCML_Module_Aggregation_Union]]:  combine multiple datasets into one by merging variables together, selecting the first of each unique name.&lt;br /&gt;
*JoinNew [[NCML_Module_Aggregation_JoinNew]]: combine variables across multiple datasets by creating a new outer dimension and coordinate variable for each of the sample datasets.&lt;br /&gt;
&lt;br /&gt;
Please see the sections for a tutorial on the various uses of these aggregations.&lt;br /&gt;
&lt;br /&gt;
= Additions/Changes to NcML 2.2 =&lt;br /&gt;
&lt;br /&gt;
This section will keep track of changes to the NcML 2.2 schema.  Eventually these&lt;br /&gt;
will be rolled into a new schema.&lt;br /&gt;
&lt;br /&gt;
== Attribute Structures (Containers) ==&lt;br /&gt;
This module also adds functionality beyond the current NcML 2.2 schema&lt;br /&gt;
--- it can handle nested &amp;lt;attribute&amp;gt; elements in order to make&lt;br /&gt;
attribute structures.  This is done by using the &amp;lt;attribute&lt;br /&gt;
type=&amp;quot;Structure&amp;quot;&amp;gt; form, for example:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;MySamples&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Location&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Station 1&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Samples&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 4 6&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;MyContainer&amp;quot; describes an attribute structure with two attribute fields,&lt;br /&gt;
a string &amp;quot;Location&amp;quot; and an array of int&#039;s called &amp;quot;Samples&amp;quot;.  &lt;br /&gt;
Note that an attribute structure of this form can&lt;br /&gt;
only contain other &amp;lt;attribute&amp;gt; elements and NOT a value.&lt;br /&gt;
&lt;br /&gt;
If the container does not already exist, it will be created at the scope it is declared, which could&lt;br /&gt;
be:&lt;br /&gt;
&lt;br /&gt;
* Global (top of dataset)&lt;br /&gt;
* Within a variable&#039;s attribute table&lt;br /&gt;
* Within another attribute container&lt;br /&gt;
&lt;br /&gt;
If an attribute container of the given name already exists at the lexical scope, it is traversed &lt;br /&gt;
in order to define the scope for the nested (children) attributes it contains.&lt;br /&gt;
&lt;br /&gt;
== Unspecified Variable Type Matching for Lexical Scope ==&lt;br /&gt;
&lt;br /&gt;
We also allow the type attribute of a variable element (variable@type) to be the empty string &lt;br /&gt;
(or unspecified) when using existing variables to define the lexical scope of an &amp;lt;attribute&amp;gt; &lt;br /&gt;
transformation.  In the schema, variable@type is (normally) required.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DAP 2 Types ==&lt;br /&gt;
&lt;br /&gt;
Additionally, we allow DAP2 atomic types (such as UInt32, URL) in addition to the NcML types.  &lt;br /&gt;
The NcML types are mapped onto the closest DAP2 type internally.&lt;br /&gt;
&lt;br /&gt;
== DAP OtherXML Attribute Type ==&lt;br /&gt;
&lt;br /&gt;
We also allow attributes to be of the new DAP type &amp;quot;OtherXML&amp;quot; for injecting arbitrary XML into an attribute as content rather than trying to form a string.  This allows the parser to check well-formedness.&lt;br /&gt;
&lt;br /&gt;
== Forward Declaration of Dimensions ==&lt;br /&gt;
&lt;br /&gt;
Since we use a SAX parser for efficiency, we require the &amp;lt;dimension&amp;gt; elements to come &#039;&#039;before&#039;&#039; their use in a &#039;&#039;variable@shape&#039;&#039;.  One way to change the schema to allow this is to force the dimension elements to be specified in a sequence after explicit and metadata choice and before all other elements.&lt;br /&gt;
&lt;br /&gt;
== Aggregation Element Location and Processing Order Differences ==&lt;br /&gt;
&lt;br /&gt;
NcML specifies that if a dataset (&amp;lt;netcdf&amp;gt; element) specifies an aggregation element, the aggregation element is always processed first, regardless of its ordering within the &amp;lt;netcdf&amp;gt; element.  Our parser, since it is SAX and not DOM, modifies this behavior in that order matters in some cases:&lt;br /&gt;
&lt;br /&gt;
* Metadata (&amp;lt;attribute&amp;gt;) elements specified &#039;&#039;prior&#039;&#039; to an aggregation &amp;quot;shadow&amp;quot; the aggregation versions.  This is be useful for &amp;quot;overriding&amp;quot; an attribute or variable in a union aggregation, where the first found will take precedence. &lt;br /&gt;
* JoinNew: If the new coordinate variable&#039;s data is to be set explicitly by specifying the new dimension&#039;s shape (either with explicit data or the autogenerated data using values@start and values@increment attributes), the &amp;lt;variable&amp;gt; &#039;&#039;must&#039;&#039; come after the aggregation since the size of the dimension is unknown until the aggregation element is processed.&lt;br /&gt;
&lt;br /&gt;
= Backward Compatibility Issues =&lt;br /&gt;
&lt;br /&gt;
Due to the way shared dimensions were implemented in the NetCDF, HDF4, and HDF5 handlers, the DAS responses did not follow the DAP2 specification.  The NcML module, on the other hand, generates DAP2 compliant DAS for these datasets, which means that wrapping some datasets in NcML will generate a DAS with a different structure.  This is important for the NcML author since it changes the names of attributes and variables.  In order for the module to find the correct scope for adding metadata, for example, the DAP2 DAS must be used.  &lt;br /&gt;
&lt;br /&gt;
In general, what this means is that an empty &amp;quot;passthrough&amp;quot; NcML file should be the starting point for authoring an NcML file.  This file would just specify a dataset and nothing else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;/data/ncml/myNetcdf.nc&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The author would then request the DAS response for the NCML file and use that as the starting point for modifications to the original dataset. &lt;br /&gt;
&lt;br /&gt;
More explicit examples are given below.&lt;br /&gt;
&lt;br /&gt;
== NetCDF ==&lt;br /&gt;
&lt;br /&gt;
The NetCDF handler represents some NC datasets as a DAP 2 Grid, but the returned DAS is not consistent with the DAP 2 spec for the attribute hierarchy for such a Grid.  The map vector attributes are placed as siblings of the grid attributes rather than within the grid lexical scope.  For example, here&#039;s the NetCDF Handler DDS for a given file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Int16 cldc[time = 456][lat = 21][lon = 360];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 456];&lt;br /&gt;
        Float32 lat[lat = 21];&lt;br /&gt;
        Float32 lon[lon = 360];&lt;br /&gt;
    } cldc;&lt;br /&gt;
} cldc.mean.nc;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
showing the Grid.  Here&#039;s the DAS the NetCDF handler generates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    lat {&lt;br /&gt;
        String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
        String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
        Float32 actual_range 10.00000000, -10.00000000;&lt;br /&gt;
    }&lt;br /&gt;
    lon {&lt;br /&gt;
        String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
        String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
        Float32 actual_range 0.5000000000, 359.5000000;&lt;br /&gt;
    }&lt;br /&gt;
    time {&lt;br /&gt;
        String units &amp;quot;days since 1-1-1 00:00:0.0&amp;quot;;&lt;br /&gt;
        String long_name &amp;quot;Time&amp;quot;;&lt;br /&gt;
        String delta_t &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
        String avg_period &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
        Float64 actual_range 715511.00000000000, 729360.00000000000;&lt;br /&gt;
    }&lt;br /&gt;
    cldc {&lt;br /&gt;
        Float32 valid_range 0.000000000, 8.000000000;&lt;br /&gt;
        Float32 actual_range 0.000000000, 8.000000000;&lt;br /&gt;
        String units &amp;quot;okta&amp;quot;;&lt;br /&gt;
        Int16 precision 1;&lt;br /&gt;
        Int16 missing_value 32766;&lt;br /&gt;
        Int16 _FillValue 32766;&lt;br /&gt;
        String long_name &amp;quot;Cloudiness Monthly Mean at Surface&amp;quot;;&lt;br /&gt;
        String dataset &amp;quot;COADS 1-degree Equatorial Enhanced\\012AI&amp;quot;;&lt;br /&gt;
        String var_desc &amp;quot;Cloudiness\\012C&amp;quot;;&lt;br /&gt;
        String level_desc &amp;quot;Surface\\0120&amp;quot;;&lt;br /&gt;
        String statistic &amp;quot;Mean\\012M&amp;quot;;&lt;br /&gt;
        String parent_stat &amp;quot;Individual Obs\\012I&amp;quot;;&lt;br /&gt;
        Float32 add_offset 3276.500000;&lt;br /&gt;
        Float32 scale_factor 0.1000000015;&lt;br /&gt;
    }&lt;br /&gt;
    NC_GLOBAL {&lt;br /&gt;
        String title &amp;quot;COADS 1-degree Equatorial Enhanced&amp;quot;;&lt;br /&gt;
        String history &amp;quot;&amp;quot;;&lt;br /&gt;
        String Conventions &amp;quot;COARDS&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    DODS_EXTRA {&lt;br /&gt;
        String Unlimited_Dimension &amp;quot;time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the map vector attributes are in the &amp;quot;dataset&amp;quot; scope.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the DAS that the NcML Module produces from the correctly formed DDX:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    NC_GLOBAL {&lt;br /&gt;
        String title &amp;quot;COADS 1-degree Equatorial Enhanced&amp;quot;;&lt;br /&gt;
        String history &amp;quot;&amp;quot;;&lt;br /&gt;
        String Conventions &amp;quot;COARDS&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    DODS_EXTRA {&lt;br /&gt;
        String Unlimited_Dimension &amp;quot;time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    cldc {&lt;br /&gt;
        Float32 valid_range 0.000000000, 8.000000000;&lt;br /&gt;
        Float32 actual_range 0.000000000, 8.000000000;&lt;br /&gt;
        String units &amp;quot;okta&amp;quot;;&lt;br /&gt;
        Int16 precision 1;&lt;br /&gt;
        Int16 missing_value 32766;&lt;br /&gt;
        Int16 _FillValue 32766;&lt;br /&gt;
        String long_name &amp;quot;Cloudiness Monthly Mean at Surface&amp;quot;;&lt;br /&gt;
        String dataset &amp;quot;COADS 1-degree Equatorial Enhanced\\012AI&amp;quot;;&lt;br /&gt;
        String var_desc &amp;quot;Cloudiness\\012C&amp;quot;;&lt;br /&gt;
        String level_desc &amp;quot;Surface\\0120&amp;quot;;&lt;br /&gt;
        String statistic &amp;quot;Mean\\012M&amp;quot;;&lt;br /&gt;
        String parent_stat &amp;quot;Individual Obs\\012I&amp;quot;;&lt;br /&gt;
        Float32 add_offset 3276.500000;&lt;br /&gt;
        Float32 scale_factor 0.1000000015;&lt;br /&gt;
        cldc {&lt;br /&gt;
        }&lt;br /&gt;
        time {&lt;br /&gt;
            String units &amp;quot;days since 1-1-1 00:00:0.0&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;Time&amp;quot;;&lt;br /&gt;
            String delta_t &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
            String avg_period &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
            Float64 actual_range 715511.00000000000, 729360.00000000000;&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
            Float32 actual_range 10.00000000, -10.00000000;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
            Float32 actual_range 0.5000000000, 359.5000000;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here the Grid Structure &amp;quot;cldc&amp;quot;  and its contained data array (of the same name &amp;quot;cldc&amp;quot;) and map vectors have their own attribute containers as DAP 2 specifies.&lt;br /&gt;
&lt;br /&gt;
What this means for the author of an NcML file adding metadata to a NetCDF dataset that returns a Grid is that they should generate a &amp;quot;passthrough&amp;quot; file and get the DAS and then specify modifications based on that structure.  &lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example passthrough:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/cldc.mean.nc&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For example, to add an attribute to the map vector &amp;quot;lat&amp;quot; in the above, we&#039;d need the following NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/cldc.mean.nc&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;!-- Traverse into the Grid as a Structure --&amp;gt;&lt;br /&gt;
  &amp;lt;variable name=&amp;quot;cldc&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Traverse into the &amp;quot;lat&amp;quot; map vector (Array) --&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lat&amp;quot;&amp;gt; &lt;br /&gt;
      &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;I am a new attribute in the Grid map vector named lat!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lon&amp;quot;&amp;gt; &lt;br /&gt;
      &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;I am a new attribute in the Grid map vector named lon!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This clearly shows that the structure of the Grid must be used in the NcML:  the attribute being added is technically &amp;quot;cldc.lat.Description&amp;quot; in a fully qualified name.  The parser would return an error if it was attempted as &amp;quot;lat.Description&amp;quot; as the NetCDF DAS for the original file would have led one to believe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== HDF4/HDF5 ==&lt;br /&gt;
&lt;br /&gt;
Similarly to the NetCDF case, the Hyrax HDF4 Module produces DAS responses that do not respect the DAP2 specification.  If an NcML file is used to &amp;quot;wrap&amp;quot; an HDF4 dataset, the&lt;br /&gt;
correct DAP2 DAS response will be generated, however. &lt;br /&gt;
&lt;br /&gt;
This is important for those writing NcML for HDF4 data since the&lt;br /&gt;
lexical scope for attributes relies on the correct DAS form --- to&lt;br /&gt;
handle this, the user should start with a &amp;quot;passthrough&amp;quot; NcML file (see the above NetCDF example) and&lt;br /&gt;
use the DAS from that as the starting point for knowing the structure&lt;br /&gt;
the NcML handler expects to see in the NcML file.  Alternatively, the DDX has the &lt;br /&gt;
proper attribute structure as well (the DAS is generated from it).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Known Bugs =&lt;br /&gt;
&lt;br /&gt;
There are no known bugs currently.&lt;br /&gt;
&lt;br /&gt;
= Planned Future Enhancements =&lt;br /&gt;
&lt;br /&gt;
Planned enhancements for future versions of the module include:&lt;br /&gt;
&lt;br /&gt;
* New NcML Aggregations&lt;br /&gt;
** JoinExisting&lt;br /&gt;
*** Joins a variable across multiple datasets by appending the data for a given dimension from each dataset &lt;br /&gt;
*** Will also allow directory scans for specifying the aggregation&lt;br /&gt;
** Forecast Model Run Collection (FMRC)&lt;br /&gt;
*** Special case of JoinNew for forecast data with two time variables&lt;br /&gt;
*** See: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/FmrcAggregation.html&lt;br /&gt;
&lt;br /&gt;
= Copyright =&lt;br /&gt;
&lt;br /&gt;
This software is copyrighted under the GNU Lesser GPL.  Please see the&lt;br /&gt;
files COPYING and COPYRIGHT that came with this distribution.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=BES_-_Modules_-_NcML_Module&amp;diff=5593</id>
		<title>BES - Modules - NcML Module</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=BES_-_Modules_-_NcML_Module&amp;diff=5593"/>
		<updated>2010-04-20T19:57:25Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
[[Category:NCML]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Welcome to the OPeNDAP NcML Data Handler Module v1.0.1 for Hyrax 1.6!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[Updated for NcML Module v1.0.1 for Hyrax 1.6.0 beta --  8 April 2010]&lt;br /&gt;
&lt;br /&gt;
This module may be added to a Hyrax 1.6 server to extend its data&lt;br /&gt;
serving capability to NcML 2.2 files (see&lt;br /&gt;
http://www.unidata.ucar.edu/software/netcdf/ncml/).  NcML provides support for modifying other datasets in various ways, such as adding metadata and data and aggregating multiple datasets in several ways.&lt;br /&gt;
&lt;br /&gt;
We refer the reader to the Unidata NcML tutorial: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Tutorial.html which will give the basics of using NcML.  We then give a reference manual for the various elements and their attributes.  Additionally we have provided a more extensive tutorial on NcML aggregation.  Please see [[#Aggregation Tutorials]].&lt;br /&gt;
&lt;br /&gt;
Since the DAP Grid is a common case, we will also give a simple example for adding metadata to the various parts of a Grid dataset using NcML.  Please see [[Grid_Metadata_Tutorial]].&lt;br /&gt;
&lt;br /&gt;
==Features==         &lt;br /&gt;
   &lt;br /&gt;
This current version (v1.0.1) currently implements a subset of NcML 2.2&lt;br /&gt;
functionality, along with some OPeNDAP extensions:&lt;br /&gt;
&lt;br /&gt;
* Metadata Manipulation&lt;br /&gt;
** Addition, Removal, and Modification of attributes to other datasets (NetCDF, HDF4, HD5, etc.) served by the same Hyrax 1.6 server&lt;br /&gt;
** Extends NcML 2.2 to allow for common nested &amp;quot;attribute containers&amp;quot; &lt;br /&gt;
** Attributes can be DAP2 types as well as the NcML types &lt;br /&gt;
** Attributes can be of the special &amp;quot;OtherXML&amp;quot; type for injecting arbitrary XML into a DDX response&lt;br /&gt;
* Data Manipulation&lt;br /&gt;
** Addition of new data variables (scalars or arrays of basic types as well as structures) &lt;br /&gt;
** Variables may be removed from the wrapped dataset&lt;br /&gt;
** Allows the creation of &amp;quot;pure virtual&amp;quot; datasets which do not wrap another dataset&lt;br /&gt;
* Aggregations: JoinNew and Union [[#Aggregation Tutorials]]&lt;br /&gt;
** JoinNew Aggregation ([[NCML_Module_Aggregation_JoinNew]])&lt;br /&gt;
*** Allows multiple datasets to be &amp;quot;joined&amp;quot; by creating a new outer dimension for the aggregated variable&lt;br /&gt;
*** Aggregation member datasets can be listed explicitly with explicit coordinates for the new dimension for each member&lt;br /&gt;
*** Scan: Aggregations can be specified &amp;quot;automatically&amp;quot; by scanning a directory for files matching certain criteria, such as a suffix or regular expression.&lt;br /&gt;
*** Metadata may be added to the new coordinate variable for the new dimension&lt;br /&gt;
** Union Aggregation ([[NCML_Module_Aggregation_Union]])&lt;br /&gt;
*** Merges all member datasets into one by taking the first named instance of variables and metadata from the members&lt;br /&gt;
*** Useful for combining two or more datasets with different variables into a single set&lt;br /&gt;
&lt;br /&gt;
== Installation from Source ==&lt;br /&gt;
For information on how to build and install the NcML Data Module, please see the INSTALL file that came with the source distribution.&lt;br /&gt;
&lt;br /&gt;
= Installation Overview =&lt;br /&gt;
&lt;br /&gt;
The NcML Module requires a working Hyrax 1.6 installation.  It is a module&lt;br /&gt;
that is dynamically loaded into the Hyrax BES (Back End Server) to&lt;br /&gt;
allow it to handle NcML files.  &lt;br /&gt;
&lt;br /&gt;
Please see the file INSTALL for full build and install instructions as&lt;br /&gt;
well as requirements.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; After installation, you MUST restart Hyrax by restarting the BES and&lt;br /&gt;
OLFS so the NcML Module is loaded!&lt;br /&gt;
&lt;br /&gt;
== Requirement: International Components for Unicode (ICU) Library == &lt;br /&gt;
&lt;br /&gt;
The most important external requirement is an installation of the International Components for Unicode (ICU) version 3.6 or higher (tested up to 4.2.1).   The source distributions (as well as some binaries) may be found at the site: http://site.icu-project.org/download&lt;br /&gt;
&lt;br /&gt;
If you are using Linux RPM&#039;s to run Hyrax, you can get an RPM for ICU as well.  Search for the RPM named &amp;quot;libicu&amp;quot; using a package manager or yum, e.g.   If you are compiling the module from source, you will also need the RPM &amp;quot;libicu-devel&amp;quot; to get the headers installed.  &lt;br /&gt;
&lt;br /&gt;
If you install in the default locations, the ncml_module should find the libraries and headers.  Otherwise, please consult the INSTALL file for more information about installing ICU to a non-standard location.&lt;br /&gt;
&lt;br /&gt;
== Testing Installation ==&lt;br /&gt;
&lt;br /&gt;
Test data is provided to see if the installation was successful.  The file sample_virtual_dataset.ncml is a dataset purely created in NcML and doesn&#039;t contain an underlying dataset.  &lt;br /&gt;
You may also view fnoc1_improved.ncml to test adding attributes to an existing netCDF dataset (fnoc1.nc), but this requires the netCDF data handler to be&lt;br /&gt;
installed first!  Several other examples installed also use the HDF4 and HDF5 handlers.&lt;br /&gt;
&lt;br /&gt;
= Functionality =&lt;br /&gt;
&lt;br /&gt;
This version of the NcML Module implements a subset of NcML 2.2&lt;br /&gt;
functionality.  The reader is directed to http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/ for more information on NcML.&lt;br /&gt;
&lt;br /&gt;
Our module can currently:&lt;br /&gt;
&lt;br /&gt;
*Refer only to files being served locally (not remotely)&lt;br /&gt;
*Add, modify, and remove attribute metadata to a dataset&lt;br /&gt;
*Create a purely virtual dataset using just NcML and no underlying dataset&lt;br /&gt;
*Create new scalar variables of any simple NcML type or simple DAP type&lt;br /&gt;
*Create new Structure variables (which can contain new child variables)&lt;br /&gt;
*Create new N-dimensional arrays of simple types (NcML or DAP)&lt;br /&gt;
*Remove existing variables from a wrapped dataset&lt;br /&gt;
*Rename existing variables in a wrapped dataset&lt;br /&gt;
*Name dimensions as a mnemonic for specifying Array shapes&lt;br /&gt;
*Perform union aggregations on multiple datasets, virtual or wrapped or both&lt;br /&gt;
*Perform joinNew aggregations to merge a variable across multiple datasets by creating a new outer dimension&lt;br /&gt;
*Specify aggregation member datasets by scanning directories for files matching certain criteria&lt;br /&gt;
&lt;br /&gt;
We describe each supported NcML element in detail below.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;netcdf&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;netcdf&amp;gt; element is used to define a dataset, either a wrapped dataset that is to be modified, a pure virtual dataset, or a member dataset of an aggregation.  The &amp;lt;netcdf&amp;gt; element is assumed to be the topmost node, or as a child of an aggregation element.&lt;br /&gt;
&lt;br /&gt;
=== Local vs. Remote Datasets ===&lt;br /&gt;
&lt;br /&gt;
We assume that the location attribute (&#039;&#039;netcdf@location&#039;&#039;) refers to the full path (with respect to the BES data root directory) of a &#039;&#039;&#039;&#039;&#039;local&#039;&#039;&#039;&#039;&#039; dataset (served by the same Hyrax server).  The current version of the module cannot be used to modify remote datasets.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;netcdf@location&#039;&#039; is the empty string (or unspecified, as empty is the default), the dataset is a pure virtual dataset, fully specified within the NcML file itself.  Attributes and variables may be fully described and accessed with constraints just as normal datasets in this manner.  The installed sample datafile &amp;quot;sample_virtual_dataset.ncml&amp;quot; is an example test case for this functionality.&lt;br /&gt;
&lt;br /&gt;
=== Unsupported Attributes ===&lt;br /&gt;
&lt;br /&gt;
The current version does not support the following attributes of &amp;lt;netcdf&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
*enhance&lt;br /&gt;
*addRecords&lt;br /&gt;
*fmrcDefinition (will be supported when FMRC aggregation is added)&lt;br /&gt;
*ncoords (will be supported when joinExisting is added)&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;readMetadata&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;readMetadata/&amp;gt; element is the default, so is effectively not needed.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;explicit&amp;gt; element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;explicit/&amp;gt; element simply clears all attribute tables in the referred to netcdf@location before applying the rest of the &lt;br /&gt;
NcML transformations to the metadata.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;dimension&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;dimension&amp;gt; element has limited functionality in this release since the DAP2 doesn&#039;t support dimensions as more than mnemonics at this time.  The limitations are:&lt;br /&gt;
&lt;br /&gt;
* We only parse the &#039;&#039;dimension@name&#039;&#039; and &#039;&#039;dimension@length&#039;&#039; attributes.  &lt;br /&gt;
* Dimensions can only be specified as a direct child of a &amp;lt;netcdf&amp;gt; element prior to any reference to them&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt; &lt;br /&gt;
  &amp;lt;dimension name=&amp;quot;station&amp;quot; length=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;dimension name=&amp;quot;samples&amp;quot; length=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;!-- Some variable elements refer to the dimensions here --&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The dimension element sets up a mapping from the &#039;&#039;name&#039;&#039; to the unsigned integer &#039;&#039;length&#039;&#039; and can be used in a &#039;&#039;variable@shape&#039;&#039; to specify a length for an array dimension (see the section on &amp;lt;variable&amp;gt; below).  The dimension map is cleared when &amp;lt;/netcdf&amp;gt; is encountered (though this doesn&#039;t matter currently since we allow only one right now, but it will matter for aggregation, potentially).  We also do not support &amp;lt;group&amp;gt;, which is the only other legal place in NcML 2.2 for a dimension element.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* If the name and length are not both specified.&lt;br /&gt;
* If the dimension name already exists in the current scope&lt;br /&gt;
* If the length is not an unsigned integer&lt;br /&gt;
* If any of the other attributes specified in NcML 2.2 are used.  We do not handle them, so we consider them errors now.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;variable&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;variable&amp;gt; element is used to:&lt;br /&gt;
&lt;br /&gt;
* Provide lexical scope for a contained &amp;lt;attribute&amp;gt; or &amp;lt;variable&amp;gt; element&lt;br /&gt;
* Rename existing variables &lt;br /&gt;
* Add new scalar variables of simple types&lt;br /&gt;
* Add new Structure variables&lt;br /&gt;
* Add new N-dimensional Array&#039;s of simple types&lt;br /&gt;
* Specify the coordinate variable for the new dimension in a joinNew aggregation &lt;br /&gt;
&lt;br /&gt;
We describe each in turn in more detail.&lt;br /&gt;
&lt;br /&gt;
=== Specifying Lexical Scope with &amp;lt;variable type=&amp;quot;&amp;quot;&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Consider the following example:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;variable name=&amp;quot;u&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Metadata&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;This is metadata!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code assumes that a variable named &amp;quot;u&amp;quot; exists (of any type since we do not specify) and provides the lexical scope for the&lt;br /&gt;
attribute &amp;quot;Metadata&amp;quot; which will be added or modified within the attribute table for the variable &amp;quot;u&amp;quot; (it&#039;s qualified name would be &amp;quot;u.Metadata&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
==== Nested DAP Structure and Grid Scopes ====&lt;br /&gt;
&lt;br /&gt;
Scoping variable elements may be nested if the containing variable is a Structure (this includes the special case of Grid)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;DATA_GRANULE&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;PlanetaryGrid&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;variable name=&amp;quot;percipitate&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;inches&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This adds a &amp;quot;unit&amp;quot; attribute to the variable &amp;quot;percipitate&amp;quot; within the nested Structure&#039;s &lt;br /&gt;
(&amp;quot;DATA_GRANULE.PlanetaryGrid.percipitate&amp;quot; as fully qualified name).  &lt;br /&gt;
Note that we &#039;&#039;&#039;must&#039;&#039;&#039; refer to the type explicitly as a &amp;quot;Structure&amp;quot; so the parser knows&lt;br /&gt;
to traverse the tree.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; the variable might be of type Grid, but the type &amp;quot;Structure&amp;quot; must be used in the NcML to traverse it.&lt;br /&gt;
&lt;br /&gt;
==== Adding Multiple Attributes to the Same Variable ====&lt;br /&gt;
&lt;br /&gt;
Once the variable&#039;s scope is set by the opening &amp;lt;variable&amp;gt; element, more than one attribute can be specified within it.  This will make the NcML more readable and also will make the parsing more efficient since the variable will only need to be looked up once.&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_1&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Hello&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_2&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;World!&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
should be preferred over:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_1&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Hello&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_2&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;World!&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
although they produce the same result.  Any number of attributes can be specified before the variable is closed.&lt;br /&gt;
&lt;br /&gt;
=== Renaming Existing Variables ===&lt;br /&gt;
&lt;br /&gt;
The attribute &#039;&#039;variable@orgName&#039;&#039; is used to rename an existing variable. &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;NewName&amp;quot; orgName=&amp;quot;OldName&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing variable at the current scope named &amp;quot;OldName&amp;quot; to &amp;quot;NewName&amp;quot;.  After this point in the NcML file (such as in constraints specified for the DAP request), the variable is known by &amp;quot;NewName&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note that the type is not required here --- the variable is assumed to exist and its existing type is used.  It is not possible to change the type of an existing variable at this time!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:  &lt;br /&gt;
* If a variable with &#039;&#039;variable@orgName&#039;&#039; doesn&#039;t exist in the current scope&lt;br /&gt;
* If the new name &#039;&#039;variable@name&#039;&#039; is already taken in the current scope&lt;br /&gt;
* If a new variable is created but does not have exactly one values element&lt;br /&gt;
&lt;br /&gt;
=== Adding a New Scalar Variable ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;variable&amp;gt; element can be used to create a new scalar variable of a simple type (i.e. an atomic NcML type such as &amp;quot;int&amp;quot; or &amp;quot;float&amp;quot;, or any DAP atomic type, such as &amp;quot;UInt32&amp;quot; or &amp;quot;URL&amp;quot;) by specifying an empty &#039;&#039;variable@shape&#039;&#039; (which is the default), a simple type for &#039;&#039;variable@type&#039;&#039;, and a contained &amp;lt;values&amp;gt; element with the one value of correct type. &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;TheAnswerToLifeTheUniverseAndEverything&amp;quot; type=&amp;quot;double&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;SolvedBy&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;Deep Thought&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;values&amp;gt;42.000&amp;lt;/values&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create a new variable named &amp;quot;TheAnswerToLifeTheUniverseAndEverything&amp;quot; at the current scope.  It has no shape so will be a scalar of type &amp;quot;double&amp;quot; and will have the value 42.0.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* It is a parse error to not specify a &amp;lt;values&amp;gt; element with exactly one proper value of the variable type.&lt;br /&gt;
* It is a parse error to specify a malformed or out of bounds value for the data type&lt;br /&gt;
&lt;br /&gt;
=== Adding a New Structure Variable ===&lt;br /&gt;
&lt;br /&gt;
A new Structure variable can be specified at the global scope or within another Structure.  It is illegal for an array to have type structure, so the shape must be empty.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;MyNewStructure&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;MetaData&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;This is metadata!&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;ContainedScalar1&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&amp;lt;values&amp;gt;I live in a new structure!&amp;lt;/values&amp;gt;&amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;ContainedInt1&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;&amp;lt;values&amp;gt;42&amp;lt;/values&amp;gt;&amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
specifies a new structure called &amp;quot;MyNewStructure&amp;quot; which contains two scalar variable fields &amp;quot;ContainedScalar1&amp;quot; and &amp;quot;ContainedInt1&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
Nested structures are allowed as well.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Error&#039;&#039;&#039;: &lt;br /&gt;
* If another variable or attribute exists at the current scope with the new name.  &lt;br /&gt;
* If a &amp;lt;values&amp;gt; element is specified as a direct child of a new Structure --- structures cannot contain values, only attributes and other variables.&lt;br /&gt;
&lt;br /&gt;
=== Adding a New N-dimensional Array ===&lt;br /&gt;
&lt;br /&gt;
An N-dimensional array of a simple type may be created virtually as well by specifying a non-empty &#039;&#039;variable@shape&#039;&#039;.  The shape contains the array dimensions in left-to-right order of slowest varying dimension first.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;FloatArray&amp;quot; type=&amp;quot;float&amp;quot; shape=&amp;quot;2 5&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;!-- values specified in row major order (leftmost dimension in shape varies slowest) &lt;br /&gt;
	Any whitespace is a valid separator by default, so we can use newlines to pretty print 2D matrices.&lt;br /&gt;
	--&amp;gt;&lt;br /&gt;
      &amp;lt;values&amp;gt;&lt;br /&gt;
	0.1 0.2 0.3 0.4 0.5&lt;br /&gt;
	1.1 1.1 1.3 1.4 1.5&lt;br /&gt;
      &amp;lt;/values&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will specify a 2x5 dimension array of float values called &amp;quot;FloatArray&amp;quot;.  The &amp;lt;values&amp;gt; element must contain 2x5=10 values in row major order (slowest varying dimension first).  Since whitespace is the default separator, we use a newline to show the dimension boundary for the values, which is easy to see for a 2D matrix such as this.&lt;br /&gt;
&lt;br /&gt;
A dimension name may also be used to refer mnemonically to a length.  The DAP response will use this mnemonic in its output, but it is not currently used for shared dimensions, only as a mnemonic.   See the section on the &amp;lt;dimension&amp;gt; element for more information.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt;&lt;br /&gt;
 &amp;lt;dimension name=&amp;quot;station&amp;quot; length=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;dimension name=&amp;quot;sample&amp;quot; length=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;FloatArray&amp;quot; type=&amp;quot;float&amp;quot; shape=&amp;quot;station sample&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;values&amp;gt;&lt;br /&gt;
	0.1 0.2 0.3 0.4 0.5&lt;br /&gt;
	1.1 1.1 1.3 1.4 1.5&lt;br /&gt;
      &amp;lt;/values&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will produce the same 2x5 array, but will incorporate the dimension mnemonics into the response.  For example, here&#039;s the DDS response:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
     Float32 FloatArray[station = 2][samples = 5];&lt;br /&gt;
} sample_virtual_dataset.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;values&amp;gt; element respects the &#039;&#039;values@separator&#039;&#039; attribute if whitespace isn&#039;t correct.  This is very useful for arrays of strings with whitespace, for example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;StringArray&amp;quot; type=&amp;quot;string&amp;quot; shape=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;values separator=&amp;quot;*&amp;quot;&amp;gt;String 1*String 2*String 3&amp;lt;/values&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
creates a length 3 array of string StringArray = {&amp;quot;String 1&amp;quot;, &amp;quot;String 2&amp;quot;, &amp;quot;String 3&amp;quot;}.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:  &lt;br /&gt;
* It is an error to specify the incorrect number of values&lt;br /&gt;
* It is an error if any value is malformed or out of range for the data type.&lt;br /&gt;
* It is an error to specify a named dimension which does not exist in the current &amp;lt;netcdf&amp;gt; scope.&lt;br /&gt;
* It is an error to specify an Array whose flattened size (product of dimensions) is &amp;gt; 2^31-1.&lt;br /&gt;
&lt;br /&gt;
=== Specifying the new coordinate variable for a joinNew aggregation ===&lt;br /&gt;
&lt;br /&gt;
In the special case of a joinNew aggregation, the new coordinate variable may be specified with the &amp;lt;variable&amp;gt; element.  The new coordinate variable is &#039;&#039;defined&#039;&#039; to have the same name as the new dimension.  This allows for several things:&lt;br /&gt;
&lt;br /&gt;
*Explicit specification of the variable type and coordinates for the new dimension&lt;br /&gt;
*Specification of the metadata for the new coordinate variable &lt;br /&gt;
&lt;br /&gt;
In the first case, the author can specify explicitly the type of the new coordinate variable and the actual values for each dataset.  In this case, the variable &#039;&#039;must&#039;&#039; be specified &#039;&#039;after&#039;&#039; the aggregation element in the file so the new dimension&#039;s size (number of member datasets) may be known and error checking performed.  Metadata can also be added to the variable here.&lt;br /&gt;
&lt;br /&gt;
In the second case, the author may just specify the variable name, which allows one to specify the metadata for a coordinate variable that is automatically generated by the aggregation itself.  This is the only allowable case for a variable element to &#039;&#039;not&#039;&#039; contain a values element!  Coordinate variables are generated automatically in two cases:&lt;br /&gt;
&lt;br /&gt;
*The author has specified an explicit list of member datasets, with or without explicit coordVal attributes.  &lt;br /&gt;
*The author has used a &amp;lt;scan&amp;gt; element to specify the member datasets via a directory scan&lt;br /&gt;
&lt;br /&gt;
In this case, the &amp;lt;variable&amp;gt; element may come before or after the &amp;lt;aggregation&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*If an explicit variable is declared for the new coordinate variable:&lt;br /&gt;
** And it contains explicit values, the number of values must be equal to the number of member datasets in the aggregation.&lt;br /&gt;
** It must be specifed &#039;&#039;after&#039;&#039; the &amp;lt;aggregation&amp;gt; element&lt;br /&gt;
&lt;br /&gt;
* If a numeric coordVal is used to specify the first member dataset&#039;s coordinate, then &#039;&#039;all&#039;&#039; datasets must contain a numerical coordinate.&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variable (variableAgg) is not found in &#039;&#039;all&#039;&#039; member datasets.&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variable is not of the same type in &#039;&#039;all&#039;&#039; member datasets.  Coercion is &#039;&#039;not&#039;&#039; performed!&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variables in all member datasets do not have the same shape&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if an explicit coordinate variable is specified with a shape that is &#039;&#039;not&#039;&#039; the same as the new dimension name (and the variable name itself).&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;values&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;values&amp;gt; element can only be used in the context of a &#039;&#039;&#039;new&#039;&#039;&#039; variable of scalar or array type.  We cannot change the values for existing variables in this version of the handler. &lt;br /&gt;
The characters content of a &amp;lt;values&amp;gt; element is considered to be a separated list of value tokens valid for the type of the variable of the parent element.  The number of specified tokens in the content &#039;&#039;must&#039;&#039; equal the product of the dimensions of the enclosing &#039;&#039;variable@shape&#039;&#039;, or be one value for a scalar.  It is an error to &#039;&#039;not&#039;&#039; specify a &amp;lt;values&amp;gt; element for a declared new variable as well.  &lt;br /&gt;
&lt;br /&gt;
=== Changing the Separator Tokens === &lt;br /&gt;
&lt;br /&gt;
The author may specify values@separator to change the default value token separator from the default whitespace.  This is very useful for specifying arrays of strings with whitespace in them, or if data in CSV form is being pasted in.  &lt;br /&gt;
&lt;br /&gt;
=== Autogeneration of Uniform Arrays ===&lt;br /&gt;
&lt;br /&gt;
We also can parse &#039;&#039;values@start&#039;&#039; and &#039;&#039;values@increment&#039;&#039; INSTEAD OF tokens in the content.  This will &amp;quot;autogenerate&amp;quot; a uniform array of values of the given product of dimensions length for the containing variable.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Evens&amp;quot; type=&amp;quot;int&amp;quot; shape=&amp;quot;100&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;values start=&amp;quot;0&amp;quot; increment=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will specify an array of the first 100 even numbers (including 0).  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* If the incorrect number of tokens are specified for the containing variable&#039;s shape&lt;br /&gt;
* If any value token cannot be parsed as a valid value for the containing variable&#039;s type&lt;br /&gt;
* If content is specified in addition to start and increment&lt;br /&gt;
* If only one of start or increment is specified&lt;br /&gt;
* If the values element is placed anywhere except within a NEW variable.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;attribute&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
As an overview, whenever the parser encounters an &amp;lt;attribute&amp;gt; with a non-existing name (at the current scope),&lt;br /&gt;
it creates a new one, whether a container or atomic attribute (see below).  If the attribute exists,&lt;br /&gt;
its value and/or type is modified to those specified in the &amp;lt;attribute&amp;gt; element.  If an attribute&lt;br /&gt;
structure (container) exists, it is used to define a nested lexical scope for child attributes.  &lt;br /&gt;
&lt;br /&gt;
Attributes may be scalar (one value) or one dimensional arrays.  Arrays are specified by using whitespace (default) to separate the different values.  The attribute@separator may also be set in order to specify a different separator, such as CSV format or to specify a non-whitespace separator so strings with whitespace are not tokenized.  We will give examples of creating array attributes below.&lt;br /&gt;
&lt;br /&gt;
=== Adding New Attributes or Modifying an Existing Attribute ===&lt;br /&gt;
&lt;br /&gt;
If a specified attribute with the attribute@name does not exist at the current lexical scope, &lt;br /&gt;
a new one is created with the given type and value.  For example, assume &amp;quot;new_metadata&amp;quot; doesn&#039;t&lt;br /&gt;
exist at the current parse scope.  Then:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;new_metadata&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;This is a new entry!&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create the attribute at that scope.  Note that value can be specified in the content of the &lt;br /&gt;
element as well.  This is identical to the above:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;new_metadata&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;This is a new entry!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the attribute@name already exists at the scope, it is modified to contain the specified type and value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Arrays ====&lt;br /&gt;
&lt;br /&gt;
As in NcML, for numerical types an array can be specified by separating the tokens by whitespace (default) or be&lt;br /&gt;
specifying the token separator with attribute@separator.  For example,&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;myArray&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 2 3&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;myArray&amp;quot; type=&amp;quot;int&amp;quot; separator=&amp;quot;,&amp;quot;&amp;gt;1,2,3&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
both specify the same array of three integers named &amp;quot;myArray&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
TODO Add more information on splitting with a separator!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Structures (Containers) ====&lt;br /&gt;
&lt;br /&gt;
We use attribute@type=&amp;quot;Structure&amp;quot; to define a new (or existing) attribute container.   So if we&lt;br /&gt;
wanted to add a new attribute structure, we&#039;d use something like this: &lt;br /&gt;
&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;MySamples&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Location&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Station 1&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Samples&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 4 6&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assuming &amp;quot;MySamples&amp;quot; doesn&#039;t already exist, an attribute container will be created at the current scope&lt;br /&gt;
and the &amp;quot;Location&amp;quot; and &amp;quot;Samples&amp;quot; attributes will be added to it.&lt;br /&gt;
&lt;br /&gt;
Note that we can create nested attribute structures to arbitrary depth this way as well.&lt;br /&gt;
&lt;br /&gt;
If the attribute container with the given name already exists at the current scope, &lt;br /&gt;
then the attribute@type=&amp;quot;Structure&amp;quot; form is used to define&lt;br /&gt;
the lexical scope for the container.  In other words, child &amp;lt;attribute&amp;gt; elements will&lt;br /&gt;
be processed within the scope of the container.   For example, in the above example, if&lt;br /&gt;
&amp;quot;MySamples&amp;quot; already exists, then the &amp;quot;Location&amp;quot; and &amp;quot;Samples&amp;quot; will be processed within the&lt;br /&gt;
existing container (they may or may not already exist as well).&lt;br /&gt;
&lt;br /&gt;
==== Renaming an Existing Attribute or Attribute Container ====&lt;br /&gt;
&lt;br /&gt;
We also support the attribute@orgName attribute for renaming attributes.   &lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;NewName&amp;quot; orgName=&amp;quot;OldName&amp;quot; type=&amp;quot;string&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing attribute &amp;quot;OldName&amp;quot; to &amp;quot;NewName&amp;quot; while leaving its value alone.&lt;br /&gt;
If attribute@value is also specified, then the attribute is renamed &#039;&#039;and&#039;&#039; has its value modified.&lt;br /&gt;
&lt;br /&gt;
This works for renaming attribute containers as well:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;MyNewContainer&amp;quot; orgName=&amp;quot;MyOldContainer&amp;quot; type=&amp;quot;Structure&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing &amp;quot;MyOldContainer&amp;quot; to &amp;quot;MyNewContainer&amp;quot;.  Note that any children&lt;br /&gt;
of this container will remain in it.&lt;br /&gt;
&lt;br /&gt;
=== DAP &#039;&#039;OtherXML&#039;&#039; Extension ===&lt;br /&gt;
&lt;br /&gt;
The module now allows specification of attributes of the new DAP type &amp;quot;OtherXML&amp;quot;.  This allows the NCML file author to inject arbitrary well-formed XML into an attribute for clients that want XML metadata rather than just string or url.  Internally, the attribute is still a string (and in a DAP DAS response will be quoted inside one string).  However, since it is XML, the NCMLParser still parses it and checks it for well-formedness (but NOT against schemas).  This extension allows the NCMLParser to parse the arbitrary XML within the given attribute without causing errors, since it can be any XML.  &lt;br /&gt;
&lt;br /&gt;
The injected XML is most useful in the DDX response, where it shows up directly in the response as XML.  XSLT and other clients can then parse it.&lt;br /&gt;
&lt;br /&gt;
==== Errors ====&lt;br /&gt;
&lt;br /&gt;
*The XML &#039;&#039;&#039;must&#039;&#039;&#039; be in the content of the &amp;lt;attribute type=&amp;quot;OtherXML&amp;quot;&amp;gt; element.  It is a parser error for &#039;&#039;attribute@value&#039;&#039; to be set if &#039;&#039;attribute@type&#039;&#039; is &amp;quot;OtherXML&amp;quot;.  &lt;br /&gt;
*The XML must also be well-formed since it is parsed.  A parse error will be thrown if the OtherXML is malformed.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of the use of this special case.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf xmlns=&amp;quot;http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2&amp;quot; location=&amp;quot;/coverage/200803061600_HFRadar_USEGC_6km_rtv_SIO.nc&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;someName&amp;quot; type=&amp;quot;OtherXML&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;Domain xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot; &lt;br /&gt;
                xmlns:ows=&amp;quot;http://www.opengis.net/ows/1.1&amp;quot;&lt;br /&gt;
                xmlns:gml=&amp;quot;http://www.opengis.net/gml/3.2&amp;quot;&lt;br /&gt;
                &amp;gt;&lt;br /&gt;
            &amp;lt;SpatialDomain&amp;gt;&lt;br /&gt;
                &amp;lt;ows:BoundingBox crs=&amp;quot;urn:ogc:def:crs:EPSG::4326&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;ows:LowerCorner&amp;gt;-97.8839 21.736&amp;lt;/ows:LowerCorner&amp;gt;&lt;br /&gt;
                    &amp;lt;ows:UpperCorner&amp;gt;-57.2312 46.4944&amp;lt;/ows:UpperCorner&amp;gt;&lt;br /&gt;
                &amp;lt;/ows:BoundingBox&amp;gt;&lt;br /&gt;
            &amp;lt;/SpatialDomain&amp;gt;&lt;br /&gt;
            &amp;lt;TemporalDomain&amp;gt;&lt;br /&gt;
                &amp;lt;gml:timePosition&amp;gt;2008-03-27T16:00:00.000Z&amp;lt;/gml:timePosition&amp;gt;&lt;br /&gt;
            &amp;lt;/TemporalDomain&amp;gt;&lt;br /&gt;
        &amp;lt;/Domain&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedCRS xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;urn:ogc:def:crs:EPSG::4326&amp;lt;/SupportedCRS&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedFormat xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;netcdf-cf1.0&amp;lt;/SupportedFormat&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedFormat xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;dap2.0&amp;lt;/SupportedFormat&amp;gt;&lt;br /&gt;
    &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039; Put the DDX response for the above in here!&lt;br /&gt;
&lt;br /&gt;
====Namespace Closure====&lt;br /&gt;
&lt;br /&gt;
Furthermore, the parser will make the chunk of OtherXML &amp;quot;namespace closed&amp;quot;.  This means any namespaces specified in parent NCML elements of the OtherXML tree will be &amp;quot;brought down&amp;quot; and added to the &#039;&#039;root&#039;&#039; OtherXML elements so that the subtree may be pulled out and added to the DDX and still have its namespaces.  The algorithm doesn&#039;t just bring used prefixes, but brings &#039;&#039;all&#039;&#039; of the lexically scoped closest namespaces in all ancestors.  In other words, it adds unique namespaces (as determined by prefix) in order from the root of the OtherXML tree as it traverses to the root of the NCML document.  &lt;br /&gt;
&lt;br /&gt;
Namespace closure is a syntactic sugar that simplifies the author&#039;s task since they can specify the namespaces just once at the top of the NCML file and expect that when the subtree of XML is added to the DDX that these namespaces will come along with that subtree of XML.  Otherwise they have to explicitly add the namespaces to each attributes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039; Add an example!&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;remove&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;remove&amp;gt; element can remove attributes and variables.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;attribute name=&amp;quot;NC_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;remove name=&amp;quot;base_time&amp;quot; type=&amp;quot;attribute&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will remove the attribute named &amp;quot;base_time&amp;quot; in the attribute structure named &amp;quot;NC_GLOBAL&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Note that this works for attribute containers as well!  We could recursively remove the &#039;&#039;entire&#039;&#039;&lt;br /&gt;
attribute container (i.e. it and all its children) with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;remove name=&amp;quot;NC_GLOBAL&amp;quot; type=&amp;quot;attribute&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It also can be used to remove variables from existing datasets:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
  &amp;lt;remove name=&amp;quot;SomeExistingVariable&amp;quot; type=&amp;quot;variable&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This also recurses on variables of type Structure --- the entire structure including all of its children are removed from the dataset&#039;s response.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* It is a parse error if the given attribute or variable doesn&#039;t exist in the current scope&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;aggregation&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
Aggregation involves combining multiple datasets (&amp;lt;netcdf&amp;gt;) into a virtual &amp;quot;single&amp;quot; dataset in various ways.  For a tutorial on aggregation in NcML 2.2, the reader is referred to the Unidata page: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Aggregation.html&lt;br /&gt;
&lt;br /&gt;
NcML 2.2 supports multiple types of aggregation: union, joinNew, joinExisting, and fmrc (forecast model run collection).  &lt;br /&gt;
&lt;br /&gt;
The current version of the NcML module supports two of these aggregations:&lt;br /&gt;
&lt;br /&gt;
*Union [[NCML_Module_Aggregation_Union]]&lt;br /&gt;
*JoinNew [[NCML_Module_Aggregation_JoinNew]]&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;union&#039;&#039; aggregation specifies that the first instance of a variable or attribute (by name) that is found in the ordered list of datasets will be the one in the output aggregation.   This is useful for combining two dataset files, each which may contain a single variable, into a composite dataset with both variables.&lt;br /&gt;
&lt;br /&gt;
A JoinNew aggregation joins a variable which exists in multiple datasets (usually samples of a datum over time) into a new variable containing the data from &#039;&#039;all&#039;&#039; member datasets by creating a new outer dimension.  The &#039;&#039;i&#039;&#039;th component in the new outer dimension is the variable&#039;s data from the &#039;&#039;i&#039;&#039;th member dataset.  It also adds a new coordinate variable of whose name is the new dimension&#039;s name and whose shape (length) is the new dimension as well.  This new coordinate variable may be explicitly given by the author or may be autogenerated in one of several ways.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;scan&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The scan element can be used within an aggregation context to allow a directory to be searched in various ways in order to specify the members of an aggregation.  This allows a static NcML file to refer to an aggregation which may change over time, such as where a new data file is generated each day.&lt;br /&gt;
&lt;br /&gt;
We describe usage of the &amp;lt;scan&amp;gt; element in detail in the joinNew aggregation tutorial at [[NCML_Module_Aggregation_JoinNew]].&lt;br /&gt;
&lt;br /&gt;
= Errors =&lt;br /&gt;
&lt;br /&gt;
There are three types of error messages that may be returned:&lt;br /&gt;
&lt;br /&gt;
* Internal Error&lt;br /&gt;
* Resource Not Found Error&lt;br /&gt;
* Parse Error&lt;br /&gt;
&lt;br /&gt;
== Internal Errors ==&lt;br /&gt;
&#039;&#039;&#039;Internal errors&#039;&#039;&#039; should be reported to support@opendap.org as they are likely bugs.&lt;br /&gt;
&lt;br /&gt;
== Resource Not Found Errors ==&lt;br /&gt;
&lt;br /&gt;
If the netcdf@location specifies a non-existent local dataset (one that is not being served by&lt;br /&gt;
the same Hyrax server), it will specify the resource was not found.   This may also be returned&lt;br /&gt;
if a handler for the specified dataset is not currently loaded in the BES.  Users should test that the&lt;br /&gt;
dataset to be wrapped already exists and can be viewed on the running server before writing NcML &lt;br /&gt;
to add metadata.  It&#039;s also an error to refer to remote datasets (at this time).&lt;br /&gt;
&lt;br /&gt;
== Parse Errors ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse errors&#039;&#039;&#039; are user errors in the NcML file.  These could be malformed XML, malformed NcML, &lt;br /&gt;
unimplemented features of NcML, or could be errors in referring to the wrapped dataset.  &lt;br /&gt;
&lt;br /&gt;
The error message should specify &lt;br /&gt;
the error condition as well as the &amp;quot;current scope&amp;quot; as a fully qualified DAP name within the &lt;br /&gt;
loaded dataset.  This should be enough information to correct the parse error as new NcML&lt;br /&gt;
files are created.&lt;br /&gt;
&lt;br /&gt;
The parser will generate parse errors in various &lt;br /&gt;
situations where it expects to find certain structure in the underlying dataset.  Some examples:&lt;br /&gt;
&lt;br /&gt;
* A variable of the given name was not found at the current scope&lt;br /&gt;
* attribute@orgName was specified, but the attribute cannot be found at current scope.&lt;br /&gt;
* attribute@orgName was specified, but the new name is already used at current scope.&lt;br /&gt;
* remove specified a non-existing attribute name&lt;br /&gt;
&lt;br /&gt;
= Aggregation Tutorials =&lt;br /&gt;
&lt;br /&gt;
The NcML module may also be used to aggregate multiple datasets into one virtual dataset.  We currently support two of the NcML aggregtions:&lt;br /&gt;
&lt;br /&gt;
*Union [[NCML_Module_Aggregation_Union]]:  combine multiple datasets into one by merging variables together, selecting the first of each unique name.&lt;br /&gt;
*JoinNew [[NCML_Module_Aggregation_JoinNew]]: combine variables across multiple datasets by creating a new outer dimension and coordinate variable for each of the sample datasets.&lt;br /&gt;
&lt;br /&gt;
Please see the sections for a tutorial on the various uses of these aggregations.&lt;br /&gt;
&lt;br /&gt;
= Additions/Changes to NcML 2.2 =&lt;br /&gt;
&lt;br /&gt;
This section will keep track of changes to the NcML 2.2 schema.  Eventually these&lt;br /&gt;
will be rolled into a new schema.&lt;br /&gt;
&lt;br /&gt;
== Attribute Structures (Containers) ==&lt;br /&gt;
This module also adds functionality beyond the current NcML 2.2 schema&lt;br /&gt;
--- it can handle nested &amp;lt;attribute&amp;gt; elements in order to make&lt;br /&gt;
attribute structures.  This is done by using the &amp;lt;attribute&lt;br /&gt;
type=&amp;quot;Structure&amp;quot;&amp;gt; form, for example:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;MySamples&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Location&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Station 1&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Samples&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 4 6&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;MyContainer&amp;quot; describes an attribute structure with two attribute fields,&lt;br /&gt;
a string &amp;quot;Location&amp;quot; and an array of int&#039;s called &amp;quot;Samples&amp;quot;.  &lt;br /&gt;
Note that an attribute structure of this form can&lt;br /&gt;
only contain other &amp;lt;attribute&amp;gt; elements and NOT a value.&lt;br /&gt;
&lt;br /&gt;
If the container does not already exist, it will be created at the scope it is declared, which could&lt;br /&gt;
be:&lt;br /&gt;
&lt;br /&gt;
* Global (top of dataset)&lt;br /&gt;
* Within a variable&#039;s attribute table&lt;br /&gt;
* Within another attribute container&lt;br /&gt;
&lt;br /&gt;
If an attribute container of the given name already exists at the lexical scope, it is traversed &lt;br /&gt;
in order to define the scope for the nested (children) attributes it contains.&lt;br /&gt;
&lt;br /&gt;
== Unspecified Variable Type Matching for Lexical Scope ==&lt;br /&gt;
&lt;br /&gt;
We also allow the type attribute of a variable element (variable@type) to be the empty string &lt;br /&gt;
(or unspecified) when using existing variables to define the lexical scope of an &amp;lt;attribute&amp;gt; &lt;br /&gt;
transformation.  In the schema, variable@type is (normally) required.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DAP 2 Types ==&lt;br /&gt;
&lt;br /&gt;
Additionally, we allow DAP2 atomic types (such as UInt32, URL) in addition to the NcML types.  &lt;br /&gt;
The NcML types are mapped onto the closest DAP2 type internally.&lt;br /&gt;
&lt;br /&gt;
== DAP OtherXML Attribute Type ==&lt;br /&gt;
&lt;br /&gt;
We also allow attributes to be of the new DAP type &amp;quot;OtherXML&amp;quot; for injecting arbitrary XML into an attribute as content rather than trying to form a string.  This allows the parser to check well-formedness.&lt;br /&gt;
&lt;br /&gt;
== Forward Declaration of Dimensions ==&lt;br /&gt;
&lt;br /&gt;
Since we use a SAX parser for efficiency, we require the &amp;lt;dimension&amp;gt; elements to come &#039;&#039;before&#039;&#039; their use in a &#039;&#039;variable@shape&#039;&#039;.  One way to change the schema to allow this is to force the dimension elements to be specified in a sequence after explicit and metadata choice and before all other elements.&lt;br /&gt;
&lt;br /&gt;
== Aggregation Element Location and Processing Order Differences ==&lt;br /&gt;
&lt;br /&gt;
NcML specifies that if a dataset (&amp;lt;netcdf&amp;gt; element) specifies an aggregation element, the aggregation element is always processed first, regardless of its ordering within the &amp;lt;netcdf&amp;gt; element.  Our parser, since it is SAX and not DOM, modifies this behavior in that order matters in some cases:&lt;br /&gt;
&lt;br /&gt;
* Metadata (&amp;lt;attribute&amp;gt;) elements specified &#039;&#039;prior&#039;&#039; to an aggregation &amp;quot;shadow&amp;quot; the aggregation versions.  This is be useful for &amp;quot;overriding&amp;quot; an attribute or variable in a union aggregation, where the first found will take precedence. &lt;br /&gt;
* JoinNew: If the new coordinate variable&#039;s data is to be set explicitly by specifying the new dimension&#039;s shape (either with explicit data or the autogenerated data using values@start and values@increment attributes), the &amp;lt;variable&amp;gt; &#039;&#039;must&#039;&#039; come after the aggregation since the size of the dimension is unknown until the aggregation element is processed.&lt;br /&gt;
&lt;br /&gt;
= Backward Compatibility Issues =&lt;br /&gt;
&lt;br /&gt;
Due to the way shared dimensions were implemented in the NetCDF, HDF4, and HDF5 handlers, the DAS responses did not follow the DAP2 specification.  The NcML module, on the other hand, generates DAP2 compliant DAS for these datasets, which means that wrapping some datasets in NcML will generate a DAS with a different structure.  This is important for the NcML author since it changes the names of attributes and variables.  In order for the module to find the correct scope for adding metadata, for example, the DAP2 DAS must be used.  &lt;br /&gt;
&lt;br /&gt;
In general, what this means is that an empty &amp;quot;passthrough&amp;quot; NcML file should be the starting point for authoring an NcML file.  This file would just specify a dataset and nothing else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;/data/ncml/myNetcdf.nc&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The author would then request the DAS response for the NCML file and use that as the starting point for modifications to the original dataset. &lt;br /&gt;
&lt;br /&gt;
More explicit examples are given below.&lt;br /&gt;
&lt;br /&gt;
== NetCDF ==&lt;br /&gt;
&lt;br /&gt;
The NetCDF handler represents some NC datasets as a DAP 2 Grid, but the returned DAS is not consistent with the DAP 2 spec for the attribute hierarchy for such a Grid.  The map vector attributes are placed as siblings of the grid attributes rather than within the grid lexical scope.  For example, here&#039;s the NetCDF Handler DDS for a given file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Int16 cldc[time = 456][lat = 21][lon = 360];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 456];&lt;br /&gt;
        Float32 lat[lat = 21];&lt;br /&gt;
        Float32 lon[lon = 360];&lt;br /&gt;
    } cldc;&lt;br /&gt;
} cldc.mean.nc;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
showing the Grid.  Here&#039;s the DAS the NetCDF handler generates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    lat {&lt;br /&gt;
        String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
        String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
        Float32 actual_range 10.00000000, -10.00000000;&lt;br /&gt;
    }&lt;br /&gt;
    lon {&lt;br /&gt;
        String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
        String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
        Float32 actual_range 0.5000000000, 359.5000000;&lt;br /&gt;
    }&lt;br /&gt;
    time {&lt;br /&gt;
        String units &amp;quot;days since 1-1-1 00:00:0.0&amp;quot;;&lt;br /&gt;
        String long_name &amp;quot;Time&amp;quot;;&lt;br /&gt;
        String delta_t &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
        String avg_period &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
        Float64 actual_range 715511.00000000000, 729360.00000000000;&lt;br /&gt;
    }&lt;br /&gt;
    cldc {&lt;br /&gt;
        Float32 valid_range 0.000000000, 8.000000000;&lt;br /&gt;
        Float32 actual_range 0.000000000, 8.000000000;&lt;br /&gt;
        String units &amp;quot;okta&amp;quot;;&lt;br /&gt;
        Int16 precision 1;&lt;br /&gt;
        Int16 missing_value 32766;&lt;br /&gt;
        Int16 _FillValue 32766;&lt;br /&gt;
        String long_name &amp;quot;Cloudiness Monthly Mean at Surface&amp;quot;;&lt;br /&gt;
        String dataset &amp;quot;COADS 1-degree Equatorial Enhanced\\012AI&amp;quot;;&lt;br /&gt;
        String var_desc &amp;quot;Cloudiness\\012C&amp;quot;;&lt;br /&gt;
        String level_desc &amp;quot;Surface\\0120&amp;quot;;&lt;br /&gt;
        String statistic &amp;quot;Mean\\012M&amp;quot;;&lt;br /&gt;
        String parent_stat &amp;quot;Individual Obs\\012I&amp;quot;;&lt;br /&gt;
        Float32 add_offset 3276.500000;&lt;br /&gt;
        Float32 scale_factor 0.1000000015;&lt;br /&gt;
    }&lt;br /&gt;
    NC_GLOBAL {&lt;br /&gt;
        String title &amp;quot;COADS 1-degree Equatorial Enhanced&amp;quot;;&lt;br /&gt;
        String history &amp;quot;&amp;quot;;&lt;br /&gt;
        String Conventions &amp;quot;COARDS&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    DODS_EXTRA {&lt;br /&gt;
        String Unlimited_Dimension &amp;quot;time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the map vector attributes are in the &amp;quot;dataset&amp;quot; scope.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the DAS that the NcML Module produces from the correctly formed DDX:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    NC_GLOBAL {&lt;br /&gt;
        String title &amp;quot;COADS 1-degree Equatorial Enhanced&amp;quot;;&lt;br /&gt;
        String history &amp;quot;&amp;quot;;&lt;br /&gt;
        String Conventions &amp;quot;COARDS&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    DODS_EXTRA {&lt;br /&gt;
        String Unlimited_Dimension &amp;quot;time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    cldc {&lt;br /&gt;
        Float32 valid_range 0.000000000, 8.000000000;&lt;br /&gt;
        Float32 actual_range 0.000000000, 8.000000000;&lt;br /&gt;
        String units &amp;quot;okta&amp;quot;;&lt;br /&gt;
        Int16 precision 1;&lt;br /&gt;
        Int16 missing_value 32766;&lt;br /&gt;
        Int16 _FillValue 32766;&lt;br /&gt;
        String long_name &amp;quot;Cloudiness Monthly Mean at Surface&amp;quot;;&lt;br /&gt;
        String dataset &amp;quot;COADS 1-degree Equatorial Enhanced\\012AI&amp;quot;;&lt;br /&gt;
        String var_desc &amp;quot;Cloudiness\\012C&amp;quot;;&lt;br /&gt;
        String level_desc &amp;quot;Surface\\0120&amp;quot;;&lt;br /&gt;
        String statistic &amp;quot;Mean\\012M&amp;quot;;&lt;br /&gt;
        String parent_stat &amp;quot;Individual Obs\\012I&amp;quot;;&lt;br /&gt;
        Float32 add_offset 3276.500000;&lt;br /&gt;
        Float32 scale_factor 0.1000000015;&lt;br /&gt;
        cldc {&lt;br /&gt;
        }&lt;br /&gt;
        time {&lt;br /&gt;
            String units &amp;quot;days since 1-1-1 00:00:0.0&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;Time&amp;quot;;&lt;br /&gt;
            String delta_t &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
            String avg_period &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
            Float64 actual_range 715511.00000000000, 729360.00000000000;&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
            Float32 actual_range 10.00000000, -10.00000000;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
            Float32 actual_range 0.5000000000, 359.5000000;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here the Grid Structure &amp;quot;cldc&amp;quot;  and its contained data array (of the same name &amp;quot;cldc&amp;quot;) and map vectors have their own attribute containers as DAP 2 specifies.&lt;br /&gt;
&lt;br /&gt;
What this means for the author of an NcML file adding metadata to a NetCDF dataset that returns a Grid is that they should generate a &amp;quot;passthrough&amp;quot; file and get the DAS and then specify modifications based on that structure.  &lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example passthrough:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/cldc.mean.nc&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For example, to add an attribute to the map vector &amp;quot;lat&amp;quot; in the above, we&#039;d need the following NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/cldc.mean.nc&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;!-- Traverse into the Grid as a Structure --&amp;gt;&lt;br /&gt;
  &amp;lt;variable name=&amp;quot;cldc&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Traverse into the &amp;quot;lat&amp;quot; map vector (Array) --&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lat&amp;quot;&amp;gt; &lt;br /&gt;
      &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;I am a new attribute in the Grid map vector named lat!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lon&amp;quot;&amp;gt; &lt;br /&gt;
      &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;I am a new attribute in the Grid map vector named lon!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This clearly shows that the structure of the Grid must be used in the NcML:  the attribute being added is technically &amp;quot;cldc.lat.Description&amp;quot; in a fully qualified name.  The parser would return an error if it was attempted as &amp;quot;lat.Description&amp;quot; as the NetCDF DAS for the original file would have led one to believe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== HDF4/HDF5 ==&lt;br /&gt;
&lt;br /&gt;
Similarly to the NetCDF case, the Hyrax HDF4 Module produces DAS responses that do not respect the DAP2 specification.  If an NcML file is used to &amp;quot;wrap&amp;quot; an HDF4 dataset, the&lt;br /&gt;
correct DAP2 DAS response will be generated, however. &lt;br /&gt;
&lt;br /&gt;
This is important for those writing NcML for HDF4 data since the&lt;br /&gt;
lexical scope for attributes relies on the correct DAS form --- to&lt;br /&gt;
handle this, the user should start with a &amp;quot;passthrough&amp;quot; NcML file (see the above NetCDF example) and&lt;br /&gt;
use the DAS from that as the starting point for knowing the structure&lt;br /&gt;
the NcML handler expects to see in the NcML file.  Alternatively, the DDX has the &lt;br /&gt;
proper attribute structure as well (the DAS is generated from it).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Known Bugs =&lt;br /&gt;
&lt;br /&gt;
There are no known bugs currently.&lt;br /&gt;
&lt;br /&gt;
= Planned Future Enhancements =&lt;br /&gt;
&lt;br /&gt;
Planned enhancements for future versions of the module include:&lt;br /&gt;
&lt;br /&gt;
* New NcML Aggregations&lt;br /&gt;
** JoinExisting&lt;br /&gt;
*** Joins a variable across multiple datasets by appending the data for a given dimension from each dataset &lt;br /&gt;
*** Will also allow directory scans for specifying the aggregation&lt;br /&gt;
** Forecast Model Run Collection (FMRC)&lt;br /&gt;
*** Special case of JoinNew for forecast data with two time variables&lt;br /&gt;
*** See: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/FmrcAggregation.html&lt;br /&gt;
&lt;br /&gt;
= Copyright =&lt;br /&gt;
&lt;br /&gt;
This software is copyrighted under the GNU Lesser GPL.  Please see the&lt;br /&gt;
files COPYING and COPYRIGHT that came with this distribution.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=BES_-_Modules_-_NcML_Module&amp;diff=5592</id>
		<title>BES - Modules - NcML Module</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=BES_-_Modules_-_NcML_Module&amp;diff=5592"/>
		<updated>2010-04-20T19:35:34Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Features */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
[[Category:NCML]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Welcome to the OPeNDAP NcML Data Handler Module v1.0.1 for Hyrax 1.6!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[Updated for NcML Module v1.0.1 for Hyrax 1.6.0 beta --  8 April 2010]&lt;br /&gt;
&lt;br /&gt;
This module may be added to a Hyrax 1.6 server to extend its data&lt;br /&gt;
serving capability to NcML 2.2 files (see&lt;br /&gt;
http://www.unidata.ucar.edu/software/netcdf/ncml/).  NcML provides support for modifying other datasets in various ways, such as adding metadata and data and aggregating multiple datasets in several ways&lt;br /&gt;
&lt;br /&gt;
==Features==         &lt;br /&gt;
   &lt;br /&gt;
This current version (v1.0.1) currently implements a subset of NcML 2.2&lt;br /&gt;
functionality, along with some OPeNDAP extensions:&lt;br /&gt;
&lt;br /&gt;
* Metadata Manipulation&lt;br /&gt;
** Addition, Removal, and Modification of attributes to other datasets (NetCDF, HDF4, HD5, etc.) served by the same Hyrax 1.6 server&lt;br /&gt;
** Extends NcML 2.2 to allow for common nested &amp;quot;attribute containers&amp;quot; &lt;br /&gt;
** Attributes can be DAP2 types as well as the NcML types &lt;br /&gt;
** Attributes can be of the special &amp;quot;OtherXML&amp;quot; type for injecting arbitrary XML into a DDX response&lt;br /&gt;
* Data Manipulation&lt;br /&gt;
** Addition of new data variables (scalars or arrays of basic types as well as structures) &lt;br /&gt;
** Variables may be removed from the wrapped dataset&lt;br /&gt;
** Allows the creation of &amp;quot;pure virtual&amp;quot; datasets which do not wrap another dataset&lt;br /&gt;
* Aggregations: JoinNew and Union [[#Aggregation Tutorials]]&lt;br /&gt;
** JoinNew Aggregation ([[NCML_Module_Aggregation_JoinNew]])&lt;br /&gt;
*** Allows multiple datasets to be &amp;quot;joined&amp;quot; by creating a new outer dimension for the aggregated variable&lt;br /&gt;
*** Aggregation member datasets can be listed explicitly with explicit coordinates for the new dimension for each member&lt;br /&gt;
*** Scan: Aggregations can be specified &amp;quot;automatically&amp;quot; by scanning a directory for files matching certain criteria, such as a suffix or regular expression.&lt;br /&gt;
*** Metadata may be added to the new coordinate variable for the new dimension&lt;br /&gt;
** Union Aggregation ([[NCML_Module_Aggregation_Union]])&lt;br /&gt;
*** Merges all member datasets into one by taking the first named instance of variables and metadata from the members&lt;br /&gt;
*** Useful for combining two or more datasets with different variables into a single set&lt;br /&gt;
&lt;br /&gt;
== Installation from Source ==&lt;br /&gt;
For information on how to build and install the NcML Data Module, please see the INSTALL file that came with the source distribution.&lt;br /&gt;
&lt;br /&gt;
= Installation Overview =&lt;br /&gt;
&lt;br /&gt;
The NcML Module requires a working Hyrax 1.6 installation.  It is a module&lt;br /&gt;
that is dynamically loaded into the Hyrax BES (Back End Server) to&lt;br /&gt;
allow it to handle NcML files.  &lt;br /&gt;
&lt;br /&gt;
Please see the file INSTALL for full build and install instructions as&lt;br /&gt;
well as requirements.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; After installation, you MUST restart Hyrax by restarting the BES and&lt;br /&gt;
OLFS so the NcML Module is loaded!&lt;br /&gt;
&lt;br /&gt;
== Requirement: International Components for Unicode (ICU) Library == &lt;br /&gt;
&lt;br /&gt;
The most important external requirement is an installation of the International Components for Unicode (ICU) version 3.6 or higher (tested up to 4.2.1).   The source distributions (as well as some binaries) may be found at the site: http://site.icu-project.org/download&lt;br /&gt;
&lt;br /&gt;
If you are using Linux RPM&#039;s to run Hyrax, you can get an RPM for ICU as well.  Search for the RPM named &amp;quot;libicu&amp;quot; using a package manager or yum, e.g.   If you are compiling the module from source, you will also need the RPM &amp;quot;libicu-devel&amp;quot; to get the headers installed.  &lt;br /&gt;
&lt;br /&gt;
If you install in the default locations, the ncml_module should find the libraries and headers.  Otherwise, please consult the INSTALL file for more information about installing ICU to a non-standard location.&lt;br /&gt;
&lt;br /&gt;
== Testing Installation ==&lt;br /&gt;
&lt;br /&gt;
Test data is provided to see if the installation was successful.  The file sample_virtual_dataset.ncml is a dataset purely created in NcML and doesn&#039;t contain an underlying dataset.  &lt;br /&gt;
You may also view fnoc1_improved.ncml to test adding attributes to an existing netCDF dataset (fnoc1.nc), but this requires the netCDF data handler to be&lt;br /&gt;
installed first!  Several other examples installed also use the HDF4 and HDF5 handlers.&lt;br /&gt;
&lt;br /&gt;
= Functionality =&lt;br /&gt;
&lt;br /&gt;
This version of the NcML Module implements a subset of NcML 2.2&lt;br /&gt;
functionality.  The reader is directed to http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/ for more information on NcML.&lt;br /&gt;
&lt;br /&gt;
Our module can currently:&lt;br /&gt;
&lt;br /&gt;
*Refer only to files being served locally (not remotely)&lt;br /&gt;
*Add, modify, and remove attribute metadata to a dataset&lt;br /&gt;
*Create a purely virtual dataset using just NcML and no underlying dataset&lt;br /&gt;
*Create new scalar variables of any simple NcML type or simple DAP type&lt;br /&gt;
*Create new Structure variables (which can contain new child variables)&lt;br /&gt;
*Create new N-dimensional arrays of simple types (NcML or DAP)&lt;br /&gt;
*Remove existing variables from a wrapped dataset&lt;br /&gt;
*Rename existing variables in a wrapped dataset&lt;br /&gt;
*Name dimensions as a mnemonic for specifying Array shapes&lt;br /&gt;
*Perform union aggregations on multiple datasets, virtual or wrapped or both&lt;br /&gt;
*Perform joinNew aggregations to merge a variable across multiple datasets by creating a new outer dimension&lt;br /&gt;
*Specify aggregation member datasets by scanning directories for files matching certain criteria&lt;br /&gt;
&lt;br /&gt;
We describe each supported NcML element in detail below.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;netcdf&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;netcdf&amp;gt; element is used to define a dataset, either a wrapped dataset that is to be modified, a pure virtual dataset, or a member dataset of an aggregation.  The &amp;lt;netcdf&amp;gt; element is assumed to be the topmost node, or as a child of an aggregation element.&lt;br /&gt;
&lt;br /&gt;
=== Local vs. Remote Datasets ===&lt;br /&gt;
&lt;br /&gt;
We assume that the location attribute (&#039;&#039;netcdf@location&#039;&#039;) refers to the full path (with respect to the BES data root directory) of a &#039;&#039;&#039;&#039;&#039;local&#039;&#039;&#039;&#039;&#039; dataset (served by the same Hyrax server).  The current version of the module cannot be used to modify remote datasets.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;netcdf@location&#039;&#039; is the empty string (or unspecified, as empty is the default), the dataset is a pure virtual dataset, fully specified within the NcML file itself.  Attributes and variables may be fully described and accessed with constraints just as normal datasets in this manner.  The installed sample datafile &amp;quot;sample_virtual_dataset.ncml&amp;quot; is an example test case for this functionality.&lt;br /&gt;
&lt;br /&gt;
=== Unsupported Attributes ===&lt;br /&gt;
&lt;br /&gt;
The current version does not support the following attributes of &amp;lt;netcdf&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
*enhance&lt;br /&gt;
*addRecords&lt;br /&gt;
*fmrcDefinition (will be supported when FMRC aggregation is added)&lt;br /&gt;
*ncoords (will be supported when joinExisting is added)&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;readMetadata&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;readMetadata/&amp;gt; element is the default, so is effectively not needed.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;explicit&amp;gt; element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;explicit/&amp;gt; element simply clears all attribute tables in the referred to netcdf@location before applying the rest of the &lt;br /&gt;
NcML transformations to the metadata.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;dimension&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;dimension&amp;gt; element has limited functionality in this release since the DAP2 doesn&#039;t support dimensions as more than mnemonics at this time.  The limitations are:&lt;br /&gt;
&lt;br /&gt;
* We only parse the &#039;&#039;dimension@name&#039;&#039; and &#039;&#039;dimension@length&#039;&#039; attributes.  &lt;br /&gt;
* Dimensions can only be specified as a direct child of a &amp;lt;netcdf&amp;gt; element prior to any reference to them&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt; &lt;br /&gt;
  &amp;lt;dimension name=&amp;quot;station&amp;quot; length=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;dimension name=&amp;quot;samples&amp;quot; length=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;!-- Some variable elements refer to the dimensions here --&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The dimension element sets up a mapping from the &#039;&#039;name&#039;&#039; to the unsigned integer &#039;&#039;length&#039;&#039; and can be used in a &#039;&#039;variable@shape&#039;&#039; to specify a length for an array dimension (see the section on &amp;lt;variable&amp;gt; below).  The dimension map is cleared when &amp;lt;/netcdf&amp;gt; is encountered (though this doesn&#039;t matter currently since we allow only one right now, but it will matter for aggregation, potentially).  We also do not support &amp;lt;group&amp;gt;, which is the only other legal place in NcML 2.2 for a dimension element.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* If the name and length are not both specified.&lt;br /&gt;
* If the dimension name already exists in the current scope&lt;br /&gt;
* If the length is not an unsigned integer&lt;br /&gt;
* If any of the other attributes specified in NcML 2.2 are used.  We do not handle them, so we consider them errors now.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;variable&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;variable&amp;gt; element is used to:&lt;br /&gt;
&lt;br /&gt;
* Provide lexical scope for a contained &amp;lt;attribute&amp;gt; or &amp;lt;variable&amp;gt; element&lt;br /&gt;
* Rename existing variables &lt;br /&gt;
* Add new scalar variables of simple types&lt;br /&gt;
* Add new Structure variables&lt;br /&gt;
* Add new N-dimensional Array&#039;s of simple types&lt;br /&gt;
* Specify the coordinate variable for the new dimension in a joinNew aggregation &lt;br /&gt;
&lt;br /&gt;
We describe each in turn in more detail.&lt;br /&gt;
&lt;br /&gt;
=== Specifying Lexical Scope with &amp;lt;variable type=&amp;quot;&amp;quot;&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Consider the following example:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;variable name=&amp;quot;u&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Metadata&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;This is metadata!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code assumes that a variable named &amp;quot;u&amp;quot; exists (of any type since we do not specify) and provides the lexical scope for the&lt;br /&gt;
attribute &amp;quot;Metadata&amp;quot; which will be added or modified within the attribute table for the variable &amp;quot;u&amp;quot; (it&#039;s qualified name would be &amp;quot;u.Metadata&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
==== Nested DAP Structure and Grid Scopes ====&lt;br /&gt;
&lt;br /&gt;
Scoping variable elements may be nested if the containing variable is a Structure (this includes the special case of Grid)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;DATA_GRANULE&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;PlanetaryGrid&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;variable name=&amp;quot;percipitate&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;inches&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This adds a &amp;quot;unit&amp;quot; attribute to the variable &amp;quot;percipitate&amp;quot; within the nested Structure&#039;s &lt;br /&gt;
(&amp;quot;DATA_GRANULE.PlanetaryGrid.percipitate&amp;quot; as fully qualified name).  &lt;br /&gt;
Note that we &#039;&#039;&#039;must&#039;&#039;&#039; refer to the type explicitly as a &amp;quot;Structure&amp;quot; so the parser knows&lt;br /&gt;
to traverse the tree.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; the variable might be of type Grid, but the type &amp;quot;Structure&amp;quot; must be used in the NcML to traverse it.&lt;br /&gt;
&lt;br /&gt;
==== Adding Multiple Attributes to the Same Variable ====&lt;br /&gt;
&lt;br /&gt;
Once the variable&#039;s scope is set by the opening &amp;lt;variable&amp;gt; element, more than one attribute can be specified within it.  This will make the NcML more readable and also will make the parsing more efficient since the variable will only need to be looked up once.&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_1&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Hello&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_2&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;World!&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
should be preferred over:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_1&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Hello&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_2&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;World!&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
although they produce the same result.  Any number of attributes can be specified before the variable is closed.&lt;br /&gt;
&lt;br /&gt;
=== Renaming Existing Variables ===&lt;br /&gt;
&lt;br /&gt;
The attribute &#039;&#039;variable@orgName&#039;&#039; is used to rename an existing variable. &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;NewName&amp;quot; orgName=&amp;quot;OldName&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing variable at the current scope named &amp;quot;OldName&amp;quot; to &amp;quot;NewName&amp;quot;.  After this point in the NcML file (such as in constraints specified for the DAP request), the variable is known by &amp;quot;NewName&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note that the type is not required here --- the variable is assumed to exist and its existing type is used.  It is not possible to change the type of an existing variable at this time!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:  &lt;br /&gt;
* If a variable with &#039;&#039;variable@orgName&#039;&#039; doesn&#039;t exist in the current scope&lt;br /&gt;
* If the new name &#039;&#039;variable@name&#039;&#039; is already taken in the current scope&lt;br /&gt;
* If a new variable is created but does not have exactly one values element&lt;br /&gt;
&lt;br /&gt;
=== Adding a New Scalar Variable ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;variable&amp;gt; element can be used to create a new scalar variable of a simple type (i.e. an atomic NcML type such as &amp;quot;int&amp;quot; or &amp;quot;float&amp;quot;, or any DAP atomic type, such as &amp;quot;UInt32&amp;quot; or &amp;quot;URL&amp;quot;) by specifying an empty &#039;&#039;variable@shape&#039;&#039; (which is the default), a simple type for &#039;&#039;variable@type&#039;&#039;, and a contained &amp;lt;values&amp;gt; element with the one value of correct type. &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;TheAnswerToLifeTheUniverseAndEverything&amp;quot; type=&amp;quot;double&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;SolvedBy&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;Deep Thought&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;values&amp;gt;42.000&amp;lt;/values&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create a new variable named &amp;quot;TheAnswerToLifeTheUniverseAndEverything&amp;quot; at the current scope.  It has no shape so will be a scalar of type &amp;quot;double&amp;quot; and will have the value 42.0.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* It is a parse error to not specify a &amp;lt;values&amp;gt; element with exactly one proper value of the variable type.&lt;br /&gt;
* It is a parse error to specify a malformed or out of bounds value for the data type&lt;br /&gt;
&lt;br /&gt;
=== Adding a New Structure Variable ===&lt;br /&gt;
&lt;br /&gt;
A new Structure variable can be specified at the global scope or within another Structure.  It is illegal for an array to have type structure, so the shape must be empty.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;MyNewStructure&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;MetaData&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;This is metadata!&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;ContainedScalar1&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&amp;lt;values&amp;gt;I live in a new structure!&amp;lt;/values&amp;gt;&amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;ContainedInt1&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;&amp;lt;values&amp;gt;42&amp;lt;/values&amp;gt;&amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
specifies a new structure called &amp;quot;MyNewStructure&amp;quot; which contains two scalar variable fields &amp;quot;ContainedScalar1&amp;quot; and &amp;quot;ContainedInt1&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
Nested structures are allowed as well.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Error&#039;&#039;&#039;: &lt;br /&gt;
* If another variable or attribute exists at the current scope with the new name.  &lt;br /&gt;
* If a &amp;lt;values&amp;gt; element is specified as a direct child of a new Structure --- structures cannot contain values, only attributes and other variables.&lt;br /&gt;
&lt;br /&gt;
=== Adding a New N-dimensional Array ===&lt;br /&gt;
&lt;br /&gt;
An N-dimensional array of a simple type may be created virtually as well by specifying a non-empty &#039;&#039;variable@shape&#039;&#039;.  The shape contains the array dimensions in left-to-right order of slowest varying dimension first.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;FloatArray&amp;quot; type=&amp;quot;float&amp;quot; shape=&amp;quot;2 5&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;!-- values specified in row major order (leftmost dimension in shape varies slowest) &lt;br /&gt;
	Any whitespace is a valid separator by default, so we can use newlines to pretty print 2D matrices.&lt;br /&gt;
	--&amp;gt;&lt;br /&gt;
      &amp;lt;values&amp;gt;&lt;br /&gt;
	0.1 0.2 0.3 0.4 0.5&lt;br /&gt;
	1.1 1.1 1.3 1.4 1.5&lt;br /&gt;
      &amp;lt;/values&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will specify a 2x5 dimension array of float values called &amp;quot;FloatArray&amp;quot;.  The &amp;lt;values&amp;gt; element must contain 2x5=10 values in row major order (slowest varying dimension first).  Since whitespace is the default separator, we use a newline to show the dimension boundary for the values, which is easy to see for a 2D matrix such as this.&lt;br /&gt;
&lt;br /&gt;
A dimension name may also be used to refer mnemonically to a length.  The DAP response will use this mnemonic in its output, but it is not currently used for shared dimensions, only as a mnemonic.   See the section on the &amp;lt;dimension&amp;gt; element for more information.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt;&lt;br /&gt;
 &amp;lt;dimension name=&amp;quot;station&amp;quot; length=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;dimension name=&amp;quot;sample&amp;quot; length=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;FloatArray&amp;quot; type=&amp;quot;float&amp;quot; shape=&amp;quot;station sample&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;values&amp;gt;&lt;br /&gt;
	0.1 0.2 0.3 0.4 0.5&lt;br /&gt;
	1.1 1.1 1.3 1.4 1.5&lt;br /&gt;
      &amp;lt;/values&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will produce the same 2x5 array, but will incorporate the dimension mnemonics into the response.  For example, here&#039;s the DDS response:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
     Float32 FloatArray[station = 2][samples = 5];&lt;br /&gt;
} sample_virtual_dataset.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;values&amp;gt; element respects the &#039;&#039;values@separator&#039;&#039; attribute if whitespace isn&#039;t correct.  This is very useful for arrays of strings with whitespace, for example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;StringArray&amp;quot; type=&amp;quot;string&amp;quot; shape=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;values separator=&amp;quot;*&amp;quot;&amp;gt;String 1*String 2*String 3&amp;lt;/values&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
creates a length 3 array of string StringArray = {&amp;quot;String 1&amp;quot;, &amp;quot;String 2&amp;quot;, &amp;quot;String 3&amp;quot;}.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:  &lt;br /&gt;
* It is an error to specify the incorrect number of values&lt;br /&gt;
* It is an error if any value is malformed or out of range for the data type.&lt;br /&gt;
* It is an error to specify a named dimension which does not exist in the current &amp;lt;netcdf&amp;gt; scope.&lt;br /&gt;
* It is an error to specify an Array whose flattened size (product of dimensions) is &amp;gt; 2^31-1.&lt;br /&gt;
&lt;br /&gt;
=== Specifying the new coordinate variable for a joinNew aggregation ===&lt;br /&gt;
&lt;br /&gt;
In the special case of a joinNew aggregation, the new coordinate variable may be specified with the &amp;lt;variable&amp;gt; element.  The new coordinate variable is &#039;&#039;defined&#039;&#039; to have the same name as the new dimension.  This allows for several things:&lt;br /&gt;
&lt;br /&gt;
*Explicit specification of the variable type and coordinates for the new dimension&lt;br /&gt;
*Specification of the metadata for the new coordinate variable &lt;br /&gt;
&lt;br /&gt;
In the first case, the author can specify explicitly the type of the new coordinate variable and the actual values for each dataset.  In this case, the variable &#039;&#039;must&#039;&#039; be specified &#039;&#039;after&#039;&#039; the aggregation element in the file so the new dimension&#039;s size (number of member datasets) may be known and error checking performed.  Metadata can also be added to the variable here.&lt;br /&gt;
&lt;br /&gt;
In the second case, the author may just specify the variable name, which allows one to specify the metadata for a coordinate variable that is automatically generated by the aggregation itself.  This is the only allowable case for a variable element to &#039;&#039;not&#039;&#039; contain a values element!  Coordinate variables are generated automatically in two cases:&lt;br /&gt;
&lt;br /&gt;
*The author has specified an explicit list of member datasets, with or without explicit coordVal attributes.  &lt;br /&gt;
*The author has used a &amp;lt;scan&amp;gt; element to specify the member datasets via a directory scan&lt;br /&gt;
&lt;br /&gt;
In this case, the &amp;lt;variable&amp;gt; element may come before or after the &amp;lt;aggregation&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*If an explicit variable is declared for the new coordinate variable:&lt;br /&gt;
** And it contains explicit values, the number of values must be equal to the number of member datasets in the aggregation.&lt;br /&gt;
** It must be specifed &#039;&#039;after&#039;&#039; the &amp;lt;aggregation&amp;gt; element&lt;br /&gt;
&lt;br /&gt;
* If a numeric coordVal is used to specify the first member dataset&#039;s coordinate, then &#039;&#039;all&#039;&#039; datasets must contain a numerical coordinate.&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variable (variableAgg) is not found in &#039;&#039;all&#039;&#039; member datasets.&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variable is not of the same type in &#039;&#039;all&#039;&#039; member datasets.  Coercion is &#039;&#039;not&#039;&#039; performed!&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variables in all member datasets do not have the same shape&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if an explicit coordinate variable is specified with a shape that is &#039;&#039;not&#039;&#039; the same as the new dimension name (and the variable name itself).&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;values&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;values&amp;gt; element can only be used in the context of a &#039;&#039;&#039;new&#039;&#039;&#039; variable of scalar or array type.  We cannot change the values for existing variables in this version of the handler. &lt;br /&gt;
The characters content of a &amp;lt;values&amp;gt; element is considered to be a separated list of value tokens valid for the type of the variable of the parent element.  The number of specified tokens in the content &#039;&#039;must&#039;&#039; equal the product of the dimensions of the enclosing &#039;&#039;variable@shape&#039;&#039;, or be one value for a scalar.  It is an error to &#039;&#039;not&#039;&#039; specify a &amp;lt;values&amp;gt; element for a declared new variable as well.  &lt;br /&gt;
&lt;br /&gt;
=== Changing the Separator Tokens === &lt;br /&gt;
&lt;br /&gt;
The author may specify values@separator to change the default value token separator from the default whitespace.  This is very useful for specifying arrays of strings with whitespace in them, or if data in CSV form is being pasted in.  &lt;br /&gt;
&lt;br /&gt;
=== Autogeneration of Uniform Arrays ===&lt;br /&gt;
&lt;br /&gt;
We also can parse &#039;&#039;values@start&#039;&#039; and &#039;&#039;values@increment&#039;&#039; INSTEAD OF tokens in the content.  This will &amp;quot;autogenerate&amp;quot; a uniform array of values of the given product of dimensions length for the containing variable.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Evens&amp;quot; type=&amp;quot;int&amp;quot; shape=&amp;quot;100&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;values start=&amp;quot;0&amp;quot; increment=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will specify an array of the first 100 even numbers (including 0).  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* If the incorrect number of tokens are specified for the containing variable&#039;s shape&lt;br /&gt;
* If any value token cannot be parsed as a valid value for the containing variable&#039;s type&lt;br /&gt;
* If content is specified in addition to start and increment&lt;br /&gt;
* If only one of start or increment is specified&lt;br /&gt;
* If the values element is placed anywhere except within a NEW variable.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;attribute&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
As an overview, whenever the parser encounters an &amp;lt;attribute&amp;gt; with a non-existing name (at the current scope),&lt;br /&gt;
it creates a new one, whether a container or atomic attribute (see below).  If the attribute exists,&lt;br /&gt;
its value and/or type is modified to those specified in the &amp;lt;attribute&amp;gt; element.  If an attribute&lt;br /&gt;
structure (container) exists, it is used to define a nested lexical scope for child attributes.  &lt;br /&gt;
&lt;br /&gt;
Attributes may be scalar (one value) or one dimensional arrays.  Arrays are specified by using whitespace (default) to separate the different values.  The attribute@separator may also be set in order to specify a different separator, such as CSV format or to specify a non-whitespace separator so strings with whitespace are not tokenized.  We will give examples of creating array attributes below.&lt;br /&gt;
&lt;br /&gt;
=== Adding New Attributes or Modifying an Existing Attribute ===&lt;br /&gt;
&lt;br /&gt;
If a specified attribute with the attribute@name does not exist at the current lexical scope, &lt;br /&gt;
a new one is created with the given type and value.  For example, assume &amp;quot;new_metadata&amp;quot; doesn&#039;t&lt;br /&gt;
exist at the current parse scope.  Then:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;new_metadata&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;This is a new entry!&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create the attribute at that scope.  Note that value can be specified in the content of the &lt;br /&gt;
element as well.  This is identical to the above:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;new_metadata&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;This is a new entry!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the attribute@name already exists at the scope, it is modified to contain the specified type and value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Arrays ====&lt;br /&gt;
&lt;br /&gt;
As in NcML, for numerical types an array can be specified by separating the tokens by whitespace (default) or be&lt;br /&gt;
specifying the token separator with attribute@separator.  For example,&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;myArray&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 2 3&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;myArray&amp;quot; type=&amp;quot;int&amp;quot; separator=&amp;quot;,&amp;quot;&amp;gt;1,2,3&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
both specify the same array of three integers named &amp;quot;myArray&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
TODO Add more information on splitting with a separator!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Structures (Containers) ====&lt;br /&gt;
&lt;br /&gt;
We use attribute@type=&amp;quot;Structure&amp;quot; to define a new (or existing) attribute container.   So if we&lt;br /&gt;
wanted to add a new attribute structure, we&#039;d use something like this: &lt;br /&gt;
&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;MySamples&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Location&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Station 1&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Samples&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 4 6&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assuming &amp;quot;MySamples&amp;quot; doesn&#039;t already exist, an attribute container will be created at the current scope&lt;br /&gt;
and the &amp;quot;Location&amp;quot; and &amp;quot;Samples&amp;quot; attributes will be added to it.&lt;br /&gt;
&lt;br /&gt;
Note that we can create nested attribute structures to arbitrary depth this way as well.&lt;br /&gt;
&lt;br /&gt;
If the attribute container with the given name already exists at the current scope, &lt;br /&gt;
then the attribute@type=&amp;quot;Structure&amp;quot; form is used to define&lt;br /&gt;
the lexical scope for the container.  In other words, child &amp;lt;attribute&amp;gt; elements will&lt;br /&gt;
be processed within the scope of the container.   For example, in the above example, if&lt;br /&gt;
&amp;quot;MySamples&amp;quot; already exists, then the &amp;quot;Location&amp;quot; and &amp;quot;Samples&amp;quot; will be processed within the&lt;br /&gt;
existing container (they may or may not already exist as well).&lt;br /&gt;
&lt;br /&gt;
==== Renaming an Existing Attribute or Attribute Container ====&lt;br /&gt;
&lt;br /&gt;
We also support the attribute@orgName attribute for renaming attributes.   &lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;NewName&amp;quot; orgName=&amp;quot;OldName&amp;quot; type=&amp;quot;string&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing attribute &amp;quot;OldName&amp;quot; to &amp;quot;NewName&amp;quot; while leaving its value alone.&lt;br /&gt;
If attribute@value is also specified, then the attribute is renamed &#039;&#039;and&#039;&#039; has its value modified.&lt;br /&gt;
&lt;br /&gt;
This works for renaming attribute containers as well:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;MyNewContainer&amp;quot; orgName=&amp;quot;MyOldContainer&amp;quot; type=&amp;quot;Structure&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing &amp;quot;MyOldContainer&amp;quot; to &amp;quot;MyNewContainer&amp;quot;.  Note that any children&lt;br /&gt;
of this container will remain in it.&lt;br /&gt;
&lt;br /&gt;
=== DAP &#039;&#039;OtherXML&#039;&#039; Extension ===&lt;br /&gt;
&lt;br /&gt;
The module now allows specification of attributes of the new DAP type &amp;quot;OtherXML&amp;quot;.  This allows the NCML file author to inject arbitrary well-formed XML into an attribute for clients that want XML metadata rather than just string or url.  Internally, the attribute is still a string (and in a DAP DAS response will be quoted inside one string).  However, since it is XML, the NCMLParser still parses it and checks it for well-formedness (but NOT against schemas).  This extension allows the NCMLParser to parse the arbitrary XML within the given attribute without causing errors, since it can be any XML.  &lt;br /&gt;
&lt;br /&gt;
The injected XML is most useful in the DDX response, where it shows up directly in the response as XML.  XSLT and other clients can then parse it.&lt;br /&gt;
&lt;br /&gt;
==== Errors ====&lt;br /&gt;
&lt;br /&gt;
*The XML &#039;&#039;&#039;must&#039;&#039;&#039; be in the content of the &amp;lt;attribute type=&amp;quot;OtherXML&amp;quot;&amp;gt; element.  It is a parser error for &#039;&#039;attribute@value&#039;&#039; to be set if &#039;&#039;attribute@type&#039;&#039; is &amp;quot;OtherXML&amp;quot;.  &lt;br /&gt;
*The XML must also be well-formed since it is parsed.  A parse error will be thrown if the OtherXML is malformed.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of the use of this special case.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf xmlns=&amp;quot;http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2&amp;quot; location=&amp;quot;/coverage/200803061600_HFRadar_USEGC_6km_rtv_SIO.nc&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;someName&amp;quot; type=&amp;quot;OtherXML&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;Domain xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot; &lt;br /&gt;
                xmlns:ows=&amp;quot;http://www.opengis.net/ows/1.1&amp;quot;&lt;br /&gt;
                xmlns:gml=&amp;quot;http://www.opengis.net/gml/3.2&amp;quot;&lt;br /&gt;
                &amp;gt;&lt;br /&gt;
            &amp;lt;SpatialDomain&amp;gt;&lt;br /&gt;
                &amp;lt;ows:BoundingBox crs=&amp;quot;urn:ogc:def:crs:EPSG::4326&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;ows:LowerCorner&amp;gt;-97.8839 21.736&amp;lt;/ows:LowerCorner&amp;gt;&lt;br /&gt;
                    &amp;lt;ows:UpperCorner&amp;gt;-57.2312 46.4944&amp;lt;/ows:UpperCorner&amp;gt;&lt;br /&gt;
                &amp;lt;/ows:BoundingBox&amp;gt;&lt;br /&gt;
            &amp;lt;/SpatialDomain&amp;gt;&lt;br /&gt;
            &amp;lt;TemporalDomain&amp;gt;&lt;br /&gt;
                &amp;lt;gml:timePosition&amp;gt;2008-03-27T16:00:00.000Z&amp;lt;/gml:timePosition&amp;gt;&lt;br /&gt;
            &amp;lt;/TemporalDomain&amp;gt;&lt;br /&gt;
        &amp;lt;/Domain&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedCRS xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;urn:ogc:def:crs:EPSG::4326&amp;lt;/SupportedCRS&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedFormat xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;netcdf-cf1.0&amp;lt;/SupportedFormat&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedFormat xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;dap2.0&amp;lt;/SupportedFormat&amp;gt;&lt;br /&gt;
    &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039; Put the DDX response for the above in here!&lt;br /&gt;
&lt;br /&gt;
====Namespace Closure====&lt;br /&gt;
&lt;br /&gt;
Furthermore, the parser will make the chunk of OtherXML &amp;quot;namespace closed&amp;quot;.  This means any namespaces specified in parent NCML elements of the OtherXML tree will be &amp;quot;brought down&amp;quot; and added to the &#039;&#039;root&#039;&#039; OtherXML elements so that the subtree may be pulled out and added to the DDX and still have its namespaces.  The algorithm doesn&#039;t just bring used prefixes, but brings &#039;&#039;all&#039;&#039; of the lexically scoped closest namespaces in all ancestors.  In other words, it adds unique namespaces (as determined by prefix) in order from the root of the OtherXML tree as it traverses to the root of the NCML document.  &lt;br /&gt;
&lt;br /&gt;
Namespace closure is a syntactic sugar that simplifies the author&#039;s task since they can specify the namespaces just once at the top of the NCML file and expect that when the subtree of XML is added to the DDX that these namespaces will come along with that subtree of XML.  Otherwise they have to explicitly add the namespaces to each attributes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039; Add an example!&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;remove&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;remove&amp;gt; element can remove attributes and variables.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;attribute name=&amp;quot;NC_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;remove name=&amp;quot;base_time&amp;quot; type=&amp;quot;attribute&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will remove the attribute named &amp;quot;base_time&amp;quot; in the attribute structure named &amp;quot;NC_GLOBAL&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Note that this works for attribute containers as well!  We could recursively remove the &#039;&#039;entire&#039;&#039;&lt;br /&gt;
attribute container (i.e. it and all its children) with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;remove name=&amp;quot;NC_GLOBAL&amp;quot; type=&amp;quot;attribute&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It also can be used to remove variables from existing datasets:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
  &amp;lt;remove name=&amp;quot;SomeExistingVariable&amp;quot; type=&amp;quot;variable&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This also recurses on variables of type Structure --- the entire structure including all of its children are removed from the dataset&#039;s response.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* It is a parse error if the given attribute or variable doesn&#039;t exist in the current scope&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;aggregation&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
Aggregation involves combining multiple datasets (&amp;lt;netcdf&amp;gt;) into a virtual &amp;quot;single&amp;quot; dataset in various ways.  For a tutorial on aggregation in NcML 2.2, the reader is referred to the Unidata page: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Aggregation.html&lt;br /&gt;
&lt;br /&gt;
NcML 2.2 supports multiple types of aggregation: union, joinNew, joinExisting, and fmrc (forecast model run collection).  &lt;br /&gt;
&lt;br /&gt;
The current version of the NcML module supports two of these aggregations:&lt;br /&gt;
&lt;br /&gt;
*Union [[NCML_Module_Aggregation_Union]]&lt;br /&gt;
*JoinNew [[NCML_Module_Aggregation_JoinNew]]&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;union&#039;&#039; aggregation specifies that the first instance of a variable or attribute (by name) that is found in the ordered list of datasets will be the one in the output aggregation.   This is useful for combining two dataset files, each which may contain a single variable, into a composite dataset with both variables.&lt;br /&gt;
&lt;br /&gt;
A JoinNew aggregation joins a variable which exists in multiple datasets (usually samples of a datum over time) into a new variable containing the data from &#039;&#039;all&#039;&#039; member datasets by creating a new outer dimension.  The &#039;&#039;i&#039;&#039;th component in the new outer dimension is the variable&#039;s data from the &#039;&#039;i&#039;&#039;th member dataset.  It also adds a new coordinate variable of whose name is the new dimension&#039;s name and whose shape (length) is the new dimension as well.  This new coordinate variable may be explicitly given by the author or may be autogenerated in one of several ways.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;scan&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The scan element can be used within an aggregation context to allow a directory to be searched in various ways in order to specify the members of an aggregation.  This allows a static NcML file to refer to an aggregation which may change over time, such as where a new data file is generated each day.&lt;br /&gt;
&lt;br /&gt;
We describe usage of the &amp;lt;scan&amp;gt; element in detail in the joinNew aggregation tutorial at [[NCML_Module_Aggregation_JoinNew]].&lt;br /&gt;
&lt;br /&gt;
= Errors =&lt;br /&gt;
&lt;br /&gt;
There are three types of error messages that may be returned:&lt;br /&gt;
&lt;br /&gt;
* Internal Error&lt;br /&gt;
* Resource Not Found Error&lt;br /&gt;
* Parse Error&lt;br /&gt;
&lt;br /&gt;
== Internal Errors ==&lt;br /&gt;
&#039;&#039;&#039;Internal errors&#039;&#039;&#039; should be reported to support@opendap.org as they are likely bugs.&lt;br /&gt;
&lt;br /&gt;
== Resource Not Found Errors ==&lt;br /&gt;
&lt;br /&gt;
If the netcdf@location specifies a non-existent local dataset (one that is not being served by&lt;br /&gt;
the same Hyrax server), it will specify the resource was not found.   This may also be returned&lt;br /&gt;
if a handler for the specified dataset is not currently loaded in the BES.  Users should test that the&lt;br /&gt;
dataset to be wrapped already exists and can be viewed on the running server before writing NcML &lt;br /&gt;
to add metadata.  It&#039;s also an error to refer to remote datasets (at this time).&lt;br /&gt;
&lt;br /&gt;
== Parse Errors ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse errors&#039;&#039;&#039; are user errors in the NcML file.  These could be malformed XML, malformed NcML, &lt;br /&gt;
unimplemented features of NcML, or could be errors in referring to the wrapped dataset.  &lt;br /&gt;
&lt;br /&gt;
The error message should specify &lt;br /&gt;
the error condition as well as the &amp;quot;current scope&amp;quot; as a fully qualified DAP name within the &lt;br /&gt;
loaded dataset.  This should be enough information to correct the parse error as new NcML&lt;br /&gt;
files are created.&lt;br /&gt;
&lt;br /&gt;
The parser will generate parse errors in various &lt;br /&gt;
situations where it expects to find certain structure in the underlying dataset.  Some examples:&lt;br /&gt;
&lt;br /&gt;
* A variable of the given name was not found at the current scope&lt;br /&gt;
* attribute@orgName was specified, but the attribute cannot be found at current scope.&lt;br /&gt;
* attribute@orgName was specified, but the new name is already used at current scope.&lt;br /&gt;
* remove specified a non-existing attribute name&lt;br /&gt;
&lt;br /&gt;
= Aggregation Tutorials =&lt;br /&gt;
&lt;br /&gt;
The NcML module may also be used to aggregate multiple datasets into one virtual dataset.  We currently support two of the NcML aggregtions:&lt;br /&gt;
&lt;br /&gt;
*Union [[NCML_Module_Aggregation_Union]]:  combine multiple datasets into one by merging variables together, selecting the first of each unique name.&lt;br /&gt;
*JoinNew [[NCML_Module_Aggregation_JoinNew]]: combine variables across multiple datasets by creating a new outer dimension and coordinate variable for each of the sample datasets.&lt;br /&gt;
&lt;br /&gt;
Please see the sections for a tutorial on the various uses of these aggregations.&lt;br /&gt;
&lt;br /&gt;
= Additions/Changes to NcML 2.2 =&lt;br /&gt;
&lt;br /&gt;
This section will keep track of changes to the NcML 2.2 schema.  Eventually these&lt;br /&gt;
will be rolled into a new schema.&lt;br /&gt;
&lt;br /&gt;
== Attribute Structures (Containers) ==&lt;br /&gt;
This module also adds functionality beyond the current NcML 2.2 schema&lt;br /&gt;
--- it can handle nested &amp;lt;attribute&amp;gt; elements in order to make&lt;br /&gt;
attribute structures.  This is done by using the &amp;lt;attribute&lt;br /&gt;
type=&amp;quot;Structure&amp;quot;&amp;gt; form, for example:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;MySamples&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Location&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Station 1&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Samples&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 4 6&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;MyContainer&amp;quot; describes an attribute structure with two attribute fields,&lt;br /&gt;
a string &amp;quot;Location&amp;quot; and an array of int&#039;s called &amp;quot;Samples&amp;quot;.  &lt;br /&gt;
Note that an attribute structure of this form can&lt;br /&gt;
only contain other &amp;lt;attribute&amp;gt; elements and NOT a value.&lt;br /&gt;
&lt;br /&gt;
If the container does not already exist, it will be created at the scope it is declared, which could&lt;br /&gt;
be:&lt;br /&gt;
&lt;br /&gt;
* Global (top of dataset)&lt;br /&gt;
* Within a variable&#039;s attribute table&lt;br /&gt;
* Within another attribute container&lt;br /&gt;
&lt;br /&gt;
If an attribute container of the given name already exists at the lexical scope, it is traversed &lt;br /&gt;
in order to define the scope for the nested (children) attributes it contains.&lt;br /&gt;
&lt;br /&gt;
== Unspecified Variable Type Matching for Lexical Scope ==&lt;br /&gt;
&lt;br /&gt;
We also allow the type attribute of a variable element (variable@type) to be the empty string &lt;br /&gt;
(or unspecified) when using existing variables to define the lexical scope of an &amp;lt;attribute&amp;gt; &lt;br /&gt;
transformation.  In the schema, variable@type is (normally) required.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DAP 2 Types ==&lt;br /&gt;
&lt;br /&gt;
Additionally, we allow DAP2 atomic types (such as UInt32, URL) in addition to the NcML types.  &lt;br /&gt;
The NcML types are mapped onto the closest DAP2 type internally.&lt;br /&gt;
&lt;br /&gt;
== DAP OtherXML Attribute Type ==&lt;br /&gt;
&lt;br /&gt;
We also allow attributes to be of the new DAP type &amp;quot;OtherXML&amp;quot; for injecting arbitrary XML into an attribute as content rather than trying to form a string.  This allows the parser to check well-formedness.&lt;br /&gt;
&lt;br /&gt;
== Forward Declaration of Dimensions ==&lt;br /&gt;
&lt;br /&gt;
Since we use a SAX parser for efficiency, we require the &amp;lt;dimension&amp;gt; elements to come &#039;&#039;before&#039;&#039; their use in a &#039;&#039;variable@shape&#039;&#039;.  One way to change the schema to allow this is to force the dimension elements to be specified in a sequence after explicit and metadata choice and before all other elements.&lt;br /&gt;
&lt;br /&gt;
== Aggregation Element Location and Processing Order Differences ==&lt;br /&gt;
&lt;br /&gt;
NcML specifies that if a dataset (&amp;lt;netcdf&amp;gt; element) specifies an aggregation element, the aggregation element is always processed first, regardless of its ordering within the &amp;lt;netcdf&amp;gt; element.  Our parser, since it is SAX and not DOM, modifies this behavior in that order matters in some cases:&lt;br /&gt;
&lt;br /&gt;
* Metadata (&amp;lt;attribute&amp;gt;) elements specified &#039;&#039;prior&#039;&#039; to an aggregation &amp;quot;shadow&amp;quot; the aggregation versions.  This is be useful for &amp;quot;overriding&amp;quot; an attribute or variable in a union aggregation, where the first found will take precedence. &lt;br /&gt;
* JoinNew: If the new coordinate variable&#039;s data is to be set explicitly by specifying the new dimension&#039;s shape (either with explicit data or the autogenerated data using values@start and values@increment attributes), the &amp;lt;variable&amp;gt; &#039;&#039;must&#039;&#039; come after the aggregation since the size of the dimension is unknown until the aggregation element is processed.&lt;br /&gt;
&lt;br /&gt;
= Backward Compatibility Issues =&lt;br /&gt;
&lt;br /&gt;
Due to the way shared dimensions were implemented in the NetCDF, HDF4, and HDF5 handlers, the DAS responses did not follow the DAP2 specification.  The NcML module, on the other hand, generates DAP2 compliant DAS for these datasets, which means that wrapping some datasets in NcML will generate a DAS with a different structure.  This is important for the NcML author since it changes the names of attributes and variables.  In order for the module to find the correct scope for adding metadata, for example, the DAP2 DAS must be used.  &lt;br /&gt;
&lt;br /&gt;
In general, what this means is that an empty &amp;quot;passthrough&amp;quot; NcML file should be the starting point for authoring an NcML file.  This file would just specify a dataset and nothing else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;/data/ncml/myNetcdf.nc&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The author would then request the DAS response for the NCML file and use that as the starting point for modifications to the original dataset. &lt;br /&gt;
&lt;br /&gt;
More explicit examples are given below.&lt;br /&gt;
&lt;br /&gt;
== NetCDF ==&lt;br /&gt;
&lt;br /&gt;
The NetCDF handler represents some NC datasets as a DAP 2 Grid, but the returned DAS is not consistent with the DAP 2 spec for the attribute hierarchy for such a Grid.  The map vector attributes are placed as siblings of the grid attributes rather than within the grid lexical scope.  For example, here&#039;s the NetCDF Handler DDS for a given file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Int16 cldc[time = 456][lat = 21][lon = 360];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 456];&lt;br /&gt;
        Float32 lat[lat = 21];&lt;br /&gt;
        Float32 lon[lon = 360];&lt;br /&gt;
    } cldc;&lt;br /&gt;
} cldc.mean.nc;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
showing the Grid.  Here&#039;s the DAS the NetCDF handler generates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    lat {&lt;br /&gt;
        String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
        String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
        Float32 actual_range 10.00000000, -10.00000000;&lt;br /&gt;
    }&lt;br /&gt;
    lon {&lt;br /&gt;
        String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
        String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
        Float32 actual_range 0.5000000000, 359.5000000;&lt;br /&gt;
    }&lt;br /&gt;
    time {&lt;br /&gt;
        String units &amp;quot;days since 1-1-1 00:00:0.0&amp;quot;;&lt;br /&gt;
        String long_name &amp;quot;Time&amp;quot;;&lt;br /&gt;
        String delta_t &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
        String avg_period &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
        Float64 actual_range 715511.00000000000, 729360.00000000000;&lt;br /&gt;
    }&lt;br /&gt;
    cldc {&lt;br /&gt;
        Float32 valid_range 0.000000000, 8.000000000;&lt;br /&gt;
        Float32 actual_range 0.000000000, 8.000000000;&lt;br /&gt;
        String units &amp;quot;okta&amp;quot;;&lt;br /&gt;
        Int16 precision 1;&lt;br /&gt;
        Int16 missing_value 32766;&lt;br /&gt;
        Int16 _FillValue 32766;&lt;br /&gt;
        String long_name &amp;quot;Cloudiness Monthly Mean at Surface&amp;quot;;&lt;br /&gt;
        String dataset &amp;quot;COADS 1-degree Equatorial Enhanced\\012AI&amp;quot;;&lt;br /&gt;
        String var_desc &amp;quot;Cloudiness\\012C&amp;quot;;&lt;br /&gt;
        String level_desc &amp;quot;Surface\\0120&amp;quot;;&lt;br /&gt;
        String statistic &amp;quot;Mean\\012M&amp;quot;;&lt;br /&gt;
        String parent_stat &amp;quot;Individual Obs\\012I&amp;quot;;&lt;br /&gt;
        Float32 add_offset 3276.500000;&lt;br /&gt;
        Float32 scale_factor 0.1000000015;&lt;br /&gt;
    }&lt;br /&gt;
    NC_GLOBAL {&lt;br /&gt;
        String title &amp;quot;COADS 1-degree Equatorial Enhanced&amp;quot;;&lt;br /&gt;
        String history &amp;quot;&amp;quot;;&lt;br /&gt;
        String Conventions &amp;quot;COARDS&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    DODS_EXTRA {&lt;br /&gt;
        String Unlimited_Dimension &amp;quot;time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the map vector attributes are in the &amp;quot;dataset&amp;quot; scope.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the DAS that the NcML Module produces from the correctly formed DDX:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    NC_GLOBAL {&lt;br /&gt;
        String title &amp;quot;COADS 1-degree Equatorial Enhanced&amp;quot;;&lt;br /&gt;
        String history &amp;quot;&amp;quot;;&lt;br /&gt;
        String Conventions &amp;quot;COARDS&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    DODS_EXTRA {&lt;br /&gt;
        String Unlimited_Dimension &amp;quot;time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    cldc {&lt;br /&gt;
        Float32 valid_range 0.000000000, 8.000000000;&lt;br /&gt;
        Float32 actual_range 0.000000000, 8.000000000;&lt;br /&gt;
        String units &amp;quot;okta&amp;quot;;&lt;br /&gt;
        Int16 precision 1;&lt;br /&gt;
        Int16 missing_value 32766;&lt;br /&gt;
        Int16 _FillValue 32766;&lt;br /&gt;
        String long_name &amp;quot;Cloudiness Monthly Mean at Surface&amp;quot;;&lt;br /&gt;
        String dataset &amp;quot;COADS 1-degree Equatorial Enhanced\\012AI&amp;quot;;&lt;br /&gt;
        String var_desc &amp;quot;Cloudiness\\012C&amp;quot;;&lt;br /&gt;
        String level_desc &amp;quot;Surface\\0120&amp;quot;;&lt;br /&gt;
        String statistic &amp;quot;Mean\\012M&amp;quot;;&lt;br /&gt;
        String parent_stat &amp;quot;Individual Obs\\012I&amp;quot;;&lt;br /&gt;
        Float32 add_offset 3276.500000;&lt;br /&gt;
        Float32 scale_factor 0.1000000015;&lt;br /&gt;
        cldc {&lt;br /&gt;
        }&lt;br /&gt;
        time {&lt;br /&gt;
            String units &amp;quot;days since 1-1-1 00:00:0.0&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;Time&amp;quot;;&lt;br /&gt;
            String delta_t &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
            String avg_period &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
            Float64 actual_range 715511.00000000000, 729360.00000000000;&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
            Float32 actual_range 10.00000000, -10.00000000;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
            Float32 actual_range 0.5000000000, 359.5000000;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here the Grid Structure &amp;quot;cldc&amp;quot;  and its contained data array (of the same name &amp;quot;cldc&amp;quot;) and map vectors have their own attribute containers as DAP 2 specifies.&lt;br /&gt;
&lt;br /&gt;
What this means for the author of an NcML file adding metadata to a NetCDF dataset that returns a Grid is that they should generate a &amp;quot;passthrough&amp;quot; file and get the DAS and then specify modifications based on that structure.  &lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example passthrough:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/cldc.mean.nc&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For example, to add an attribute to the map vector &amp;quot;lat&amp;quot; in the above, we&#039;d need the following NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/cldc.mean.nc&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;!-- Traverse into the Grid as a Structure --&amp;gt;&lt;br /&gt;
  &amp;lt;variable name=&amp;quot;cldc&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Traverse into the &amp;quot;lat&amp;quot; map vector (Array) --&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lat&amp;quot;&amp;gt; &lt;br /&gt;
      &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;I am a new attribute in the Grid map vector named lat!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lon&amp;quot;&amp;gt; &lt;br /&gt;
      &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;I am a new attribute in the Grid map vector named lon!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This clearly shows that the structure of the Grid must be used in the NcML:  the attribute being added is technically &amp;quot;cldc.lat.Description&amp;quot; in a fully qualified name.  The parser would return an error if it was attempted as &amp;quot;lat.Description&amp;quot; as the NetCDF DAS for the original file would have led one to believe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== HDF4/HDF5 ==&lt;br /&gt;
&lt;br /&gt;
Similarly to the NetCDF case, the Hyrax HDF4 Module produces DAS responses that do not respect the DAP2 specification.  If an NcML file is used to &amp;quot;wrap&amp;quot; an HDF4 dataset, the&lt;br /&gt;
correct DAP2 DAS response will be generated, however. &lt;br /&gt;
&lt;br /&gt;
This is important for those writing NcML for HDF4 data since the&lt;br /&gt;
lexical scope for attributes relies on the correct DAS form --- to&lt;br /&gt;
handle this, the user should start with a &amp;quot;passthrough&amp;quot; NcML file (see the above NetCDF example) and&lt;br /&gt;
use the DAS from that as the starting point for knowing the structure&lt;br /&gt;
the NcML handler expects to see in the NcML file.  Alternatively, the DDX has the &lt;br /&gt;
proper attribute structure as well (the DAS is generated from it).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Known Bugs =&lt;br /&gt;
&lt;br /&gt;
There are no known bugs currently.&lt;br /&gt;
&lt;br /&gt;
= Planned Future Enhancements =&lt;br /&gt;
&lt;br /&gt;
Planned enhancements for future versions of the module include:&lt;br /&gt;
&lt;br /&gt;
* New NcML Aggregations&lt;br /&gt;
** JoinExisting&lt;br /&gt;
*** Joins a variable across multiple datasets by appending the data for a given dimension from each dataset &lt;br /&gt;
*** Will also allow directory scans for specifying the aggregation&lt;br /&gt;
** Forecast Model Run Collection (FMRC)&lt;br /&gt;
*** Special case of JoinNew for forecast data with two time variables&lt;br /&gt;
*** See: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/FmrcAggregation.html&lt;br /&gt;
&lt;br /&gt;
= Copyright =&lt;br /&gt;
&lt;br /&gt;
This software is copyrighted under the GNU Lesser GPL.  Please see the&lt;br /&gt;
files COPYING and COPYRIGHT that came with this distribution.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=BES_-_Modules_-_NcML_Module&amp;diff=5591</id>
		<title>BES - Modules - NcML Module</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=BES_-_Modules_-_NcML_Module&amp;diff=5591"/>
		<updated>2010-04-20T19:33:08Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Features */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
[[Category:NCML]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Welcome to the OPeNDAP NcML Data Handler Module v1.0.1 for Hyrax 1.6!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[Updated for NcML Module v1.0.1 for Hyrax 1.6.0 beta --  8 April 2010]&lt;br /&gt;
&lt;br /&gt;
This module may be added to a Hyrax 1.6 server to extend its data&lt;br /&gt;
serving capability to NcML 2.2 files (see&lt;br /&gt;
http://www.unidata.ucar.edu/software/netcdf/ncml/).  NcML provides support for modifying other datasets in various ways, such as adding metadata and data and aggregating multiple datasets in several ways&lt;br /&gt;
&lt;br /&gt;
==Features==         &lt;br /&gt;
   &lt;br /&gt;
This current version (v1.0.1) currently implements a subset of NcML 2.2&lt;br /&gt;
functionality, along with some OPeNDAP extensions:&lt;br /&gt;
&lt;br /&gt;
* Metadata Manipulation&lt;br /&gt;
** Addition, Removal, and Modification of attributes to other datasets (NetCDF, HDF4, HD5, etc.) served by the same Hyrax 1.6 server&lt;br /&gt;
** Extends NcML 2.2 to allow for common nested &amp;quot;attribute containers&amp;quot; &lt;br /&gt;
** Attributes can be DAP2 types as well as the NcML types &lt;br /&gt;
** Attributes can be of the special &amp;quot;OtherXML&amp;quot; type for injecting arbitrary XML into a DDX response&lt;br /&gt;
* Data Manipulation&lt;br /&gt;
** Addition of new data variables (scalars or arrays of basic types as well as structures) &lt;br /&gt;
** Variables may be removed from the wrapped dataset&lt;br /&gt;
** Allows the creation of &amp;quot;pure virtual&amp;quot; datasets which do not wrap another dataset&lt;br /&gt;
* Aggregations: JoinNew and Union [[#Aggregation Tutorials]]&lt;br /&gt;
** JoinNew Aggregation &lt;br /&gt;
*** Allows multiple datasets to be &amp;quot;joined&amp;quot; by creating a new outer dimension for the aggregated variable&lt;br /&gt;
*** Aggregation member datasets can be listed explicitly with explicit coordinates for the new dimension for each member&lt;br /&gt;
*** Scan: Aggregations can be specified &amp;quot;automatically&amp;quot; by scanning a directory for files matching certain criteria, such as a suffix or regular expression.&lt;br /&gt;
*** Metadata may be added to the new coordinate variable for the new dimension&lt;br /&gt;
** Union Aggregation&lt;br /&gt;
*** Merges all member datasets into one by taking the first named instance of variables and metadata from the members&lt;br /&gt;
*** Useful for combining two or more datasets with different variables into a single set&lt;br /&gt;
&lt;br /&gt;
== Installation from Source ==&lt;br /&gt;
For information on how to build and install the NcML Data Module, please see the INSTALL file that came with the source distribution.&lt;br /&gt;
&lt;br /&gt;
= Installation Overview =&lt;br /&gt;
&lt;br /&gt;
The NcML Module requires a working Hyrax 1.6 installation.  It is a module&lt;br /&gt;
that is dynamically loaded into the Hyrax BES (Back End Server) to&lt;br /&gt;
allow it to handle NcML files.  &lt;br /&gt;
&lt;br /&gt;
Please see the file INSTALL for full build and install instructions as&lt;br /&gt;
well as requirements.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; After installation, you MUST restart Hyrax by restarting the BES and&lt;br /&gt;
OLFS so the NcML Module is loaded!&lt;br /&gt;
&lt;br /&gt;
== Requirement: International Components for Unicode (ICU) Library == &lt;br /&gt;
&lt;br /&gt;
The most important external requirement is an installation of the International Components for Unicode (ICU) version 3.6 or higher (tested up to 4.2.1).   The source distributions (as well as some binaries) may be found at the site: http://site.icu-project.org/download&lt;br /&gt;
&lt;br /&gt;
If you are using Linux RPM&#039;s to run Hyrax, you can get an RPM for ICU as well.  Search for the RPM named &amp;quot;libicu&amp;quot; using a package manager or yum, e.g.   If you are compiling the module from source, you will also need the RPM &amp;quot;libicu-devel&amp;quot; to get the headers installed.  &lt;br /&gt;
&lt;br /&gt;
If you install in the default locations, the ncml_module should find the libraries and headers.  Otherwise, please consult the INSTALL file for more information about installing ICU to a non-standard location.&lt;br /&gt;
&lt;br /&gt;
== Testing Installation ==&lt;br /&gt;
&lt;br /&gt;
Test data is provided to see if the installation was successful.  The file sample_virtual_dataset.ncml is a dataset purely created in NcML and doesn&#039;t contain an underlying dataset.  &lt;br /&gt;
You may also view fnoc1_improved.ncml to test adding attributes to an existing netCDF dataset (fnoc1.nc), but this requires the netCDF data handler to be&lt;br /&gt;
installed first!  Several other examples installed also use the HDF4 and HDF5 handlers.&lt;br /&gt;
&lt;br /&gt;
= Functionality =&lt;br /&gt;
&lt;br /&gt;
This version of the NcML Module implements a subset of NcML 2.2&lt;br /&gt;
functionality.  The reader is directed to http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/ for more information on NcML.&lt;br /&gt;
&lt;br /&gt;
Our module can currently:&lt;br /&gt;
&lt;br /&gt;
*Refer only to files being served locally (not remotely)&lt;br /&gt;
*Add, modify, and remove attribute metadata to a dataset&lt;br /&gt;
*Create a purely virtual dataset using just NcML and no underlying dataset&lt;br /&gt;
*Create new scalar variables of any simple NcML type or simple DAP type&lt;br /&gt;
*Create new Structure variables (which can contain new child variables)&lt;br /&gt;
*Create new N-dimensional arrays of simple types (NcML or DAP)&lt;br /&gt;
*Remove existing variables from a wrapped dataset&lt;br /&gt;
*Rename existing variables in a wrapped dataset&lt;br /&gt;
*Name dimensions as a mnemonic for specifying Array shapes&lt;br /&gt;
*Perform union aggregations on multiple datasets, virtual or wrapped or both&lt;br /&gt;
*Perform joinNew aggregations to merge a variable across multiple datasets by creating a new outer dimension&lt;br /&gt;
*Specify aggregation member datasets by scanning directories for files matching certain criteria&lt;br /&gt;
&lt;br /&gt;
We describe each supported NcML element in detail below.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;netcdf&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;netcdf&amp;gt; element is used to define a dataset, either a wrapped dataset that is to be modified, a pure virtual dataset, or a member dataset of an aggregation.  The &amp;lt;netcdf&amp;gt; element is assumed to be the topmost node, or as a child of an aggregation element.&lt;br /&gt;
&lt;br /&gt;
=== Local vs. Remote Datasets ===&lt;br /&gt;
&lt;br /&gt;
We assume that the location attribute (&#039;&#039;netcdf@location&#039;&#039;) refers to the full path (with respect to the BES data root directory) of a &#039;&#039;&#039;&#039;&#039;local&#039;&#039;&#039;&#039;&#039; dataset (served by the same Hyrax server).  The current version of the module cannot be used to modify remote datasets.&lt;br /&gt;
&lt;br /&gt;
If &#039;&#039;netcdf@location&#039;&#039; is the empty string (or unspecified, as empty is the default), the dataset is a pure virtual dataset, fully specified within the NcML file itself.  Attributes and variables may be fully described and accessed with constraints just as normal datasets in this manner.  The installed sample datafile &amp;quot;sample_virtual_dataset.ncml&amp;quot; is an example test case for this functionality.&lt;br /&gt;
&lt;br /&gt;
=== Unsupported Attributes ===&lt;br /&gt;
&lt;br /&gt;
The current version does not support the following attributes of &amp;lt;netcdf&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
*enhance&lt;br /&gt;
*addRecords&lt;br /&gt;
*fmrcDefinition (will be supported when FMRC aggregation is added)&lt;br /&gt;
*ncoords (will be supported when joinExisting is added)&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;readMetadata&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;readMetadata/&amp;gt; element is the default, so is effectively not needed.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;explicit&amp;gt; element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;explicit/&amp;gt; element simply clears all attribute tables in the referred to netcdf@location before applying the rest of the &lt;br /&gt;
NcML transformations to the metadata.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;dimension&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;dimension&amp;gt; element has limited functionality in this release since the DAP2 doesn&#039;t support dimensions as more than mnemonics at this time.  The limitations are:&lt;br /&gt;
&lt;br /&gt;
* We only parse the &#039;&#039;dimension@name&#039;&#039; and &#039;&#039;dimension@length&#039;&#039; attributes.  &lt;br /&gt;
* Dimensions can only be specified as a direct child of a &amp;lt;netcdf&amp;gt; element prior to any reference to them&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt; &lt;br /&gt;
  &amp;lt;dimension name=&amp;quot;station&amp;quot; length=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;dimension name=&amp;quot;samples&amp;quot; length=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;!-- Some variable elements refer to the dimensions here --&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The dimension element sets up a mapping from the &#039;&#039;name&#039;&#039; to the unsigned integer &#039;&#039;length&#039;&#039; and can be used in a &#039;&#039;variable@shape&#039;&#039; to specify a length for an array dimension (see the section on &amp;lt;variable&amp;gt; below).  The dimension map is cleared when &amp;lt;/netcdf&amp;gt; is encountered (though this doesn&#039;t matter currently since we allow only one right now, but it will matter for aggregation, potentially).  We also do not support &amp;lt;group&amp;gt;, which is the only other legal place in NcML 2.2 for a dimension element.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* If the name and length are not both specified.&lt;br /&gt;
* If the dimension name already exists in the current scope&lt;br /&gt;
* If the length is not an unsigned integer&lt;br /&gt;
* If any of the other attributes specified in NcML 2.2 are used.  We do not handle them, so we consider them errors now.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;variable&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;variable&amp;gt; element is used to:&lt;br /&gt;
&lt;br /&gt;
* Provide lexical scope for a contained &amp;lt;attribute&amp;gt; or &amp;lt;variable&amp;gt; element&lt;br /&gt;
* Rename existing variables &lt;br /&gt;
* Add new scalar variables of simple types&lt;br /&gt;
* Add new Structure variables&lt;br /&gt;
* Add new N-dimensional Array&#039;s of simple types&lt;br /&gt;
* Specify the coordinate variable for the new dimension in a joinNew aggregation &lt;br /&gt;
&lt;br /&gt;
We describe each in turn in more detail.&lt;br /&gt;
&lt;br /&gt;
=== Specifying Lexical Scope with &amp;lt;variable type=&amp;quot;&amp;quot;&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Consider the following example:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;variable name=&amp;quot;u&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Metadata&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;This is metadata!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code assumes that a variable named &amp;quot;u&amp;quot; exists (of any type since we do not specify) and provides the lexical scope for the&lt;br /&gt;
attribute &amp;quot;Metadata&amp;quot; which will be added or modified within the attribute table for the variable &amp;quot;u&amp;quot; (it&#039;s qualified name would be &amp;quot;u.Metadata&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
==== Nested DAP Structure and Grid Scopes ====&lt;br /&gt;
&lt;br /&gt;
Scoping variable elements may be nested if the containing variable is a Structure (this includes the special case of Grid)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;DATA_GRANULE&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;PlanetaryGrid&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;variable name=&amp;quot;percipitate&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;inches&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This adds a &amp;quot;unit&amp;quot; attribute to the variable &amp;quot;percipitate&amp;quot; within the nested Structure&#039;s &lt;br /&gt;
(&amp;quot;DATA_GRANULE.PlanetaryGrid.percipitate&amp;quot; as fully qualified name).  &lt;br /&gt;
Note that we &#039;&#039;&#039;must&#039;&#039;&#039; refer to the type explicitly as a &amp;quot;Structure&amp;quot; so the parser knows&lt;br /&gt;
to traverse the tree.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; the variable might be of type Grid, but the type &amp;quot;Structure&amp;quot; must be used in the NcML to traverse it.&lt;br /&gt;
&lt;br /&gt;
==== Adding Multiple Attributes to the Same Variable ====&lt;br /&gt;
&lt;br /&gt;
Once the variable&#039;s scope is set by the opening &amp;lt;variable&amp;gt; element, more than one attribute can be specified within it.  This will make the NcML more readable and also will make the parsing more efficient since the variable will only need to be looked up once.&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_1&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Hello&amp;quot;/&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_2&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;World!&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
should be preferred over:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_1&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Hello&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Foo&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;Attr_2&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;World!&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
although they produce the same result.  Any number of attributes can be specified before the variable is closed.&lt;br /&gt;
&lt;br /&gt;
=== Renaming Existing Variables ===&lt;br /&gt;
&lt;br /&gt;
The attribute &#039;&#039;variable@orgName&#039;&#039; is used to rename an existing variable. &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;NewName&amp;quot; orgName=&amp;quot;OldName&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing variable at the current scope named &amp;quot;OldName&amp;quot; to &amp;quot;NewName&amp;quot;.  After this point in the NcML file (such as in constraints specified for the DAP request), the variable is known by &amp;quot;NewName&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note that the type is not required here --- the variable is assumed to exist and its existing type is used.  It is not possible to change the type of an existing variable at this time!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:  &lt;br /&gt;
* If a variable with &#039;&#039;variable@orgName&#039;&#039; doesn&#039;t exist in the current scope&lt;br /&gt;
* If the new name &#039;&#039;variable@name&#039;&#039; is already taken in the current scope&lt;br /&gt;
* If a new variable is created but does not have exactly one values element&lt;br /&gt;
&lt;br /&gt;
=== Adding a New Scalar Variable ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;variable&amp;gt; element can be used to create a new scalar variable of a simple type (i.e. an atomic NcML type such as &amp;quot;int&amp;quot; or &amp;quot;float&amp;quot;, or any DAP atomic type, such as &amp;quot;UInt32&amp;quot; or &amp;quot;URL&amp;quot;) by specifying an empty &#039;&#039;variable@shape&#039;&#039; (which is the default), a simple type for &#039;&#039;variable@type&#039;&#039;, and a contained &amp;lt;values&amp;gt; element with the one value of correct type. &lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;TheAnswerToLifeTheUniverseAndEverything&amp;quot; type=&amp;quot;double&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;SolvedBy&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;Deep Thought&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;values&amp;gt;42.000&amp;lt;/values&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create a new variable named &amp;quot;TheAnswerToLifeTheUniverseAndEverything&amp;quot; at the current scope.  It has no shape so will be a scalar of type &amp;quot;double&amp;quot; and will have the value 42.0.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* It is a parse error to not specify a &amp;lt;values&amp;gt; element with exactly one proper value of the variable type.&lt;br /&gt;
* It is a parse error to specify a malformed or out of bounds value for the data type&lt;br /&gt;
&lt;br /&gt;
=== Adding a New Structure Variable ===&lt;br /&gt;
&lt;br /&gt;
A new Structure variable can be specified at the global scope or within another Structure.  It is illegal for an array to have type structure, so the shape must be empty.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;MyNewStructure&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;MetaData&amp;quot; type=&amp;quot;String&amp;quot; value=&amp;quot;This is metadata!&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;ContainedScalar1&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&amp;lt;values&amp;gt;I live in a new structure!&amp;lt;/values&amp;gt;&amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;ContainedInt1&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;&amp;lt;values&amp;gt;42&amp;lt;/values&amp;gt;&amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
specifies a new structure called &amp;quot;MyNewStructure&amp;quot; which contains two scalar variable fields &amp;quot;ContainedScalar1&amp;quot; and &amp;quot;ContainedInt1&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
Nested structures are allowed as well.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Error&#039;&#039;&#039;: &lt;br /&gt;
* If another variable or attribute exists at the current scope with the new name.  &lt;br /&gt;
* If a &amp;lt;values&amp;gt; element is specified as a direct child of a new Structure --- structures cannot contain values, only attributes and other variables.&lt;br /&gt;
&lt;br /&gt;
=== Adding a New N-dimensional Array ===&lt;br /&gt;
&lt;br /&gt;
An N-dimensional array of a simple type may be created virtually as well by specifying a non-empty &#039;&#039;variable@shape&#039;&#039;.  The shape contains the array dimensions in left-to-right order of slowest varying dimension first.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;FloatArray&amp;quot; type=&amp;quot;float&amp;quot; shape=&amp;quot;2 5&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;!-- values specified in row major order (leftmost dimension in shape varies slowest) &lt;br /&gt;
	Any whitespace is a valid separator by default, so we can use newlines to pretty print 2D matrices.&lt;br /&gt;
	--&amp;gt;&lt;br /&gt;
      &amp;lt;values&amp;gt;&lt;br /&gt;
	0.1 0.2 0.3 0.4 0.5&lt;br /&gt;
	1.1 1.1 1.3 1.4 1.5&lt;br /&gt;
      &amp;lt;/values&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will specify a 2x5 dimension array of float values called &amp;quot;FloatArray&amp;quot;.  The &amp;lt;values&amp;gt; element must contain 2x5=10 values in row major order (slowest varying dimension first).  Since whitespace is the default separator, we use a newline to show the dimension boundary for the values, which is easy to see for a 2D matrix such as this.&lt;br /&gt;
&lt;br /&gt;
A dimension name may also be used to refer mnemonically to a length.  The DAP response will use this mnemonic in its output, but it is not currently used for shared dimensions, only as a mnemonic.   See the section on the &amp;lt;dimension&amp;gt; element for more information.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt;&lt;br /&gt;
 &amp;lt;dimension name=&amp;quot;station&amp;quot; length=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;dimension name=&amp;quot;sample&amp;quot; length=&amp;quot;5&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;variable name=&amp;quot;FloatArray&amp;quot; type=&amp;quot;float&amp;quot; shape=&amp;quot;station sample&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;values&amp;gt;&lt;br /&gt;
	0.1 0.2 0.3 0.4 0.5&lt;br /&gt;
	1.1 1.1 1.3 1.4 1.5&lt;br /&gt;
      &amp;lt;/values&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will produce the same 2x5 array, but will incorporate the dimension mnemonics into the response.  For example, here&#039;s the DDS response:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
     Float32 FloatArray[station = 2][samples = 5];&lt;br /&gt;
} sample_virtual_dataset.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;values&amp;gt; element respects the &#039;&#039;values@separator&#039;&#039; attribute if whitespace isn&#039;t correct.  This is very useful for arrays of strings with whitespace, for example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;StringArray&amp;quot; type=&amp;quot;string&amp;quot; shape=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;values separator=&amp;quot;*&amp;quot;&amp;gt;String 1*String 2*String 3&amp;lt;/values&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
creates a length 3 array of string StringArray = {&amp;quot;String 1&amp;quot;, &amp;quot;String 2&amp;quot;, &amp;quot;String 3&amp;quot;}.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:  &lt;br /&gt;
* It is an error to specify the incorrect number of values&lt;br /&gt;
* It is an error if any value is malformed or out of range for the data type.&lt;br /&gt;
* It is an error to specify a named dimension which does not exist in the current &amp;lt;netcdf&amp;gt; scope.&lt;br /&gt;
* It is an error to specify an Array whose flattened size (product of dimensions) is &amp;gt; 2^31-1.&lt;br /&gt;
&lt;br /&gt;
=== Specifying the new coordinate variable for a joinNew aggregation ===&lt;br /&gt;
&lt;br /&gt;
In the special case of a joinNew aggregation, the new coordinate variable may be specified with the &amp;lt;variable&amp;gt; element.  The new coordinate variable is &#039;&#039;defined&#039;&#039; to have the same name as the new dimension.  This allows for several things:&lt;br /&gt;
&lt;br /&gt;
*Explicit specification of the variable type and coordinates for the new dimension&lt;br /&gt;
*Specification of the metadata for the new coordinate variable &lt;br /&gt;
&lt;br /&gt;
In the first case, the author can specify explicitly the type of the new coordinate variable and the actual values for each dataset.  In this case, the variable &#039;&#039;must&#039;&#039; be specified &#039;&#039;after&#039;&#039; the aggregation element in the file so the new dimension&#039;s size (number of member datasets) may be known and error checking performed.  Metadata can also be added to the variable here.&lt;br /&gt;
&lt;br /&gt;
In the second case, the author may just specify the variable name, which allows one to specify the metadata for a coordinate variable that is automatically generated by the aggregation itself.  This is the only allowable case for a variable element to &#039;&#039;not&#039;&#039; contain a values element!  Coordinate variables are generated automatically in two cases:&lt;br /&gt;
&lt;br /&gt;
*The author has specified an explicit list of member datasets, with or without explicit coordVal attributes.  &lt;br /&gt;
*The author has used a &amp;lt;scan&amp;gt; element to specify the member datasets via a directory scan&lt;br /&gt;
&lt;br /&gt;
In this case, the &amp;lt;variable&amp;gt; element may come before or after the &amp;lt;aggregation&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*If an explicit variable is declared for the new coordinate variable:&lt;br /&gt;
** And it contains explicit values, the number of values must be equal to the number of member datasets in the aggregation.&lt;br /&gt;
** It must be specifed &#039;&#039;after&#039;&#039; the &amp;lt;aggregation&amp;gt; element&lt;br /&gt;
&lt;br /&gt;
* If a numeric coordVal is used to specify the first member dataset&#039;s coordinate, then &#039;&#039;all&#039;&#039; datasets must contain a numerical coordinate.&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variable (variableAgg) is not found in &#039;&#039;all&#039;&#039; member datasets.&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variable is not of the same type in &#039;&#039;all&#039;&#039; member datasets.  Coercion is &#039;&#039;not&#039;&#039; performed!&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if the specified aggregation variables in all member datasets do not have the same shape&lt;br /&gt;
&lt;br /&gt;
* An error is thrown if an explicit coordinate variable is specified with a shape that is &#039;&#039;not&#039;&#039; the same as the new dimension name (and the variable name itself).&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;values&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;values&amp;gt; element can only be used in the context of a &#039;&#039;&#039;new&#039;&#039;&#039; variable of scalar or array type.  We cannot change the values for existing variables in this version of the handler. &lt;br /&gt;
The characters content of a &amp;lt;values&amp;gt; element is considered to be a separated list of value tokens valid for the type of the variable of the parent element.  The number of specified tokens in the content &#039;&#039;must&#039;&#039; equal the product of the dimensions of the enclosing &#039;&#039;variable@shape&#039;&#039;, or be one value for a scalar.  It is an error to &#039;&#039;not&#039;&#039; specify a &amp;lt;values&amp;gt; element for a declared new variable as well.  &lt;br /&gt;
&lt;br /&gt;
=== Changing the Separator Tokens === &lt;br /&gt;
&lt;br /&gt;
The author may specify values@separator to change the default value token separator from the default whitespace.  This is very useful for specifying arrays of strings with whitespace in them, or if data in CSV form is being pasted in.  &lt;br /&gt;
&lt;br /&gt;
=== Autogeneration of Uniform Arrays ===&lt;br /&gt;
&lt;br /&gt;
We also can parse &#039;&#039;values@start&#039;&#039; and &#039;&#039;values@increment&#039;&#039; INSTEAD OF tokens in the content.  This will &amp;quot;autogenerate&amp;quot; a uniform array of values of the given product of dimensions length for the containing variable.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;variable name=&amp;quot;Evens&amp;quot; type=&amp;quot;int&amp;quot; shape=&amp;quot;100&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;values start=&amp;quot;0&amp;quot; increment=&amp;quot;2&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will specify an array of the first 100 even numbers (including 0).  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* If the incorrect number of tokens are specified for the containing variable&#039;s shape&lt;br /&gt;
* If any value token cannot be parsed as a valid value for the containing variable&#039;s type&lt;br /&gt;
* If content is specified in addition to start and increment&lt;br /&gt;
* If only one of start or increment is specified&lt;br /&gt;
* If the values element is placed anywhere except within a NEW variable.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;attribute&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
As an overview, whenever the parser encounters an &amp;lt;attribute&amp;gt; with a non-existing name (at the current scope),&lt;br /&gt;
it creates a new one, whether a container or atomic attribute (see below).  If the attribute exists,&lt;br /&gt;
its value and/or type is modified to those specified in the &amp;lt;attribute&amp;gt; element.  If an attribute&lt;br /&gt;
structure (container) exists, it is used to define a nested lexical scope for child attributes.  &lt;br /&gt;
&lt;br /&gt;
Attributes may be scalar (one value) or one dimensional arrays.  Arrays are specified by using whitespace (default) to separate the different values.  The attribute@separator may also be set in order to specify a different separator, such as CSV format or to specify a non-whitespace separator so strings with whitespace are not tokenized.  We will give examples of creating array attributes below.&lt;br /&gt;
&lt;br /&gt;
=== Adding New Attributes or Modifying an Existing Attribute ===&lt;br /&gt;
&lt;br /&gt;
If a specified attribute with the attribute@name does not exist at the current lexical scope, &lt;br /&gt;
a new one is created with the given type and value.  For example, assume &amp;quot;new_metadata&amp;quot; doesn&#039;t&lt;br /&gt;
exist at the current parse scope.  Then:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;new_metadata&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;This is a new entry!&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create the attribute at that scope.  Note that value can be specified in the content of the &lt;br /&gt;
element as well.  This is identical to the above:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;new_metadata&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;This is a new entry!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the attribute@name already exists at the scope, it is modified to contain the specified type and value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Arrays ====&lt;br /&gt;
&lt;br /&gt;
As in NcML, for numerical types an array can be specified by separating the tokens by whitespace (default) or be&lt;br /&gt;
specifying the token separator with attribute@separator.  For example,&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;myArray&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 2 3&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;myArray&amp;quot; type=&amp;quot;int&amp;quot; separator=&amp;quot;,&amp;quot;&amp;gt;1,2,3&amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
both specify the same array of three integers named &amp;quot;myArray&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
TODO Add more information on splitting with a separator!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Structures (Containers) ====&lt;br /&gt;
&lt;br /&gt;
We use attribute@type=&amp;quot;Structure&amp;quot; to define a new (or existing) attribute container.   So if we&lt;br /&gt;
wanted to add a new attribute structure, we&#039;d use something like this: &lt;br /&gt;
&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;MySamples&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Location&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Station 1&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Samples&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 4 6&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assuming &amp;quot;MySamples&amp;quot; doesn&#039;t already exist, an attribute container will be created at the current scope&lt;br /&gt;
and the &amp;quot;Location&amp;quot; and &amp;quot;Samples&amp;quot; attributes will be added to it.&lt;br /&gt;
&lt;br /&gt;
Note that we can create nested attribute structures to arbitrary depth this way as well.&lt;br /&gt;
&lt;br /&gt;
If the attribute container with the given name already exists at the current scope, &lt;br /&gt;
then the attribute@type=&amp;quot;Structure&amp;quot; form is used to define&lt;br /&gt;
the lexical scope for the container.  In other words, child &amp;lt;attribute&amp;gt; elements will&lt;br /&gt;
be processed within the scope of the container.   For example, in the above example, if&lt;br /&gt;
&amp;quot;MySamples&amp;quot; already exists, then the &amp;quot;Location&amp;quot; and &amp;quot;Samples&amp;quot; will be processed within the&lt;br /&gt;
existing container (they may or may not already exist as well).&lt;br /&gt;
&lt;br /&gt;
==== Renaming an Existing Attribute or Attribute Container ====&lt;br /&gt;
&lt;br /&gt;
We also support the attribute@orgName attribute for renaming attributes.   &lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;NewName&amp;quot; orgName=&amp;quot;OldName&amp;quot; type=&amp;quot;string&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing attribute &amp;quot;OldName&amp;quot; to &amp;quot;NewName&amp;quot; while leaving its value alone.&lt;br /&gt;
If attribute@value is also specified, then the attribute is renamed &#039;&#039;and&#039;&#039; has its value modified.&lt;br /&gt;
&lt;br /&gt;
This works for renaming attribute containers as well:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;attribute name=&amp;quot;MyNewContainer&amp;quot; orgName=&amp;quot;MyOldContainer&amp;quot; type=&amp;quot;Structure&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will rename an existing &amp;quot;MyOldContainer&amp;quot; to &amp;quot;MyNewContainer&amp;quot;.  Note that any children&lt;br /&gt;
of this container will remain in it.&lt;br /&gt;
&lt;br /&gt;
=== DAP &#039;&#039;OtherXML&#039;&#039; Extension ===&lt;br /&gt;
&lt;br /&gt;
The module now allows specification of attributes of the new DAP type &amp;quot;OtherXML&amp;quot;.  This allows the NCML file author to inject arbitrary well-formed XML into an attribute for clients that want XML metadata rather than just string or url.  Internally, the attribute is still a string (and in a DAP DAS response will be quoted inside one string).  However, since it is XML, the NCMLParser still parses it and checks it for well-formedness (but NOT against schemas).  This extension allows the NCMLParser to parse the arbitrary XML within the given attribute without causing errors, since it can be any XML.  &lt;br /&gt;
&lt;br /&gt;
The injected XML is most useful in the DDX response, where it shows up directly in the response as XML.  XSLT and other clients can then parse it.&lt;br /&gt;
&lt;br /&gt;
==== Errors ====&lt;br /&gt;
&lt;br /&gt;
*The XML &#039;&#039;&#039;must&#039;&#039;&#039; be in the content of the &amp;lt;attribute type=&amp;quot;OtherXML&amp;quot;&amp;gt; element.  It is a parser error for &#039;&#039;attribute@value&#039;&#039; to be set if &#039;&#039;attribute@type&#039;&#039; is &amp;quot;OtherXML&amp;quot;.  &lt;br /&gt;
*The XML must also be well-formed since it is parsed.  A parse error will be thrown if the OtherXML is malformed.&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of the use of this special case.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf xmlns=&amp;quot;http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2&amp;quot; location=&amp;quot;/coverage/200803061600_HFRadar_USEGC_6km_rtv_SIO.nc&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;someName&amp;quot; type=&amp;quot;OtherXML&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;Domain xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot; &lt;br /&gt;
                xmlns:ows=&amp;quot;http://www.opengis.net/ows/1.1&amp;quot;&lt;br /&gt;
                xmlns:gml=&amp;quot;http://www.opengis.net/gml/3.2&amp;quot;&lt;br /&gt;
                &amp;gt;&lt;br /&gt;
            &amp;lt;SpatialDomain&amp;gt;&lt;br /&gt;
                &amp;lt;ows:BoundingBox crs=&amp;quot;urn:ogc:def:crs:EPSG::4326&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;ows:LowerCorner&amp;gt;-97.8839 21.736&amp;lt;/ows:LowerCorner&amp;gt;&lt;br /&gt;
                    &amp;lt;ows:UpperCorner&amp;gt;-57.2312 46.4944&amp;lt;/ows:UpperCorner&amp;gt;&lt;br /&gt;
                &amp;lt;/ows:BoundingBox&amp;gt;&lt;br /&gt;
            &amp;lt;/SpatialDomain&amp;gt;&lt;br /&gt;
            &amp;lt;TemporalDomain&amp;gt;&lt;br /&gt;
                &amp;lt;gml:timePosition&amp;gt;2008-03-27T16:00:00.000Z&amp;lt;/gml:timePosition&amp;gt;&lt;br /&gt;
            &amp;lt;/TemporalDomain&amp;gt;&lt;br /&gt;
        &amp;lt;/Domain&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedCRS xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;urn:ogc:def:crs:EPSG::4326&amp;lt;/SupportedCRS&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedFormat xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;netcdf-cf1.0&amp;lt;/SupportedFormat&amp;gt;&lt;br /&gt;
        &amp;lt;SupportedFormat xmlns=&amp;quot;http://www.opengis.net/wcs/1.1&amp;quot;&amp;gt;dap2.0&amp;lt;/SupportedFormat&amp;gt;&lt;br /&gt;
    &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039; Put the DDX response for the above in here!&lt;br /&gt;
&lt;br /&gt;
====Namespace Closure====&lt;br /&gt;
&lt;br /&gt;
Furthermore, the parser will make the chunk of OtherXML &amp;quot;namespace closed&amp;quot;.  This means any namespaces specified in parent NCML elements of the OtherXML tree will be &amp;quot;brought down&amp;quot; and added to the &#039;&#039;root&#039;&#039; OtherXML elements so that the subtree may be pulled out and added to the DDX and still have its namespaces.  The algorithm doesn&#039;t just bring used prefixes, but brings &#039;&#039;all&#039;&#039; of the lexically scoped closest namespaces in all ancestors.  In other words, it adds unique namespaces (as determined by prefix) in order from the root of the OtherXML tree as it traverses to the root of the NCML document.  &lt;br /&gt;
&lt;br /&gt;
Namespace closure is a syntactic sugar that simplifies the author&#039;s task since they can specify the namespaces just once at the top of the NCML file and expect that when the subtree of XML is added to the DDX that these namespaces will come along with that subtree of XML.  Otherwise they have to explicitly add the namespaces to each attributes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODO&#039;&#039;&#039; Add an example!&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;remove&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;remove&amp;gt; element can remove attributes and variables.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;attribute name=&amp;quot;NC_GLOBAL&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;remove name=&amp;quot;base_time&amp;quot; type=&amp;quot;attribute&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will remove the attribute named &amp;quot;base_time&amp;quot; in the attribute structure named &amp;quot;NC_GLOBAL&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Note that this works for attribute containers as well!  We could recursively remove the &#039;&#039;entire&#039;&#039;&lt;br /&gt;
attribute container (i.e. it and all its children) with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;remove name=&amp;quot;NC_GLOBAL&amp;quot; type=&amp;quot;attribute&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It also can be used to remove variables from existing datasets:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
  &amp;lt;remove name=&amp;quot;SomeExistingVariable&amp;quot; type=&amp;quot;variable&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This also recurses on variables of type Structure --- the entire structure including all of its children are removed from the dataset&#039;s response.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse Errors&#039;&#039;&#039;:&lt;br /&gt;
* It is a parse error if the given attribute or variable doesn&#039;t exist in the current scope&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;aggregation&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
Aggregation involves combining multiple datasets (&amp;lt;netcdf&amp;gt;) into a virtual &amp;quot;single&amp;quot; dataset in various ways.  For a tutorial on aggregation in NcML 2.2, the reader is referred to the Unidata page: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Aggregation.html&lt;br /&gt;
&lt;br /&gt;
NcML 2.2 supports multiple types of aggregation: union, joinNew, joinExisting, and fmrc (forecast model run collection).  &lt;br /&gt;
&lt;br /&gt;
The current version of the NcML module supports two of these aggregations:&lt;br /&gt;
&lt;br /&gt;
*Union [[NCML_Module_Aggregation_Union]]&lt;br /&gt;
*JoinNew [[NCML_Module_Aggregation_JoinNew]]&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;union&#039;&#039; aggregation specifies that the first instance of a variable or attribute (by name) that is found in the ordered list of datasets will be the one in the output aggregation.   This is useful for combining two dataset files, each which may contain a single variable, into a composite dataset with both variables.&lt;br /&gt;
&lt;br /&gt;
A JoinNew aggregation joins a variable which exists in multiple datasets (usually samples of a datum over time) into a new variable containing the data from &#039;&#039;all&#039;&#039; member datasets by creating a new outer dimension.  The &#039;&#039;i&#039;&#039;th component in the new outer dimension is the variable&#039;s data from the &#039;&#039;i&#039;&#039;th member dataset.  It also adds a new coordinate variable of whose name is the new dimension&#039;s name and whose shape (length) is the new dimension as well.  This new coordinate variable may be explicitly given by the author or may be autogenerated in one of several ways.&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;scan&amp;gt; Element ==&lt;br /&gt;
&lt;br /&gt;
The scan element can be used within an aggregation context to allow a directory to be searched in various ways in order to specify the members of an aggregation.  This allows a static NcML file to refer to an aggregation which may change over time, such as where a new data file is generated each day.&lt;br /&gt;
&lt;br /&gt;
We describe usage of the &amp;lt;scan&amp;gt; element in detail in the joinNew aggregation tutorial at [[NCML_Module_Aggregation_JoinNew]].&lt;br /&gt;
&lt;br /&gt;
= Errors =&lt;br /&gt;
&lt;br /&gt;
There are three types of error messages that may be returned:&lt;br /&gt;
&lt;br /&gt;
* Internal Error&lt;br /&gt;
* Resource Not Found Error&lt;br /&gt;
* Parse Error&lt;br /&gt;
&lt;br /&gt;
== Internal Errors ==&lt;br /&gt;
&#039;&#039;&#039;Internal errors&#039;&#039;&#039; should be reported to support@opendap.org as they are likely bugs.&lt;br /&gt;
&lt;br /&gt;
== Resource Not Found Errors ==&lt;br /&gt;
&lt;br /&gt;
If the netcdf@location specifies a non-existent local dataset (one that is not being served by&lt;br /&gt;
the same Hyrax server), it will specify the resource was not found.   This may also be returned&lt;br /&gt;
if a handler for the specified dataset is not currently loaded in the BES.  Users should test that the&lt;br /&gt;
dataset to be wrapped already exists and can be viewed on the running server before writing NcML &lt;br /&gt;
to add metadata.  It&#039;s also an error to refer to remote datasets (at this time).&lt;br /&gt;
&lt;br /&gt;
== Parse Errors ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parse errors&#039;&#039;&#039; are user errors in the NcML file.  These could be malformed XML, malformed NcML, &lt;br /&gt;
unimplemented features of NcML, or could be errors in referring to the wrapped dataset.  &lt;br /&gt;
&lt;br /&gt;
The error message should specify &lt;br /&gt;
the error condition as well as the &amp;quot;current scope&amp;quot; as a fully qualified DAP name within the &lt;br /&gt;
loaded dataset.  This should be enough information to correct the parse error as new NcML&lt;br /&gt;
files are created.&lt;br /&gt;
&lt;br /&gt;
The parser will generate parse errors in various &lt;br /&gt;
situations where it expects to find certain structure in the underlying dataset.  Some examples:&lt;br /&gt;
&lt;br /&gt;
* A variable of the given name was not found at the current scope&lt;br /&gt;
* attribute@orgName was specified, but the attribute cannot be found at current scope.&lt;br /&gt;
* attribute@orgName was specified, but the new name is already used at current scope.&lt;br /&gt;
* remove specified a non-existing attribute name&lt;br /&gt;
&lt;br /&gt;
= Aggregation Tutorials =&lt;br /&gt;
&lt;br /&gt;
The NcML module may also be used to aggregate multiple datasets into one virtual dataset.  We currently support two of the NcML aggregtions:&lt;br /&gt;
&lt;br /&gt;
*Union [[NCML_Module_Aggregation_Union]]:  combine multiple datasets into one by merging variables together, selecting the first of each unique name.&lt;br /&gt;
*JoinNew [[NCML_Module_Aggregation_JoinNew]]: combine variables across multiple datasets by creating a new outer dimension and coordinate variable for each of the sample datasets.&lt;br /&gt;
&lt;br /&gt;
Please see the sections for a tutorial on the various uses of these aggregations.&lt;br /&gt;
&lt;br /&gt;
= Additions/Changes to NcML 2.2 =&lt;br /&gt;
&lt;br /&gt;
This section will keep track of changes to the NcML 2.2 schema.  Eventually these&lt;br /&gt;
will be rolled into a new schema.&lt;br /&gt;
&lt;br /&gt;
== Attribute Structures (Containers) ==&lt;br /&gt;
This module also adds functionality beyond the current NcML 2.2 schema&lt;br /&gt;
--- it can handle nested &amp;lt;attribute&amp;gt; elements in order to make&lt;br /&gt;
attribute structures.  This is done by using the &amp;lt;attribute&lt;br /&gt;
type=&amp;quot;Structure&amp;quot;&amp;gt; form, for example:&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;attribute name=&amp;quot;MySamples&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Location&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;Station 1&amp;quot;/&amp;gt;&lt;br /&gt;
     &amp;lt;attribute name=&amp;quot;Samples&amp;quot; type=&amp;quot;int&amp;quot;&amp;gt;1 4 6&amp;lt;/attribute&amp;gt;&lt;br /&gt;
   &amp;lt;/attribute&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;MyContainer&amp;quot; describes an attribute structure with two attribute fields,&lt;br /&gt;
a string &amp;quot;Location&amp;quot; and an array of int&#039;s called &amp;quot;Samples&amp;quot;.  &lt;br /&gt;
Note that an attribute structure of this form can&lt;br /&gt;
only contain other &amp;lt;attribute&amp;gt; elements and NOT a value.&lt;br /&gt;
&lt;br /&gt;
If the container does not already exist, it will be created at the scope it is declared, which could&lt;br /&gt;
be:&lt;br /&gt;
&lt;br /&gt;
* Global (top of dataset)&lt;br /&gt;
* Within a variable&#039;s attribute table&lt;br /&gt;
* Within another attribute container&lt;br /&gt;
&lt;br /&gt;
If an attribute container of the given name already exists at the lexical scope, it is traversed &lt;br /&gt;
in order to define the scope for the nested (children) attributes it contains.&lt;br /&gt;
&lt;br /&gt;
== Unspecified Variable Type Matching for Lexical Scope ==&lt;br /&gt;
&lt;br /&gt;
We also allow the type attribute of a variable element (variable@type) to be the empty string &lt;br /&gt;
(or unspecified) when using existing variables to define the lexical scope of an &amp;lt;attribute&amp;gt; &lt;br /&gt;
transformation.  In the schema, variable@type is (normally) required.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== DAP 2 Types ==&lt;br /&gt;
&lt;br /&gt;
Additionally, we allow DAP2 atomic types (such as UInt32, URL) in addition to the NcML types.  &lt;br /&gt;
The NcML types are mapped onto the closest DAP2 type internally.&lt;br /&gt;
&lt;br /&gt;
== DAP OtherXML Attribute Type ==&lt;br /&gt;
&lt;br /&gt;
We also allow attributes to be of the new DAP type &amp;quot;OtherXML&amp;quot; for injecting arbitrary XML into an attribute as content rather than trying to form a string.  This allows the parser to check well-formedness.&lt;br /&gt;
&lt;br /&gt;
== Forward Declaration of Dimensions ==&lt;br /&gt;
&lt;br /&gt;
Since we use a SAX parser for efficiency, we require the &amp;lt;dimension&amp;gt; elements to come &#039;&#039;before&#039;&#039; their use in a &#039;&#039;variable@shape&#039;&#039;.  One way to change the schema to allow this is to force the dimension elements to be specified in a sequence after explicit and metadata choice and before all other elements.&lt;br /&gt;
&lt;br /&gt;
== Aggregation Element Location and Processing Order Differences ==&lt;br /&gt;
&lt;br /&gt;
NcML specifies that if a dataset (&amp;lt;netcdf&amp;gt; element) specifies an aggregation element, the aggregation element is always processed first, regardless of its ordering within the &amp;lt;netcdf&amp;gt; element.  Our parser, since it is SAX and not DOM, modifies this behavior in that order matters in some cases:&lt;br /&gt;
&lt;br /&gt;
* Metadata (&amp;lt;attribute&amp;gt;) elements specified &#039;&#039;prior&#039;&#039; to an aggregation &amp;quot;shadow&amp;quot; the aggregation versions.  This is be useful for &amp;quot;overriding&amp;quot; an attribute or variable in a union aggregation, where the first found will take precedence. &lt;br /&gt;
* JoinNew: If the new coordinate variable&#039;s data is to be set explicitly by specifying the new dimension&#039;s shape (either with explicit data or the autogenerated data using values@start and values@increment attributes), the &amp;lt;variable&amp;gt; &#039;&#039;must&#039;&#039; come after the aggregation since the size of the dimension is unknown until the aggregation element is processed.&lt;br /&gt;
&lt;br /&gt;
= Backward Compatibility Issues =&lt;br /&gt;
&lt;br /&gt;
Due to the way shared dimensions were implemented in the NetCDF, HDF4, and HDF5 handlers, the DAS responses did not follow the DAP2 specification.  The NcML module, on the other hand, generates DAP2 compliant DAS for these datasets, which means that wrapping some datasets in NcML will generate a DAS with a different structure.  This is important for the NcML author since it changes the names of attributes and variables.  In order for the module to find the correct scope for adding metadata, for example, the DAP2 DAS must be used.  &lt;br /&gt;
&lt;br /&gt;
In general, what this means is that an empty &amp;quot;passthrough&amp;quot; NcML file should be the starting point for authoring an NcML file.  This file would just specify a dataset and nothing else:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;/data/ncml/myNetcdf.nc&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The author would then request the DAS response for the NCML file and use that as the starting point for modifications to the original dataset. &lt;br /&gt;
&lt;br /&gt;
More explicit examples are given below.&lt;br /&gt;
&lt;br /&gt;
== NetCDF ==&lt;br /&gt;
&lt;br /&gt;
The NetCDF handler represents some NC datasets as a DAP 2 Grid, but the returned DAS is not consistent with the DAP 2 spec for the attribute hierarchy for such a Grid.  The map vector attributes are placed as siblings of the grid attributes rather than within the grid lexical scope.  For example, here&#039;s the NetCDF Handler DDS for a given file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Int16 cldc[time = 456][lat = 21][lon = 360];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float64 time[time = 456];&lt;br /&gt;
        Float32 lat[lat = 21];&lt;br /&gt;
        Float32 lon[lon = 360];&lt;br /&gt;
    } cldc;&lt;br /&gt;
} cldc.mean.nc;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
showing the Grid.  Here&#039;s the DAS the NetCDF handler generates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    lat {&lt;br /&gt;
        String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
        String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
        Float32 actual_range 10.00000000, -10.00000000;&lt;br /&gt;
    }&lt;br /&gt;
    lon {&lt;br /&gt;
        String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
        String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
        Float32 actual_range 0.5000000000, 359.5000000;&lt;br /&gt;
    }&lt;br /&gt;
    time {&lt;br /&gt;
        String units &amp;quot;days since 1-1-1 00:00:0.0&amp;quot;;&lt;br /&gt;
        String long_name &amp;quot;Time&amp;quot;;&lt;br /&gt;
        String delta_t &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
        String avg_period &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
        Float64 actual_range 715511.00000000000, 729360.00000000000;&lt;br /&gt;
    }&lt;br /&gt;
    cldc {&lt;br /&gt;
        Float32 valid_range 0.000000000, 8.000000000;&lt;br /&gt;
        Float32 actual_range 0.000000000, 8.000000000;&lt;br /&gt;
        String units &amp;quot;okta&amp;quot;;&lt;br /&gt;
        Int16 precision 1;&lt;br /&gt;
        Int16 missing_value 32766;&lt;br /&gt;
        Int16 _FillValue 32766;&lt;br /&gt;
        String long_name &amp;quot;Cloudiness Monthly Mean at Surface&amp;quot;;&lt;br /&gt;
        String dataset &amp;quot;COADS 1-degree Equatorial Enhanced\\012AI&amp;quot;;&lt;br /&gt;
        String var_desc &amp;quot;Cloudiness\\012C&amp;quot;;&lt;br /&gt;
        String level_desc &amp;quot;Surface\\0120&amp;quot;;&lt;br /&gt;
        String statistic &amp;quot;Mean\\012M&amp;quot;;&lt;br /&gt;
        String parent_stat &amp;quot;Individual Obs\\012I&amp;quot;;&lt;br /&gt;
        Float32 add_offset 3276.500000;&lt;br /&gt;
        Float32 scale_factor 0.1000000015;&lt;br /&gt;
    }&lt;br /&gt;
    NC_GLOBAL {&lt;br /&gt;
        String title &amp;quot;COADS 1-degree Equatorial Enhanced&amp;quot;;&lt;br /&gt;
        String history &amp;quot;&amp;quot;;&lt;br /&gt;
        String Conventions &amp;quot;COARDS&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    DODS_EXTRA {&lt;br /&gt;
        String Unlimited_Dimension &amp;quot;time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the map vector attributes are in the &amp;quot;dataset&amp;quot; scope.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the DAS that the NcML Module produces from the correctly formed DDX:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
    NC_GLOBAL {&lt;br /&gt;
        String title &amp;quot;COADS 1-degree Equatorial Enhanced&amp;quot;;&lt;br /&gt;
        String history &amp;quot;&amp;quot;;&lt;br /&gt;
        String Conventions &amp;quot;COARDS&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    DODS_EXTRA {&lt;br /&gt;
        String Unlimited_Dimension &amp;quot;time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    cldc {&lt;br /&gt;
        Float32 valid_range 0.000000000, 8.000000000;&lt;br /&gt;
        Float32 actual_range 0.000000000, 8.000000000;&lt;br /&gt;
        String units &amp;quot;okta&amp;quot;;&lt;br /&gt;
        Int16 precision 1;&lt;br /&gt;
        Int16 missing_value 32766;&lt;br /&gt;
        Int16 _FillValue 32766;&lt;br /&gt;
        String long_name &amp;quot;Cloudiness Monthly Mean at Surface&amp;quot;;&lt;br /&gt;
        String dataset &amp;quot;COADS 1-degree Equatorial Enhanced\\012AI&amp;quot;;&lt;br /&gt;
        String var_desc &amp;quot;Cloudiness\\012C&amp;quot;;&lt;br /&gt;
        String level_desc &amp;quot;Surface\\0120&amp;quot;;&lt;br /&gt;
        String statistic &amp;quot;Mean\\012M&amp;quot;;&lt;br /&gt;
        String parent_stat &amp;quot;Individual Obs\\012I&amp;quot;;&lt;br /&gt;
        Float32 add_offset 3276.500000;&lt;br /&gt;
        Float32 scale_factor 0.1000000015;&lt;br /&gt;
        cldc {&lt;br /&gt;
        }&lt;br /&gt;
        time {&lt;br /&gt;
            String units &amp;quot;days since 1-1-1 00:00:0.0&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;Time&amp;quot;;&lt;br /&gt;
            String delta_t &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
            String avg_period &amp;quot;0000-01-00 00:00:00&amp;quot;;&lt;br /&gt;
            Float64 actual_range 715511.00000000000, 729360.00000000000;&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
            Float32 actual_range 10.00000000, -10.00000000;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
            Float32 actual_range 0.5000000000, 359.5000000;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here the Grid Structure &amp;quot;cldc&amp;quot;  and its contained data array (of the same name &amp;quot;cldc&amp;quot;) and map vectors have their own attribute containers as DAP 2 specifies.&lt;br /&gt;
&lt;br /&gt;
What this means for the author of an NcML file adding metadata to a NetCDF dataset that returns a Grid is that they should generate a &amp;quot;passthrough&amp;quot; file and get the DAS and then specify modifications based on that structure.  &lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example passthrough:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/cldc.mean.nc&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For example, to add an attribute to the map vector &amp;quot;lat&amp;quot; in the above, we&#039;d need the following NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/cldc.mean.nc&amp;quot; title=&amp;quot;This file results in a Grid&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;!-- Traverse into the Grid as a Structure --&amp;gt;&lt;br /&gt;
  &amp;lt;variable name=&amp;quot;cldc&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Traverse into the &amp;quot;lat&amp;quot; map vector (Array) --&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lat&amp;quot;&amp;gt; &lt;br /&gt;
      &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;I am a new attribute in the Grid map vector named lat!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lon&amp;quot;&amp;gt; &lt;br /&gt;
      &amp;lt;attribute name=&amp;quot;Description&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;I am a new attribute in the Grid map vector named lon!&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This clearly shows that the structure of the Grid must be used in the NcML:  the attribute being added is technically &amp;quot;cldc.lat.Description&amp;quot; in a fully qualified name.  The parser would return an error if it was attempted as &amp;quot;lat.Description&amp;quot; as the NetCDF DAS for the original file would have led one to believe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== HDF4/HDF5 ==&lt;br /&gt;
&lt;br /&gt;
Similarly to the NetCDF case, the Hyrax HDF4 Module produces DAS responses that do not respect the DAP2 specification.  If an NcML file is used to &amp;quot;wrap&amp;quot; an HDF4 dataset, the&lt;br /&gt;
correct DAP2 DAS response will be generated, however. &lt;br /&gt;
&lt;br /&gt;
This is important for those writing NcML for HDF4 data since the&lt;br /&gt;
lexical scope for attributes relies on the correct DAS form --- to&lt;br /&gt;
handle this, the user should start with a &amp;quot;passthrough&amp;quot; NcML file (see the above NetCDF example) and&lt;br /&gt;
use the DAS from that as the starting point for knowing the structure&lt;br /&gt;
the NcML handler expects to see in the NcML file.  Alternatively, the DDX has the &lt;br /&gt;
proper attribute structure as well (the DAS is generated from it).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Known Bugs =&lt;br /&gt;
&lt;br /&gt;
There are no known bugs currently.&lt;br /&gt;
&lt;br /&gt;
= Planned Future Enhancements =&lt;br /&gt;
&lt;br /&gt;
Planned enhancements for future versions of the module include:&lt;br /&gt;
&lt;br /&gt;
* New NcML Aggregations&lt;br /&gt;
** JoinExisting&lt;br /&gt;
*** Joins a variable across multiple datasets by appending the data for a given dimension from each dataset &lt;br /&gt;
*** Will also allow directory scans for specifying the aggregation&lt;br /&gt;
** Forecast Model Run Collection (FMRC)&lt;br /&gt;
*** Special case of JoinNew for forecast data with two time variables&lt;br /&gt;
*** See: http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/FmrcAggregation.html&lt;br /&gt;
&lt;br /&gt;
= Copyright =&lt;br /&gt;
&lt;br /&gt;
This software is copyrighted under the GNU Lesser GPL.  Please see the&lt;br /&gt;
files COPYING and COPYRIGHT that came with this distribution.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Metadata_on_Aggregations_Tutorial&amp;diff=5590</id>
		<title>Metadata on Aggregations Tutorial</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Metadata_on_Aggregations_Tutorial&amp;diff=5590"/>
		<updated>2010-04-20T19:31:05Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Metadata Specification on the New Coordinate Variable */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Metadata Specification on the New Coordinate Variable ===&lt;br /&gt;
[[Category:Aggregation]]&lt;br /&gt;
[[Category:NCML]]&lt;br /&gt;
&lt;br /&gt;
We can add metadata to the new coordinate variable in two ways:&lt;br /&gt;
&lt;br /&gt;
* Adding it to the &amp;lt;variable&amp;gt; element directly in the case where the new coordinate variable and values is defined explicitly&lt;br /&gt;
* Adding the metadata to an &#039;&#039;automatically created&#039;&#039; coordinate variable by leaving the &amp;lt;values&amp;gt; element out&lt;br /&gt;
&lt;br /&gt;
The first case we have already seen, but we will show it again explicitly.  The second case is a little different and we&#039;ll cover it separately.&lt;br /&gt;
&lt;br /&gt;
==== Adding Metadata to the Explicit New Coordinate Variable ====&lt;br /&gt;
&lt;br /&gt;
We have already seen examples of explicitly defining the new coordinate variable and giving its values.  In these cases, the metadata is added to the new coordinate variable exactly like any other variable.  Let&#039;s see the example again:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinNew Grid aggregation with explicit map&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;sample_time&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182183448.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183065853.hdf&amp;quot;/&amp;gt;  &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183182355.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;variable name=&amp;quot;sample_time&amp;quot; shape=&amp;quot;sample_time&amp;quot; type=&amp;quot;float&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Metadata here will also show up in the Grid map --&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;Days since 01/01/2010&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;values&amp;gt;100 200 400 1000&amp;lt;/values&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that the &#039;&#039;&#039;units&#039;&#039;&#039; attribute for the new coordinate variable has been specified.  This subset of the DAS (we don&#039;t show the extensive global metadata) shows this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
        sample_time {&lt;br /&gt;
 ---&amp;gt;           String units &amp;quot;Days since 01/01/2010&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    sample_time {&lt;br /&gt;
---&amp;gt;        String units &amp;quot;Days since 01/01/2010&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We show the new metadata with the &amp;quot;---&amp;gt;&amp;quot; marker.  Note that the metadata for the coordinate variable is also copied into the new map vector of the aggregated Grid.&lt;br /&gt;
&lt;br /&gt;
Metadata can be specified in this way for &#039;&#039;any&#039;&#039; case where the new coordinate variable is listed explicitly.  &lt;br /&gt;
&lt;br /&gt;
==== Adding Metadata to An Autogenerated Coordinate Variable ====&lt;br /&gt;
&lt;br /&gt;
If we expect the coordinate variable to be automatically added, we can also specify its metadata by referring to the variable without setting its values.  This is useful in the case of using &#039;&#039;netcdf@coordValue&#039;&#039; and we will also see it is very useful when using a &amp;lt;scan&amp;gt; element for dynamic aggregations.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s a trivial  example using the default  case of the filename:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;Test of adding metadata to the new map vector in a joinNew Grid aggregation&amp;quot;&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- &lt;br /&gt;
       Add metadata to the created new outer dimension variable after&lt;br /&gt;
       the aggregation is defined by using a placeholder variable&lt;br /&gt;
       whose values will be defined automatically by the aggregation.&lt;br /&gt;
  --&amp;gt;  &lt;br /&gt;
  &amp;lt;variable type=&amp;quot;string&amp;quot; name=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;Filename of the dataset&amp;lt;/attribute&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note here that we just neglected to add a &amp;lt;values&amp;gt; element since we want the values to be generated automatically by the aggregation.  Note also that this is &#039;&#039;almost&#039;&#039; the same way we&#039;d modify an existing variable&#039;s metadata.  The only difference is we need to &amp;quot;declare&amp;quot; the type of the variable here since technically the variable specified here is a placeholder for the generated coordinate variable.  So after the aggregation is specified, we are simply modifying the created variable&#039;s metadata, in this case the newly generated map vector.&lt;br /&gt;
&lt;br /&gt;
Here is the DAS portion with just the aggregated Grid and the new coordinate variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
        filename {&lt;br /&gt;
            String units &amp;quot;Filename of the dataset&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    filename {&lt;br /&gt;
        String units &amp;quot;Filename of the dataset&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here also the map vector gets a copy of the coordinate variable&#039;s metadata.&lt;br /&gt;
&lt;br /&gt;
We can also use this syntax in the case that &#039;&#039;netcdf@coordValue&#039;&#039; was used to autogenerate the coordinate variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinNew Grid aggregation with coordValue and metadata&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;sample_time&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; coordValue=&amp;quot;1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182183448.hdf&amp;quot; coordValue=&amp;quot;10&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183065853.hdf&amp;quot; coordValue=&amp;quot;15&amp;quot;/&amp;gt;  &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183182355.hdf&amp;quot; coordValue=&amp;quot;25&amp;quot;/&amp;gt; &lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;!-- Note: values are contrived --&amp;gt;&lt;br /&gt;
  &amp;lt;variable name=&amp;quot;sample_time&amp;quot; shape=&amp;quot;sample_time&amp;quot; type=&amp;quot;double&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;Days since 01/01/2010&amp;lt;/attribute&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we see the metadata added to the new coordinate variable and associated map vector:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
   dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
        sample_time {&lt;br /&gt;
 ---&amp;gt;           String units &amp;quot;Days since 01/01/2010&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    sample_time {&lt;br /&gt;
---&amp;gt;        String units &amp;quot;Days since 01/01/2010&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Parse Errors ====&lt;br /&gt;
&lt;br /&gt;
Since the processing of the aggregation takes a few steps, care must be taken in specifying the coordinate variable in the cases of autogenerated variables.  &lt;br /&gt;
&lt;br /&gt;
In particular, it is a Parse Error:&lt;br /&gt;
&lt;br /&gt;
* To specify the shape of the autogenerated coordinate variable if &amp;lt;values&amp;gt; are not set&lt;br /&gt;
* To leave out the type or to use a type that does not match the autogenerated type&lt;br /&gt;
&lt;br /&gt;
The second can be somewhat tricky to remember since for existing variables it can be safely left out and the variable will be &amp;quot;found&amp;quot;.  Since aggregations get processed fulled when the &amp;lt;netcdf&amp;gt; element containing them is closed, the specified coordinate variables in these cases are &#039;&#039;placeholders&#039;&#039; for the automatically generated variables, so they must match the name and type, but not specify a shape since the shape (size of the new aggregation dimension) is not known until this occurs.&lt;br /&gt;
&lt;br /&gt;
=== Metadata Specification on the Aggregation Variable Itself ===&lt;br /&gt;
&lt;br /&gt;
It is also possible to add or modify the attributes on the aggregation variable itself.  If it is a Grid, metadata can be modified on the contained array or maps as well.  Note that the aggregated variable begins with the metadata &#039;&#039;from the first dataset specified in the aggregation&#039;&#039; just like in a union aggregation.&lt;br /&gt;
&lt;br /&gt;
We will use a Grid as our primary example since other datatypes are similar and simpler and this case will cover those as well.&lt;br /&gt;
&lt;br /&gt;
==== An Aggregated Grid example ====&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start from this example aggregation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt; &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182183448.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183065853.hdf&amp;quot;/&amp;gt;  &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183182355.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is the DAS for this unmodifed aggregated Grid (with the global dataset metadata removed):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
   dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
        filename {&lt;br /&gt;
        }&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    filename {&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will now add attributes to all the existing parts of the Grid: &lt;br /&gt;
&lt;br /&gt;
* The Grid Structure itself&lt;br /&gt;
* The Array of data within the Grid&lt;br /&gt;
* Both existing map vectors (&#039;&#039;&#039;lat&#039;&#039;&#039; and &#039;&#039;&#039;lon&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
We have already seen how to add data to the new coordinate variable as well.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the NcML we will use.  Note we have added units data to the subparts of the Grid, and also added some metadata to the grid itself.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;Showing how to add metadata to all parts of an aggregated grid&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182183448.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183065853.hdf&amp;quot;/&amp;gt;  &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183182355.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;variable name=&amp;quot;dsp_band_1&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt; &amp;lt;!-- Enter the Grid level scope --&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
1)  &amp;lt;attribute name=&amp;quot;Info&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;This is metadata on the Grid itself.&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;variable name=&amp;quot;dsp_band_1&amp;quot;&amp;gt; &amp;lt;!-- Enter the scope of the Array dsp_band_1 --&amp;gt;&lt;br /&gt;
2)    &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;Temp (packed)&amp;lt;/attribute&amp;gt; &amp;lt;!-- Units of the array --&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt; &amp;lt;!-- dsp_band_1.dsp_band_1 --&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lat&amp;quot;&amp;gt; &amp;lt;!-- dsp_band_1.lat map --&amp;gt;&lt;br /&gt;
3)    &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;degrees_north&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt; &lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lon&amp;quot;&amp;gt; &amp;lt;!-- dsp_band_1.lon map --&amp;gt;&lt;br /&gt;
4)    &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;degrees_east&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt; &amp;lt;!-- dsp_band_1.lon map --&amp;gt;    &lt;br /&gt;
  &amp;lt;/variable&amp;gt; &amp;lt;!-- dsp_band_1 Grid --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Note well: this is a new coordinate variable so requires the correct type.&lt;br /&gt;
  Also note that it falls outside of the actual grid since we must specify it &lt;br /&gt;
  as a sibling coordinate variable it will be made into a Grid when the netcdf is closed. &lt;br /&gt;
  --&amp;gt;&lt;br /&gt;
  &amp;lt;variable name=&amp;quot;filename&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&lt;br /&gt;
5)  &amp;lt;attribute name=&amp;quot;Info&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;Filename with timestamp&amp;lt;/attribute&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt; &amp;lt;!-- filename --&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;/netcdf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we show metadata being injected in several ways, denoted by the 1) -- 5) notations.&lt;br /&gt;
&lt;br /&gt;
1) We are inside the scope of the top-level Grid variable, so this metadata will show up in the attribute table inside the Grid Structure.&lt;br /&gt;
2) This is the actual data Array of the Grid, &#039;&#039;&#039;dsp_band_1.dsp_band_1&#039;&#039;&#039;.  We specify the units are a packed temperature.&lt;br /&gt;
3) Here we are in the scope of a map variable, &#039;&#039;&#039;dsp_band_1.lat&#039;&#039;&#039;.  We add the units specification to this map.&lt;br /&gt;
4) Likewise, we add units to the &#039;&#039;&#039;lon&#039;&#039;&#039; map vector.&lt;br /&gt;
5) Finally, we must close the actual grid and specify the metadata for the &#039;&#039;NEW&#039;&#039; coordinate variable as a sibling of the Grid since this will be used as the canonical prototype to be added to all Grid&#039;s which are to be aggregated on the new dimension.  Note in this case (unlike previous cases) the type of the new coordinate variable is required since we are specifying a &amp;quot;placeholder&amp;quot; variable for the new map until the Grid is actually processed once its containing &amp;lt;netcdf&amp;gt; is closed (i.e. all data is available to it).&lt;br /&gt;
&lt;br /&gt;
The resulting DAS (with global dataset metadata removed for clarity):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attribute {&lt;br /&gt;
... global data clipped ...&lt;br /&gt;
  dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
 1)   String Info &amp;quot;This is metadata on the Grid itself.&amp;quot;;&lt;br /&gt;
        filename {&lt;br /&gt;
 5)       String Info &amp;quot;Filename with timestamp&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
2)        String units &amp;quot;Temp (packed)&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
3)        String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
4)        String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    filename {&lt;br /&gt;
5)    String Info &amp;quot;Filename with timestamp&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have annotated the DAS with numbers representing which lines in the NcML above correspond to the injected metadata.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=JoinNew_Explicit_Dataset_Tutorial&amp;diff=5589</id>
		<title>JoinNew Explicit Dataset Tutorial</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=JoinNew_Explicit_Dataset_Tutorial&amp;diff=5589"/>
		<updated>2010-04-20T19:30:40Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Default Values for the New Coordinate Variable (on a Grid) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Default Values for the New Coordinate Variable (on a Grid) ===&lt;br /&gt;
[[Category:Aggregation]]&lt;br /&gt;
[[Category:NCML]]&lt;br /&gt;
&lt;br /&gt;
The default for the new coordinate variable is to be of type String with the location of the dataset as the value.  For example, the following NcML file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;Simple test of joinNew Grid aggregation&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182183448.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183065853.hdf&amp;quot;/&amp;gt;  &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183182355.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
specifies an aggregation on a Grid variable &#039;&#039;&#039;dsp_band_1&#039;&#039;&#039; sampled in four HDF4 datasets listed explicitly.&lt;br /&gt;
&lt;br /&gt;
First, the data structure (DDS) is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        UInt32 dsp_band_1[filename = 4][lat = 1024][lon = 1024];&lt;br /&gt;
      Maps:&lt;br /&gt;
        String filename[filename = 4];&lt;br /&gt;
        Float64 lat[1024];&lt;br /&gt;
        Float64 lon[1024];&lt;br /&gt;
    } dsp_band_1;&lt;br /&gt;
    String filename[filename = 4];&lt;br /&gt;
} joinNew_grid.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see the aggregated variable &#039;&#039;&#039;dsp_band_1&#039;&#039;&#039; has the new outer dimension &#039;&#039;filename&#039;&#039;.  A coordinate variable &#039;&#039;filename[filename]&#039; was created as a sibling of the aggregated variable (the top level Grid we specified) and was also copied into the aggregated Grid as a new map vector.&lt;br /&gt;
&lt;br /&gt;
The ASCII data response for just the new coordinate variable &#039;&#039;filename[filename]&#039;&#039; is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
String filename[filename = 4] = {&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;, &lt;br /&gt;
&amp;quot;data/ncml/agg/grids/f97182183448.hdf&amp;quot;, &lt;br /&gt;
&amp;quot;data/ncml/agg/grids/f97183065853.hdf&amp;quot;, &lt;br /&gt;
&amp;quot;data/ncml/agg/grids/f97183182355.hdf&amp;quot;};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that the absolute location we specified for the dataset as a String is the value for each element of the new coordinate variable.&lt;br /&gt;
&lt;br /&gt;
The newly added map &#039;&#039;&#039;dsp_band_1.filename&#039;&#039;&#039; contains a copy of this data.&lt;br /&gt;
&lt;br /&gt;
=== Explicitly Specifying the New Coordinate Variable ===&lt;br /&gt;
&lt;br /&gt;
If the author wishes to have the new coordinate variable be of a specific data type with non-uniform values, then they must specify the new coordinate variable explicitly.&lt;br /&gt;
&lt;br /&gt;
==== Array Virtual Dataset ====&lt;br /&gt;
Here&#039;s an example using a contrived pure virtual dataset:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;JoinNew on Array with Explicit Map&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- joinNew and form new outer dimension &amp;quot;day&amp;quot; --&amp;gt;&lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;day&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;V&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;netcdf title=&amp;quot;Slice 1&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;dimension name=&amp;quot;sensors&amp;quot; length=&amp;quot;3&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;variable name=&amp;quot;V&amp;quot; type=&amp;quot;int&amp;quot; shape=&amp;quot;sensors&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;values&amp;gt;1 2 3&amp;lt;/values&amp;gt;&lt;br /&gt;
      &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;netcdf title=&amp;quot;Slice 2&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;dimension name=&amp;quot;sensors&amp;quot; length=&amp;quot;3&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;variable name=&amp;quot;V&amp;quot; type=&amp;quot;int&amp;quot; shape=&amp;quot;sensors&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;values&amp;gt;4 5 6&amp;lt;/values&amp;gt;&lt;br /&gt;
      &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- This is recognized as the definition of the new coordinate variable, &lt;br /&gt;
       since it has the form day[day] where day is the dimName for the aggregation. &lt;br /&gt;
       It MUST be specified after the aggregation, so that the dimension size of day&lt;br /&gt;
      has been calculated.&lt;br /&gt;
  --&amp;gt;&lt;br /&gt;
  &amp;lt;variable name=&amp;quot;day&amp;quot; type=&amp;quot;int&amp;quot; shape=&amp;quot;day&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Note: metadata may be added here as normal! --&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;Days since 01/01/2010&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;values&amp;gt;1 30&amp;lt;/values&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
	     &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The resulting DDS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Int32 V[day = 2][sensors = 3];&lt;br /&gt;
    Int32 day[day = 2];&lt;br /&gt;
} joinNew_with_explicit_map.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and the ASCII data:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Int32 V[day = 2][sensors = 3] = {{1, 2, 3},{4, 5, 6}};&lt;br /&gt;
Int32 day[day = 2] = {1, 30};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the values we have explicitly given are used here as well as the specified NcML type, &#039;&#039;int&#039;&#039; which is mapped to a DAP Int32.  &lt;br /&gt;
&lt;br /&gt;
If metadata is desired on the new coordinate variable, it may be added just as in a normal new variable declaration.  We&#039;ll give more examples of this later.&lt;br /&gt;
&lt;br /&gt;
==== Grid with Explicit Map ====&lt;br /&gt;
&lt;br /&gt;
Let&#039;s give one more example using a Grid to demonstrate the recognition of the coordinate variable as it is added to the Grid as the map vector for the new dimension:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinNew Grid aggregation with explicit map&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;sample_time&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182183448.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183065853.hdf&amp;quot;/&amp;gt;  &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183182355.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;!-- Note: values are contrived --&amp;gt;&lt;br /&gt;
  &amp;lt;variable name=&amp;quot;sample_time&amp;quot; shape=&amp;quot;sample_time&amp;quot; type=&amp;quot;float&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Metadata here will also show up in the Grid map --&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;Days since 01/01/2010&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;values&amp;gt;100 200 400 1000&amp;lt;/values&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This produces the DDS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        UInt32 dsp_band_1[sample_time = 4][lat = 1024][lon = 1024];&lt;br /&gt;
      Maps:&lt;br /&gt;
        Float32 sample_time[sample_time = 4];&lt;br /&gt;
        Float64 lat[1024];&lt;br /&gt;
        Float64 lon[1024];&lt;br /&gt;
    } dsp_band_1;&lt;br /&gt;
    Float32 sample_time[sample_time = 4];&lt;br /&gt;
} joinNew_grid_explicit_map.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can see the explicit coordinate variable &#039;&#039;&#039;sample_time&#039;&#039;&#039; was found as the sibling of the aggregated Grid as was added as the new map vector for the Grid.&lt;br /&gt;
&lt;br /&gt;
The values for the projected coordinate variables are as expected:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Float32 sample_time[sample_time = 4] = {100, 200, 400, 1000};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Errors ====&lt;br /&gt;
&lt;br /&gt;
It is a Parse Error to:&lt;br /&gt;
&lt;br /&gt;
* Give a different number of values for the explicit coordinate variable than their are specified datasets&lt;br /&gt;
* Specify the new coordinate variable prior to the &amp;lt;aggregation&amp;gt; element since the dimension size is not yet known&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Autogenerated Uniform Numeric Values ===&lt;br /&gt;
&lt;br /&gt;
If the number of datasets might vary (for example, if a &amp;lt;scan&amp;gt; element, described later, is used), but the values are uniform, the start/increment version of the &amp;lt;values&amp;gt; element may be used to generate the values for the new coordinate variable.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;JoinNew on Array with Explicit Autogenerated Map&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;day&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;V&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;netcdf title=&amp;quot;Slice 1&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;dimension name=&amp;quot;sensors&amp;quot; length=&amp;quot;3&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;variable name=&amp;quot;V&amp;quot; type=&amp;quot;int&amp;quot; shape=&amp;quot;sensors&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;values&amp;gt;1 2 3&amp;lt;/values&amp;gt;&lt;br /&gt;
      &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;netcdf title=&amp;quot;Slice 2&amp;quot;&amp;gt;&lt;br /&gt;
      &amp;lt;dimension name=&amp;quot;sensors&amp;quot; length=&amp;quot;3&amp;quot;/&amp;gt;&lt;br /&gt;
      &amp;lt;variable name=&amp;quot;V&amp;quot; type=&amp;quot;int&amp;quot; shape=&amp;quot;sensors&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;values&amp;gt;4 5 6&amp;lt;/values&amp;gt;&lt;br /&gt;
      &amp;lt;/variable&amp;gt;&lt;br /&gt;
    &amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Explicit coordinate variable definition --&amp;gt;&lt;br /&gt;
  &amp;lt;variable name=&amp;quot;day&amp;quot; type=&amp;quot;int&amp;quot; shape=&amp;quot;day&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;string&amp;quot; value=&amp;quot;days since 2000-1-01 00:00&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;!-- We sample once a week... --&amp;gt;&lt;br /&gt;
    &amp;lt;values start=&amp;quot;1&amp;quot; increment=&amp;quot;7&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
	     &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The DDS is the same as before and the coordinate variable is generated as expected:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Int32 sample_time[sample_time = 4] = {1, 8, 15, 22};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that this form is useful for uniform sampled datasets (or if only a numeric index is desired) where the variable need not be changed as datasets are added.  It is especially useful for a &amp;lt;scan&amp;gt; element that refers to a dynamic number of files that can be described with a uniformly varying index.&lt;br /&gt;
&lt;br /&gt;
=== Explicitly Using coordValue Attribute of &amp;lt;netcdf&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;netcdf@coordValue&#039;&#039; may be used to specify the value for the given dataset right where the dataset is declared.  This attribute will cause a coordinate variable to be automatically generated with the given values for each dataset filled in.  The new coordinate variable will be of type &#039;&#039;&#039;double&#039;&#039;&#039; if the coordValue&#039;s can all be parsed as a number, otherwise they will be of type &#039;&#039;&#039;String&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== String coordValue Example ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinNew Aggregation with explicit string coordValue&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;source&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;u&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;v&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Same dataset a few times, but with different coordVal --&amp;gt;&lt;br /&gt;
    &amp;lt;netcdf title=&amp;quot;Dataset 1&amp;quot; location=&amp;quot;data/ncml/fnoc1.nc&amp;quot; coordValue=&amp;quot;Station_1&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;netcdf title=&amp;quot;Dataset 2&amp;quot; location=&amp;quot;data/ncml/fnoc1.nc&amp;quot; coordValue=&amp;quot;Station_2&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;netcdf title=&amp;quot;Dataset 3&amp;quot; location=&amp;quot;data/ncml/fnoc1.nc&amp;quot; coordValue=&amp;quot;Station_3&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This results in the following DDS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Int16 u[source = 3][time_a = 16][lat = 17][lon = 21];&lt;br /&gt;
    Int16 v[source = 3][time_a = 16][lat = 17][lon = 21];&lt;br /&gt;
    Float32 lat[lat = 17];&lt;br /&gt;
    Float32 lon[lon = 21];&lt;br /&gt;
    Float32 time[time = 16];&lt;br /&gt;
    String source[source = 3];&lt;br /&gt;
} joinNew_string_coordVal.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and ASCII data response of the projected coordinate variable is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
String source[source = 3] = {&amp;quot;Station_1&amp;quot;, &amp;quot;Station_2&amp;quot;, &amp;quot;Station_3&amp;quot;};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
as we specified.&lt;br /&gt;
&lt;br /&gt;
==== Numeric (double) Use of coordValue ====&lt;br /&gt;
&lt;br /&gt;
If the first &#039;&#039;coordValue&#039;&#039; can be successfully parsed as a double numeric type, then a coordinate variable of type double (Float64) is created and all remaining &#039;&#039;coordValue&#039;&#039; specifications &#039;&#039;&#039;must&#039;&#039;&#039; be parsable as a double or a Parse Error is thrown.&lt;br /&gt;
&lt;br /&gt;
Using the same example but with numbers instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinNew Aggregation with numeric coordValue&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;source&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;u&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;v&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- Same dataset a few times, but with different coordVal --&amp;gt;&lt;br /&gt;
    &amp;lt;netcdf title=&amp;quot;Dataset 1&amp;quot; location=&amp;quot;data/ncml/fnoc1.nc&amp;quot; coordValue=&amp;quot;1.2&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;netcdf title=&amp;quot;Dataset 2&amp;quot; location=&amp;quot;data/ncml/fnoc1.nc&amp;quot; coordValue=&amp;quot;3.4&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;netcdf title=&amp;quot;Dataset 3&amp;quot; location=&amp;quot;data/ncml/fnoc1.nc&amp;quot; coordValue=&amp;quot;5.6&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt;&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This time we see that a Float64 array is created:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Int16 u[source = 3][time_a = 16][lat = 17][lon = 21];&lt;br /&gt;
    Int16 v[source = 3][time_a = 16][lat = 17][lon = 21];&lt;br /&gt;
    Float32 lat[lat = 17];&lt;br /&gt;
    Float32 lon[lon = 21];&lt;br /&gt;
    Float32 time[time = 16];&lt;br /&gt;
    Float64 source[source = 3];&lt;br /&gt;
} joinNew_numeric_coordValue.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The values we specified are in the coordinate variable ASCII data:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Float64 source[source = 3] = {1.2, 3.4, 5.6};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Dynamic_Aggregation_Tutorial&amp;diff=5588</id>
		<title>Dynamic Aggregation Tutorial</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Dynamic_Aggregation_Tutorial&amp;diff=5588"/>
		<updated>2010-04-20T19:30:01Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Location (Location Location...) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Location (Location Location...) ===&lt;br /&gt;
[[Category:Aggregation]]&lt;br /&gt;
[[Category:NCML]]&lt;br /&gt;
&lt;br /&gt;
The most important attribute of the scan element is the &#039;&#039;scan@location&#039;&#039; element that specifies the top-level search directory for the scan, relative to the BES data root directory specified in the BES configuration.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;IMPORTANT&#039;&#039;&#039;:  &#039;&#039;ALL&#039;&#039; locations are interpreted relative to the BES root directory and &#039;&#039;&#039;NOT&#039;&#039;&#039; relative to the location of the NcML file itself!  This means that all data to be aggregated &#039;&#039;&#039;must&#039;&#039;&#039; be in a subdirectory of the BES root data directory and that these directories &#039;&#039;must&#039;&#039; be specified fully, not relative to the NcML file.  &lt;br /&gt;
&lt;br /&gt;
For example, if the BES root data dir is &amp;quot;/usr/local/share/hyrax&amp;quot;, let ${BES_DATA_ROOT} refer to this location.  If the NcML aggregation file is in &amp;quot;${BES_DATA_ROOT}/data/ncml/myAgg.ncml&amp;quot; and the aggregation member datasets are in &amp;quot;${BES_DATA_ROOT}/data/hdf4/myAggDatasets&amp;quot;, then the location in the NcML file for the aggregation data directory would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;scan location=&amp;quot;data/hdf4/myAggDatasets&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which specifies the data directory relative to the BES data root as required.&lt;br /&gt;
&lt;br /&gt;
Again, due to security reasons, the data is always searched under the BES data root.  Trying to specify an absolute filesystem path, such as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;scan location=&amp;quot;/usr/local/share/data&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will &#039;&#039;NOT&#039;&#039; work.  This directory will also be assumed to be a subdirectory of the ${BES_DATA_ROOT}, regardless of the preceding &amp;quot;/&amp;quot; character.&lt;br /&gt;
&lt;br /&gt;
=== Suffix Criterion ===&lt;br /&gt;
&lt;br /&gt;
The simplest criterion is to match only files of a certain datatype in a given directory.  This is useful for filtering out text files and other files that may exist in the directory but which do not form part of the aggregation data.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s a simple example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;Example of joinNew Grid aggregation using the scan element.&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;scan location=&amp;quot;data/ncml/agg/grids&amp;quot; suffix=&amp;quot;.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assuming that the specified location &amp;quot;data/ncml/agg/grids&amp;quot; contains no subdirectories, this NcML will return all files in that directory that end in &amp;quot;.hdf&amp;quot; in alphanumerical order.  In the case of our installed example data, there are four HDF4 files in that directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
data/ncml/agg/grids/f97182070958.hdf&lt;br /&gt;
data/ncml/agg/grids/f97182183448.hdf&lt;br /&gt;
data/ncml/agg/grids/f97183065853.hdf&lt;br /&gt;
data/ncml/agg/grids/f97183182355.hdf &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These will be included in alphanumerical order, so the scan element will in effect be equivalent to the following list of &amp;lt;netcdf&amp;gt; elements:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182183448.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183065853.hdf&amp;quot;/&amp;gt;  &lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183182355.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default, scan will search subdirectories, which is why we mentioned &amp;quot;grids has no subdirectories&amp;quot;.  We discuss this in the next section.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Subdirectory Searching (The Default!) ===&lt;br /&gt;
&lt;br /&gt;
If the author specifies the &#039;&#039;scan@subdirs&#039;&#039; attribute to the value &amp;quot;true&amp;quot; (which is the default!), then the criteria will be applied recursively to any subdirectories of the &#039;&#039;scan@location&#039;&#039; base scan directory as well as to any regular files in the base directory.  &lt;br /&gt;
&lt;br /&gt;
For example, continuing our previous example, but giving a higher level location:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinNew Grid aggregation using the scan element.&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;!-- This will recurse into the &amp;quot;grids&amp;quot; subdir and grab all *.hdf files there --&amp;gt;&lt;br /&gt;
    &amp;lt;scan location=&amp;quot;data/ncml/agg/&amp;quot; suffix=&amp;quot;.hdf&amp;quot; subdirs=&amp;quot;true&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assuming that only the &amp;quot;grids&amp;quot; subdir of &amp;quot;/data/ncml/agg&amp;quot; contains HDF4 files with that extension, the same aggregation as prior will be created, i.e. an aggregation isomorphic to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182183448.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183065853.hdf&amp;quot;/&amp;gt;  &lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183182355.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;scan@subdirs&#039;&#039; attribute is much for useful for turning off the default recursion.  For example, if recursion is &#039;&#039;&#039;NOT&#039;&#039;&#039; desired, but only files with the given suffix in the given directory are required, the following will do that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinNew Grid aggregation using the scan element.&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;!-- Find *.hdf files ONLY in the given location and NOT in subdirs --&amp;gt;&lt;br /&gt;
    &amp;lt;scan location=&amp;quot;data/ncml/agg/grids&amp;quot; suffix=&amp;quot;.hdf&amp;quot; subdirs=&amp;quot;false&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== OlderThan Criterion ===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;scan@olderThan&#039;&#039; attribute can be used to filter out files that are &amp;quot;too new&amp;quot;.  This feature is useful for excluding partial files currently being written by a daemon process, for example.  &lt;br /&gt;
&lt;br /&gt;
The value of the attribute is a duration specified by a number followed by a basic time unit.  The time units recognized are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;seconds&#039;&#039;&#039;: { s, sec, secs, second, seconds }&lt;br /&gt;
* &#039;&#039;&#039;minutes&#039;&#039;&#039;: { m, min, mins, minute, minutes }&lt;br /&gt;
* &#039;&#039;&#039;hours&#039;&#039;&#039;: { h, hour, hours }&lt;br /&gt;
* &#039;&#039;&#039;days&#039;&#039;&#039;: { day, days }&lt;br /&gt;
* &#039;&#039;&#039;months&#039;&#039;&#039;: { month, months }&lt;br /&gt;
* &#039;&#039;&#039;years&#039;&#039;&#039;: { year, years }&lt;br /&gt;
&lt;br /&gt;
The strings inside { } are all recognized as referring to the given time unit.  &lt;br /&gt;
&lt;br /&gt;
For example, if we are following our previous example, but we suspect a new HDF file may be written at any time and usually takes 5 minutes to do so, we might use the following NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinNew Grid aggregation using the scan element.&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;scan location=&amp;quot;data/ncml/agg/grids&amp;quot; suffix=&amp;quot;.hdf&amp;quot; subdirs=&amp;quot;false&amp;quot; olderThan=&amp;quot;10 mins&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assuming the file will always be written withing 10 minutes, this files does what we wish.  Only files whose modification date is older than the given duration from the current system time are included.   &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039; that the modification date of the file, not the creation date, is used for the test. &lt;br /&gt;
&lt;br /&gt;
=== Regular Expression Criterion ===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;scan@regExp&#039;&#039; attribute may be used for more complicated filename matching tests where data for multiple variables, for example, may live in the same directory by whose filenames can be used to distinguish which are desired in the aggregation.  Additionally, since the pathname including the location is used for the test, a regular expression test may be used in conjunction with a recursive directory search to find files in subdirectories where the directory name itself is specified in the regular expression, not just the filename.  We&#039;ll give examples of both of these cases.  &lt;br /&gt;
&lt;br /&gt;
We also reiterate that this test is used &#039;&#039;in conjunction&#039;&#039; with any other tests --- the author may also include a suffix and an olderThan test if they wish.  All criteria must match for the file to be included in the aggregation.&lt;br /&gt;
&lt;br /&gt;
We recognize the POSIX regular expression syntax.  For more information on regular expressions and the POSIX syntax, please see: http://en.wikipedia.org/wiki/Regular_expression.&lt;br /&gt;
&lt;br /&gt;
We will give two basic examples: &lt;br /&gt;
&lt;br /&gt;
* Finding all subdirectories with a given name&lt;br /&gt;
* Matching a filename starting with a certain substring&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Matching a Subdirectory Name ====&lt;br /&gt;
Here&#039;s an example where we use a subdirectory search to find &amp;quot;.hdf&amp;quot; files in all subdirectories named &amp;quot;grids&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;Example of joinNew Grid aggregation using the scan element with a regexp&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;!-- Scan from the top for files in a grids subdir and ending in .hdf.&lt;br /&gt;
              We are also using a regexp to match on a path that ends in &amp;quot;grids&amp;quot; &lt;br /&gt;
              and has a suffix of hdf. --&amp;gt;&lt;br /&gt;
    &amp;lt;scan &lt;br /&gt;
       location=&amp;quot;data/&amp;quot; &lt;br /&gt;
       subdirs=&amp;quot;true&amp;quot; &lt;br /&gt;
       regExp=&amp;quot;^.*/grids/.+\.hdf$&amp;quot;&lt;br /&gt;
       /&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The regular expression here is &amp;quot;^.*/grids/.+\/hdf&amp;quot;.  Let&#039;s pull it apart quickly (this is not intended to be a regular expression tutorial):&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;^&amp;quot; matching the beginning of the string, so starts at the beginning of the location pathname.   (without this we can match substrings in the middle of strings, etc)&lt;br /&gt;
&lt;br /&gt;
We then match &amp;quot;.*&amp;quot; meaning 0 or more of any character.&lt;br /&gt;
&lt;br /&gt;
We then match the &amp;quot;/grids/&amp;quot; string explicitly, meaning we want all pathnames that contain &amp;quot;/grids/&amp;quot; as a subdirectory.  &lt;br /&gt;
&lt;br /&gt;
We then match &amp;quot;.+&amp;quot; meaning 1 or more of any character.&lt;br /&gt;
&lt;br /&gt;
We then match &amp;quot;\.&amp;quot; meaning a literal &amp;quot;.&amp;quot; character (the backslash &amp;quot;escapes&amp;quot; it).&lt;br /&gt;
&lt;br /&gt;
We then match the suffix &amp;quot;hdf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Finally, we match &amp;quot;$&amp;quot; meaning the end of the string.&lt;br /&gt;
&lt;br /&gt;
So ultimately, this regular expression finds all filenames ending in &amp;quot;.hdf&amp;quot; that exist in some subdirectory named &amp;quot;grids&amp;quot; of the top-level location.&lt;br /&gt;
&lt;br /&gt;
In following with our previous example, if there was only the one &amp;quot;grids&amp;quot; subdirectory in the ${BES_DATA_ROOT} with our four familiar files, we&#039;d get the same aggregation as before.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Matching a partial filename ====&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we have a given directory full of data files whose filename prefix specifies which variable they refer to.  For example, let&#039;s say our &amp;quot;grids&amp;quot; directory has files that start with &amp;quot;grad&amp;quot; as well as the files that start with &amp;quot;f&amp;quot; we have seen in our examples.  We still want just the files starting with &amp;quot;f&amp;quot; to filter out the others.  Here&#039;s an example for that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;Example of joinNew Grid aggregation using the scan element with a regexp&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;!-- Scan from the top for files in a grids subdir and starting with &amp;quot;f&amp;quot; and ending in &amp;quot;.hdf&amp;quot;.&lt;br /&gt;
        --&amp;gt;&lt;br /&gt;
    &amp;lt;scan &lt;br /&gt;
       location=&amp;quot;data/&amp;quot; &lt;br /&gt;
       subdirs=&amp;quot;true&amp;quot; &lt;br /&gt;
       regExp=&amp;quot;^.*/grids/f.+\.hdf$&amp;quot;&lt;br /&gt;
       /&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we match all pathnames ending in &amp;quot;grids&amp;quot; and files that start with the letter &amp;quot;f&amp;quot; and end with &amp;quot;.hdf&amp;quot; as we desire.&lt;br /&gt;
&lt;br /&gt;
=== Date Format Mark and Timestamp Extraction ===&lt;br /&gt;
&lt;br /&gt;
This section shows how to use the &#039;&#039;scan@dateFormatMark&#039;&#039; attribute along with other search criteria in order to extract and sort datasets by a timestamp encoded in the filename.  All that is required is that the timestamp be parseable by a pattern recognized by the Java language &amp;quot;SimpleDateFormat&amp;quot; class ([http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html java.text.SimpleDateFormat]), which has also been implemented in C++ in the [http://site.icu-project.org/  International Components for Unicode] library which we use.&lt;br /&gt;
&lt;br /&gt;
We base this example from the Unidata site [http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Aggregation.html Aggregation Tutorial].  Here we have a directory with four files whose filenames contain a timestamp describable by a SimpleDataFormat (SDF) pattern.  We will also use a regular expression criterion and suffix criterion in addition to the dateFormatMark since we have other files in the same directory and only wish to match those starting with the characters &amp;quot;CG&amp;quot; that have suffix &amp;quot;.nc&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
Here&#039;s the list of files (relative to the BES data root dir):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
data/ncml/agg/dated/CG2006158_120000h_usfc.nc&lt;br /&gt;
data/ncml/agg/dated/CG2006158_130000h_usfc.nc&lt;br /&gt;
data/ncml/agg/dated/CG2006158_140000h_usfc.nc&lt;br /&gt;
data/ncml/agg/dated/CG2006158_150000h_usfc.nc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;Test of joinNew aggregation using the scan element and dateFormatMark&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;fileTime&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;CGusfc&amp;quot;/&amp;gt;  &lt;br /&gt;
    &amp;lt;scan location=&amp;quot;data/ncml/agg/dated&amp;quot; &lt;br /&gt;
	  suffix=&amp;quot;.nc&amp;quot; &lt;br /&gt;
	  subdirs=&amp;quot;false&amp;quot;&lt;br /&gt;
	  regExp=&amp;quot;^.*/CG[^/]*&amp;quot;&lt;br /&gt;
	  dateFormatMark=&amp;quot;CG#yyyyDDD_HHmmss&amp;quot;&lt;br /&gt;
	  /&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So here we joinNew on the new outer dimension &#039;&#039;fileTime&#039;&#039;.  The new coordinate variable &#039;&#039;&#039;fileTime&#039;&#039;&#039;[&#039;&#039;fileTime&#039;&#039;] for this dimension will be an Array of type String that will contain the parsed [http://en.wikipedia.org/wiki/ISO_8601 ISO 8601] timestamps we will extract from the matching filenames.  &lt;br /&gt;
&lt;br /&gt;
We have specified that we want only Netcdf files (suffix &amp;quot;.nc&amp;quot;) which match the regular expression &amp;quot;^.*/CG[^/]*&amp;quot;.  This means match the start of the string, then any number of characters that end with a &amp;quot;/&amp;quot; (the path portion of the filename), then the letters &amp;quot;CG&amp;quot;, then some number of characters that do &#039;&#039;not&#039;&#039; include the &amp;quot;/&amp;quot; character (which is what &amp;quot;[^/]*&amp;quot; means).  Essentially, we want files whose basename (path stripped) start with &amp;quot;CG&amp;quot; and end with &amp;quot;.nc&amp;quot;.   We also do not want to recurse, but only look in the location directory &amp;quot;/data/ncml/agg/dated&amp;quot; for the files.&lt;br /&gt;
&lt;br /&gt;
Finally, we specify the &#039;&#039;scan@dateFormatMark&#039;&#039; pattern to describe how to parse the filename into an ISO 8601 date.  The &#039;&#039;dateFormatMark&#039;&#039; is processed as follows:&lt;br /&gt;
&lt;br /&gt;
* Skip the &#039;&#039;number&#039;&#039; of characters prior to the &amp;quot;#&amp;quot; mark in the pattern while scanning the base filename (no path)&lt;br /&gt;
* Interpret the next characters of the file basename using the given SimpleDateFormat string&lt;br /&gt;
* Ignore any characters after the SDF portion of the filename (such as the suffix)&lt;br /&gt;
&lt;br /&gt;
First, note that we &#039;&#039;&#039;do not match&#039;&#039;&#039; the characters in the dateFormatMark --- they are simply counted and skipped.  So rather than &amp;quot;CG#&amp;quot; specifying the prefix before the SDF, we could have also used &amp;quot;XX#&amp;quot;.  This is why we must also use a regular expression to filter out files with other prefixes that we do not want in the aggregation.  Note that the &amp;quot;#&amp;quot; is just a marker for the start of the SDF pattern and doesn&#039;t count as an actual character in the matching process.&lt;br /&gt;
&lt;br /&gt;
Second, we specify the dateFormatMark (DFM) as the following SDF pattern: &amp;quot;yyyyDDD_HHmmss&amp;quot;.  This means that we use the four digit year, then the day of the year (a three digit number), then an underscore (&amp;quot;_&amp;quot;) separator, then the 24 hour time as 6 digits.  Let&#039;s take the basename of the first file as an example:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;CG2006158_120000h_usfc.nc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
We skip two characters due to the &amp;quot;CG#&amp;quot; in the DFM.  Then we want to match the &amp;quot;yyyy&amp;quot; pattern for the year with: &amp;quot;2006&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
We then match the day of the year as &amp;quot;DDD&amp;quot; which is &amp;quot;158&amp;quot;, the 158th day of the year for 2006.&lt;br /&gt;
&lt;br /&gt;
We then match the underscore character &amp;quot;_&amp;quot; which is only a separator.&lt;br /&gt;
&lt;br /&gt;
Next, we match the 24 hour time &amp;quot;HHmmss&amp;quot; as 12:00:00 hours:mins:secs (i.e. noon).&lt;br /&gt;
&lt;br /&gt;
Finally, any characters after the DFM are ignored, here &amp;quot;h_usfc.nc&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
We see that the four dataset files are on the same day, but sampled each hour from noon to 3 pm.&lt;br /&gt;
&lt;br /&gt;
These parsed timestamps are then converted to an ISO 8601 date string which is used as the value for the coordinate variable element corresponding to that aggregation member.  The first file would thus have the time value &amp;quot;2006-06-07T12:00:00Z&amp;quot;, which is 7 June 2006 at noon in the GMT timezone.  &lt;br /&gt;
&lt;br /&gt;
The matched files are then &#039;&#039;&#039;sorted using the ISO 8601 timestamp as the sort key&#039;&#039;&#039; and added to the aggregation in this order.  Since ISO 8601 is designed such that lexicographic order is isomorphic to chronological order, this orders the datasets monotonically in time from past to future.  This is different from the &amp;lt;scan&amp;gt; behavior &#039;&#039;without&#039;&#039; a dateFormatMark specified, where files are ordered lexicographically (alphanumerically by full pathname) --- this order may or may not match chronological order.  &lt;br /&gt;
&lt;br /&gt;
If we project out the ASCII dods response for the new coordinate variable, we see all of the parsed timestamps and that they are in chronological order:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
String fileTime[fileTime = 4] = {&amp;quot;2006-06-07T12:00:00Z&amp;quot;, &lt;br /&gt;
&amp;quot;2006-06-07T13:00:00Z&amp;quot;,&lt;br /&gt;
 &amp;quot;2006-06-07T14:00:00Z&amp;quot;, &lt;br /&gt;
&amp;quot;2006-06-07T15:00:00Z&amp;quot;};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also check the resulting DDS to see that it is added as a map vector to the Grid as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Float32 CGusfc[fileTime = 4][time = 1][altitude = 1][lat = 29][lon = 26]&lt;br /&gt;
;&lt;br /&gt;
      Maps:&lt;br /&gt;
        String fileTime[fileTime = 4];&lt;br /&gt;
        Float64 time[time = 1];&lt;br /&gt;
        Float32 altitude[altitude = 1];&lt;br /&gt;
        Float32 lat[lat = 29];&lt;br /&gt;
        Float32 lon[lon = 26];&lt;br /&gt;
    } CGusfc;&lt;br /&gt;
    String fileTime[fileTime = 4];&lt;br /&gt;
} joinNew_scan_dfm.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, we look at the DAS with global metadata removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
  CGusfc {&lt;br /&gt;
        Float32 _FillValue -1.000000033e+32;&lt;br /&gt;
        Float32 missing_value -1.000000033e+32;&lt;br /&gt;
        Int32 numberOfObservations 303;&lt;br /&gt;
        Float32 actual_range -0.2876400054, 0.2763200104;&lt;br /&gt;
        fileTime {&lt;br /&gt;
---&amp;gt;            String _CoordinateAxisType &amp;quot;Time&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        CGusfc {&lt;br /&gt;
        }&lt;br /&gt;
        time {&lt;br /&gt;
            String long_name &amp;quot;End Time&amp;quot;;&lt;br /&gt;
            String standard_name &amp;quot;time&amp;quot;;&lt;br /&gt;
            String units &amp;quot;seconds since 1970-01-01T00:00:00Z&amp;quot;;&lt;br /&gt;
            Float64 actual_range 1149681600.0000000, 1149681600.0000000;&lt;br /&gt;
        }&lt;br /&gt;
        altitude {&lt;br /&gt;
            String long_name &amp;quot;Altitude&amp;quot;;&lt;br /&gt;
            String standard_name &amp;quot;altitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;m&amp;quot;;&lt;br /&gt;
            Float32 actual_range 0.000000000, 0.000000000;&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
            String standard_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
            String point_spacing &amp;quot;even&amp;quot;;&lt;br /&gt;
            Float32 actual_range 37.26869965, 38.02470016;&lt;br /&gt;
            String coordsys &amp;quot;geographic&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
            String standard_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
            String point_spacing &amp;quot;even&amp;quot;;&lt;br /&gt;
            Float32 actual_range 236.5800018, 237.4799957;&lt;br /&gt;
            String coordsys &amp;quot;geographic&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    fileTime {&lt;br /&gt;
---&amp;gt;     String _CoordinateAxisType &amp;quot;Time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that the aggregation has also automatically added the &amp;quot;_CoordinateAxisType&amp;quot; attribute and set it to &amp;quot;Time&amp;quot; (denoted by the &amp;quot;--&amp;gt;&amp;quot;) as defined by the NcML 2.2 specification.  The author may add other metadata to the new coordinate variable as discussed previously.&lt;br /&gt;
&lt;br /&gt;
=== Order of Inclusion ===&lt;br /&gt;
&lt;br /&gt;
In cases where a dateFormatMark is &#039;&#039;not&#039;&#039; specified, the member datasets are added to the aggregation in alphabetical order &#039;&#039;on the full pathname&#039;&#039;.  This is important in the case of subdirectories since the path of the subdirectory is taken into account in the sort.&lt;br /&gt;
&lt;br /&gt;
In cases where a dateFormatMark &#039;&#039;is&#039;&#039; specified, the extracted ISO 8601 timestamp is used as the sorting criterion, with older files being added before newer files.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Metadata_on_Aggregations_Tutorial&amp;diff=5587</id>
		<title>Metadata on Aggregations Tutorial</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Metadata_on_Aggregations_Tutorial&amp;diff=5587"/>
		<updated>2010-04-20T19:28:41Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Metadata Specification on the New Coordinate Variable */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Metadata Specification on the New Coordinate Variable ===&lt;br /&gt;
[[Category:Aggregation]]&lt;br /&gt;
&lt;br /&gt;
We can add metadata to the new coordinate variable in two ways:&lt;br /&gt;
&lt;br /&gt;
* Adding it to the &amp;lt;variable&amp;gt; element directly in the case where the new coordinate variable and values is defined explicitly&lt;br /&gt;
* Adding the metadata to an &#039;&#039;automatically created&#039;&#039; coordinate variable by leaving the &amp;lt;values&amp;gt; element out&lt;br /&gt;
&lt;br /&gt;
The first case we have already seen, but we will show it again explicitly.  The second case is a little different and we&#039;ll cover it separately.&lt;br /&gt;
&lt;br /&gt;
==== Adding Metadata to the Explicit New Coordinate Variable ====&lt;br /&gt;
&lt;br /&gt;
We have already seen examples of explicitly defining the new coordinate variable and giving its values.  In these cases, the metadata is added to the new coordinate variable exactly like any other variable.  Let&#039;s see the example again:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinNew Grid aggregation with explicit map&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;sample_time&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182183448.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183065853.hdf&amp;quot;/&amp;gt;  &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183182355.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;variable name=&amp;quot;sample_time&amp;quot; shape=&amp;quot;sample_time&amp;quot; type=&amp;quot;float&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Metadata here will also show up in the Grid map --&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;Days since 01/01/2010&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;values&amp;gt;100 200 400 1000&amp;lt;/values&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that the &#039;&#039;&#039;units&#039;&#039;&#039; attribute for the new coordinate variable has been specified.  This subset of the DAS (we don&#039;t show the extensive global metadata) shows this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
        sample_time {&lt;br /&gt;
 ---&amp;gt;           String units &amp;quot;Days since 01/01/2010&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    sample_time {&lt;br /&gt;
---&amp;gt;        String units &amp;quot;Days since 01/01/2010&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We show the new metadata with the &amp;quot;---&amp;gt;&amp;quot; marker.  Note that the metadata for the coordinate variable is also copied into the new map vector of the aggregated Grid.&lt;br /&gt;
&lt;br /&gt;
Metadata can be specified in this way for &#039;&#039;any&#039;&#039; case where the new coordinate variable is listed explicitly.  &lt;br /&gt;
&lt;br /&gt;
==== Adding Metadata to An Autogenerated Coordinate Variable ====&lt;br /&gt;
&lt;br /&gt;
If we expect the coordinate variable to be automatically added, we can also specify its metadata by referring to the variable without setting its values.  This is useful in the case of using &#039;&#039;netcdf@coordValue&#039;&#039; and we will also see it is very useful when using a &amp;lt;scan&amp;gt; element for dynamic aggregations.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s a trivial  example using the default  case of the filename:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;Test of adding metadata to the new map vector in a joinNew Grid aggregation&amp;quot;&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- &lt;br /&gt;
       Add metadata to the created new outer dimension variable after&lt;br /&gt;
       the aggregation is defined by using a placeholder variable&lt;br /&gt;
       whose values will be defined automatically by the aggregation.&lt;br /&gt;
  --&amp;gt;  &lt;br /&gt;
  &amp;lt;variable type=&amp;quot;string&amp;quot; name=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;Filename of the dataset&amp;lt;/attribute&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note here that we just neglected to add a &amp;lt;values&amp;gt; element since we want the values to be generated automatically by the aggregation.  Note also that this is &#039;&#039;almost&#039;&#039; the same way we&#039;d modify an existing variable&#039;s metadata.  The only difference is we need to &amp;quot;declare&amp;quot; the type of the variable here since technically the variable specified here is a placeholder for the generated coordinate variable.  So after the aggregation is specified, we are simply modifying the created variable&#039;s metadata, in this case the newly generated map vector.&lt;br /&gt;
&lt;br /&gt;
Here is the DAS portion with just the aggregated Grid and the new coordinate variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
        filename {&lt;br /&gt;
            String units &amp;quot;Filename of the dataset&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    filename {&lt;br /&gt;
        String units &amp;quot;Filename of the dataset&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here also the map vector gets a copy of the coordinate variable&#039;s metadata.&lt;br /&gt;
&lt;br /&gt;
We can also use this syntax in the case that &#039;&#039;netcdf@coordValue&#039;&#039; was used to autogenerate the coordinate variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinNew Grid aggregation with coordValue and metadata&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;sample_time&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot; coordValue=&amp;quot;1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182183448.hdf&amp;quot; coordValue=&amp;quot;10&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183065853.hdf&amp;quot; coordValue=&amp;quot;15&amp;quot;/&amp;gt;  &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183182355.hdf&amp;quot; coordValue=&amp;quot;25&amp;quot;/&amp;gt; &lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;!-- Note: values are contrived --&amp;gt;&lt;br /&gt;
  &amp;lt;variable name=&amp;quot;sample_time&amp;quot; shape=&amp;quot;sample_time&amp;quot; type=&amp;quot;double&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;string&amp;quot;&amp;gt;Days since 01/01/2010&amp;lt;/attribute&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we see the metadata added to the new coordinate variable and associated map vector:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
   dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
        sample_time {&lt;br /&gt;
 ---&amp;gt;           String units &amp;quot;Days since 01/01/2010&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    sample_time {&lt;br /&gt;
---&amp;gt;        String units &amp;quot;Days since 01/01/2010&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Parse Errors ====&lt;br /&gt;
&lt;br /&gt;
Since the processing of the aggregation takes a few steps, care must be taken in specifying the coordinate variable in the cases of autogenerated variables.  &lt;br /&gt;
&lt;br /&gt;
In particular, it is a Parse Error:&lt;br /&gt;
&lt;br /&gt;
* To specify the shape of the autogenerated coordinate variable if &amp;lt;values&amp;gt; are not set&lt;br /&gt;
* To leave out the type or to use a type that does not match the autogenerated type&lt;br /&gt;
&lt;br /&gt;
The second can be somewhat tricky to remember since for existing variables it can be safely left out and the variable will be &amp;quot;found&amp;quot;.  Since aggregations get processed fulled when the &amp;lt;netcdf&amp;gt; element containing them is closed, the specified coordinate variables in these cases are &#039;&#039;placeholders&#039;&#039; for the automatically generated variables, so they must match the name and type, but not specify a shape since the shape (size of the new aggregation dimension) is not known until this occurs.&lt;br /&gt;
&lt;br /&gt;
=== Metadata Specification on the Aggregation Variable Itself ===&lt;br /&gt;
&lt;br /&gt;
It is also possible to add or modify the attributes on the aggregation variable itself.  If it is a Grid, metadata can be modified on the contained array or maps as well.  Note that the aggregated variable begins with the metadata &#039;&#039;from the first dataset specified in the aggregation&#039;&#039; just like in a union aggregation.&lt;br /&gt;
&lt;br /&gt;
We will use a Grid as our primary example since other datatypes are similar and simpler and this case will cover those as well.&lt;br /&gt;
&lt;br /&gt;
==== An Aggregated Grid example ====&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start from this example aggregation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf&amp;gt; &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182183448.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183065853.hdf&amp;quot;/&amp;gt;  &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183182355.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is the DAS for this unmodifed aggregated Grid (with the global dataset metadata removed):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
   dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
        filename {&lt;br /&gt;
        }&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    filename {&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will now add attributes to all the existing parts of the Grid: &lt;br /&gt;
&lt;br /&gt;
* The Grid Structure itself&lt;br /&gt;
* The Array of data within the Grid&lt;br /&gt;
* Both existing map vectors (&#039;&#039;&#039;lat&#039;&#039;&#039; and &#039;&#039;&#039;lon&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
We have already seen how to add data to the new coordinate variable as well.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the NcML we will use.  Note we have added units data to the subparts of the Grid, and also added some metadata to the grid itself.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;Showing how to add metadata to all parts of an aggregated grid&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182183448.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183065853.hdf&amp;quot;/&amp;gt;  &lt;br /&gt;
    &amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183182355.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
&lt;br /&gt;
  &amp;lt;variable name=&amp;quot;dsp_band_1&amp;quot; type=&amp;quot;Structure&amp;quot;&amp;gt; &amp;lt;!-- Enter the Grid level scope --&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
1)  &amp;lt;attribute name=&amp;quot;Info&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;This is metadata on the Grid itself.&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;variable name=&amp;quot;dsp_band_1&amp;quot;&amp;gt; &amp;lt;!-- Enter the scope of the Array dsp_band_1 --&amp;gt;&lt;br /&gt;
2)    &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;Temp (packed)&amp;lt;/attribute&amp;gt; &amp;lt;!-- Units of the array --&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt; &amp;lt;!-- dsp_band_1.dsp_band_1 --&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lat&amp;quot;&amp;gt; &amp;lt;!-- dsp_band_1.lat map --&amp;gt;&lt;br /&gt;
3)    &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;degrees_north&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt; &lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;variable name=&amp;quot;lon&amp;quot;&amp;gt; &amp;lt;!-- dsp_band_1.lon map --&amp;gt;&lt;br /&gt;
4)    &amp;lt;attribute name=&amp;quot;units&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;degrees_east&amp;lt;/attribute&amp;gt;&lt;br /&gt;
    &amp;lt;/variable&amp;gt; &amp;lt;!-- dsp_band_1.lon map --&amp;gt;    &lt;br /&gt;
  &amp;lt;/variable&amp;gt; &amp;lt;!-- dsp_band_1 Grid --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;!-- Note well: this is a new coordinate variable so requires the correct type.&lt;br /&gt;
  Also note that it falls outside of the actual grid since we must specify it &lt;br /&gt;
  as a sibling coordinate variable it will be made into a Grid when the netcdf is closed. &lt;br /&gt;
  --&amp;gt;&lt;br /&gt;
  &amp;lt;variable name=&amp;quot;filename&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;&lt;br /&gt;
5)  &amp;lt;attribute name=&amp;quot;Info&amp;quot; type=&amp;quot;String&amp;quot;&amp;gt;Filename with timestamp&amp;lt;/attribute&amp;gt;&lt;br /&gt;
  &amp;lt;/variable&amp;gt; &amp;lt;!-- filename --&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;/netcdf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we show metadata being injected in several ways, denoted by the 1) -- 5) notations.&lt;br /&gt;
&lt;br /&gt;
1) We are inside the scope of the top-level Grid variable, so this metadata will show up in the attribute table inside the Grid Structure.&lt;br /&gt;
2) This is the actual data Array of the Grid, &#039;&#039;&#039;dsp_band_1.dsp_band_1&#039;&#039;&#039;.  We specify the units are a packed temperature.&lt;br /&gt;
3) Here we are in the scope of a map variable, &#039;&#039;&#039;dsp_band_1.lat&#039;&#039;&#039;.  We add the units specification to this map.&lt;br /&gt;
4) Likewise, we add units to the &#039;&#039;&#039;lon&#039;&#039;&#039; map vector.&lt;br /&gt;
5) Finally, we must close the actual grid and specify the metadata for the &#039;&#039;NEW&#039;&#039; coordinate variable as a sibling of the Grid since this will be used as the canonical prototype to be added to all Grid&#039;s which are to be aggregated on the new dimension.  Note in this case (unlike previous cases) the type of the new coordinate variable is required since we are specifying a &amp;quot;placeholder&amp;quot; variable for the new map until the Grid is actually processed once its containing &amp;lt;netcdf&amp;gt; is closed (i.e. all data is available to it).&lt;br /&gt;
&lt;br /&gt;
The resulting DAS (with global dataset metadata removed for clarity):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attribute {&lt;br /&gt;
... global data clipped ...&lt;br /&gt;
  dsp_band_1 {&lt;br /&gt;
        Byte dsp_PixelType 1;&lt;br /&gt;
        Byte dsp_PixelSize 2;&lt;br /&gt;
        UInt16 dsp_Flag 0;&lt;br /&gt;
        UInt16 dsp_nBits 16;&lt;br /&gt;
        Int32 dsp_LineSize 0;&lt;br /&gt;
        String dsp_cal_name &amp;quot;Temperature&amp;quot;;&lt;br /&gt;
        String units &amp;quot;Temp&amp;quot;;&lt;br /&gt;
        UInt16 dsp_cal_eqnNumber 2;&lt;br /&gt;
        UInt16 dsp_cal_CoeffsLength 8;&lt;br /&gt;
        Float32 dsp_cal_coeffs 0.125, -4;&lt;br /&gt;
        Float32 scale_factor 0.125;&lt;br /&gt;
        Float32 add_off -4;&lt;br /&gt;
 1)   String Info &amp;quot;This is metadata on the Grid itself.&amp;quot;;&lt;br /&gt;
        filename {&lt;br /&gt;
 5)       String Info &amp;quot;Filename with timestamp&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        dsp_band_1 {&lt;br /&gt;
2)        String units &amp;quot;Temp (packed)&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String name &amp;quot;lat&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
3)        String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String name &amp;quot;lon&amp;quot;;&lt;br /&gt;
            String long_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
4)        String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    filename {&lt;br /&gt;
5)    String Info &amp;quot;Filename with timestamp&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We have annotated the DAS with numbers representing which lines in the NcML above correspond to the injected metadata.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Dynamic_Aggregation_Tutorial&amp;diff=5586</id>
		<title>Dynamic Aggregation Tutorial</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Dynamic_Aggregation_Tutorial&amp;diff=5586"/>
		<updated>2010-04-20T19:23:20Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: /* Location (Location Location...) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Location (Location Location...) ===&lt;br /&gt;
[[Category:Aggregations]]&lt;br /&gt;
&lt;br /&gt;
The most important attribute of the scan element is the &#039;&#039;scan@location&#039;&#039; element that specifies the top-level search directory for the scan, relative to the BES data root directory specified in the BES configuration.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;IMPORTANT&#039;&#039;&#039;:  &#039;&#039;ALL&#039;&#039; locations are interpreted relative to the BES root directory and &#039;&#039;&#039;NOT&#039;&#039;&#039; relative to the location of the NcML file itself!  This means that all data to be aggregated &#039;&#039;&#039;must&#039;&#039;&#039; be in a subdirectory of the BES root data directory and that these directories &#039;&#039;must&#039;&#039; be specified fully, not relative to the NcML file.  &lt;br /&gt;
&lt;br /&gt;
For example, if the BES root data dir is &amp;quot;/usr/local/share/hyrax&amp;quot;, let ${BES_DATA_ROOT} refer to this location.  If the NcML aggregation file is in &amp;quot;${BES_DATA_ROOT}/data/ncml/myAgg.ncml&amp;quot; and the aggregation member datasets are in &amp;quot;${BES_DATA_ROOT}/data/hdf4/myAggDatasets&amp;quot;, then the location in the NcML file for the aggregation data directory would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;scan location=&amp;quot;data/hdf4/myAggDatasets&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which specifies the data directory relative to the BES data root as required.&lt;br /&gt;
&lt;br /&gt;
Again, due to security reasons, the data is always searched under the BES data root.  Trying to specify an absolute filesystem path, such as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;scan location=&amp;quot;/usr/local/share/data&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will &#039;&#039;NOT&#039;&#039; work.  This directory will also be assumed to be a subdirectory of the ${BES_DATA_ROOT}, regardless of the preceding &amp;quot;/&amp;quot; character.&lt;br /&gt;
&lt;br /&gt;
=== Suffix Criterion ===&lt;br /&gt;
&lt;br /&gt;
The simplest criterion is to match only files of a certain datatype in a given directory.  This is useful for filtering out text files and other files that may exist in the directory but which do not form part of the aggregation data.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s a simple example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;Example of joinNew Grid aggregation using the scan element.&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;scan location=&amp;quot;data/ncml/agg/grids&amp;quot; suffix=&amp;quot;.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assuming that the specified location &amp;quot;data/ncml/agg/grids&amp;quot; contains no subdirectories, this NcML will return all files in that directory that end in &amp;quot;.hdf&amp;quot; in alphanumerical order.  In the case of our installed example data, there are four HDF4 files in that directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
data/ncml/agg/grids/f97182070958.hdf&lt;br /&gt;
data/ncml/agg/grids/f97182183448.hdf&lt;br /&gt;
data/ncml/agg/grids/f97183065853.hdf&lt;br /&gt;
data/ncml/agg/grids/f97183182355.hdf &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These will be included in alphanumerical order, so the scan element will in effect be equivalent to the following list of &amp;lt;netcdf&amp;gt; elements:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182183448.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183065853.hdf&amp;quot;/&amp;gt;  &lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183182355.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default, scan will search subdirectories, which is why we mentioned &amp;quot;grids has no subdirectories&amp;quot;.  We discuss this in the next section.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Subdirectory Searching (The Default!) ===&lt;br /&gt;
&lt;br /&gt;
If the author specifies the &#039;&#039;scan@subdirs&#039;&#039; attribute to the value &amp;quot;true&amp;quot; (which is the default!), then the criteria will be applied recursively to any subdirectories of the &#039;&#039;scan@location&#039;&#039; base scan directory as well as to any regular files in the base directory.  &lt;br /&gt;
&lt;br /&gt;
For example, continuing our previous example, but giving a higher level location:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinNew Grid aggregation using the scan element.&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;!-- This will recurse into the &amp;quot;grids&amp;quot; subdir and grab all *.hdf files there --&amp;gt;&lt;br /&gt;
    &amp;lt;scan location=&amp;quot;data/ncml/agg/&amp;quot; suffix=&amp;quot;.hdf&amp;quot; subdirs=&amp;quot;true&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assuming that only the &amp;quot;grids&amp;quot; subdir of &amp;quot;/data/ncml/agg&amp;quot; contains HDF4 files with that extension, the same aggregation as prior will be created, i.e. an aggregation isomorphic to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182183448.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183065853.hdf&amp;quot;/&amp;gt;  &lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183182355.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;scan@subdirs&#039;&#039; attribute is much for useful for turning off the default recursion.  For example, if recursion is &#039;&#039;&#039;NOT&#039;&#039;&#039; desired, but only files with the given suffix in the given directory are required, the following will do that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinNew Grid aggregation using the scan element.&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;!-- Find *.hdf files ONLY in the given location and NOT in subdirs --&amp;gt;&lt;br /&gt;
    &amp;lt;scan location=&amp;quot;data/ncml/agg/grids&amp;quot; suffix=&amp;quot;.hdf&amp;quot; subdirs=&amp;quot;false&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== OlderThan Criterion ===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;scan@olderThan&#039;&#039; attribute can be used to filter out files that are &amp;quot;too new&amp;quot;.  This feature is useful for excluding partial files currently being written by a daemon process, for example.  &lt;br /&gt;
&lt;br /&gt;
The value of the attribute is a duration specified by a number followed by a basic time unit.  The time units recognized are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;seconds&#039;&#039;&#039;: { s, sec, secs, second, seconds }&lt;br /&gt;
* &#039;&#039;&#039;minutes&#039;&#039;&#039;: { m, min, mins, minute, minutes }&lt;br /&gt;
* &#039;&#039;&#039;hours&#039;&#039;&#039;: { h, hour, hours }&lt;br /&gt;
* &#039;&#039;&#039;days&#039;&#039;&#039;: { day, days }&lt;br /&gt;
* &#039;&#039;&#039;months&#039;&#039;&#039;: { month, months }&lt;br /&gt;
* &#039;&#039;&#039;years&#039;&#039;&#039;: { year, years }&lt;br /&gt;
&lt;br /&gt;
The strings inside { } are all recognized as referring to the given time unit.  &lt;br /&gt;
&lt;br /&gt;
For example, if we are following our previous example, but we suspect a new HDF file may be written at any time and usually takes 5 minutes to do so, we might use the following NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinNew Grid aggregation using the scan element.&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;scan location=&amp;quot;data/ncml/agg/grids&amp;quot; suffix=&amp;quot;.hdf&amp;quot; subdirs=&amp;quot;false&amp;quot; olderThan=&amp;quot;10 mins&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assuming the file will always be written withing 10 minutes, this files does what we wish.  Only files whose modification date is older than the given duration from the current system time are included.   &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039; that the modification date of the file, not the creation date, is used for the test. &lt;br /&gt;
&lt;br /&gt;
=== Regular Expression Criterion ===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;scan@regExp&#039;&#039; attribute may be used for more complicated filename matching tests where data for multiple variables, for example, may live in the same directory by whose filenames can be used to distinguish which are desired in the aggregation.  Additionally, since the pathname including the location is used for the test, a regular expression test may be used in conjunction with a recursive directory search to find files in subdirectories where the directory name itself is specified in the regular expression, not just the filename.  We&#039;ll give examples of both of these cases.  &lt;br /&gt;
&lt;br /&gt;
We also reiterate that this test is used &#039;&#039;in conjunction&#039;&#039; with any other tests --- the author may also include a suffix and an olderThan test if they wish.  All criteria must match for the file to be included in the aggregation.&lt;br /&gt;
&lt;br /&gt;
We recognize the POSIX regular expression syntax.  For more information on regular expressions and the POSIX syntax, please see: http://en.wikipedia.org/wiki/Regular_expression.&lt;br /&gt;
&lt;br /&gt;
We will give two basic examples: &lt;br /&gt;
&lt;br /&gt;
* Finding all subdirectories with a given name&lt;br /&gt;
* Matching a filename starting with a certain substring&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Matching a Subdirectory Name ====&lt;br /&gt;
Here&#039;s an example where we use a subdirectory search to find &amp;quot;.hdf&amp;quot; files in all subdirectories named &amp;quot;grids&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;Example of joinNew Grid aggregation using the scan element with a regexp&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;!-- Scan from the top for files in a grids subdir and ending in .hdf.&lt;br /&gt;
              We are also using a regexp to match on a path that ends in &amp;quot;grids&amp;quot; &lt;br /&gt;
              and has a suffix of hdf. --&amp;gt;&lt;br /&gt;
    &amp;lt;scan &lt;br /&gt;
       location=&amp;quot;data/&amp;quot; &lt;br /&gt;
       subdirs=&amp;quot;true&amp;quot; &lt;br /&gt;
       regExp=&amp;quot;^.*/grids/.+\.hdf$&amp;quot;&lt;br /&gt;
       /&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The regular expression here is &amp;quot;^.*/grids/.+\/hdf&amp;quot;.  Let&#039;s pull it apart quickly (this is not intended to be a regular expression tutorial):&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;^&amp;quot; matching the beginning of the string, so starts at the beginning of the location pathname.   (without this we can match substrings in the middle of strings, etc)&lt;br /&gt;
&lt;br /&gt;
We then match &amp;quot;.*&amp;quot; meaning 0 or more of any character.&lt;br /&gt;
&lt;br /&gt;
We then match the &amp;quot;/grids/&amp;quot; string explicitly, meaning we want all pathnames that contain &amp;quot;/grids/&amp;quot; as a subdirectory.  &lt;br /&gt;
&lt;br /&gt;
We then match &amp;quot;.+&amp;quot; meaning 1 or more of any character.&lt;br /&gt;
&lt;br /&gt;
We then match &amp;quot;\.&amp;quot; meaning a literal &amp;quot;.&amp;quot; character (the backslash &amp;quot;escapes&amp;quot; it).&lt;br /&gt;
&lt;br /&gt;
We then match the suffix &amp;quot;hdf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Finally, we match &amp;quot;$&amp;quot; meaning the end of the string.&lt;br /&gt;
&lt;br /&gt;
So ultimately, this regular expression finds all filenames ending in &amp;quot;.hdf&amp;quot; that exist in some subdirectory named &amp;quot;grids&amp;quot; of the top-level location.&lt;br /&gt;
&lt;br /&gt;
In following with our previous example, if there was only the one &amp;quot;grids&amp;quot; subdirectory in the ${BES_DATA_ROOT} with our four familiar files, we&#039;d get the same aggregation as before.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Matching a partial filename ====&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we have a given directory full of data files whose filename prefix specifies which variable they refer to.  For example, let&#039;s say our &amp;quot;grids&amp;quot; directory has files that start with &amp;quot;grad&amp;quot; as well as the files that start with &amp;quot;f&amp;quot; we have seen in our examples.  We still want just the files starting with &amp;quot;f&amp;quot; to filter out the others.  Here&#039;s an example for that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;Example of joinNew Grid aggregation using the scan element with a regexp&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;!-- Scan from the top for files in a grids subdir and starting with &amp;quot;f&amp;quot; and ending in &amp;quot;.hdf&amp;quot;.&lt;br /&gt;
        --&amp;gt;&lt;br /&gt;
    &amp;lt;scan &lt;br /&gt;
       location=&amp;quot;data/&amp;quot; &lt;br /&gt;
       subdirs=&amp;quot;true&amp;quot; &lt;br /&gt;
       regExp=&amp;quot;^.*/grids/f.+\.hdf$&amp;quot;&lt;br /&gt;
       /&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we match all pathnames ending in &amp;quot;grids&amp;quot; and files that start with the letter &amp;quot;f&amp;quot; and end with &amp;quot;.hdf&amp;quot; as we desire.&lt;br /&gt;
&lt;br /&gt;
=== Date Format Mark and Timestamp Extraction ===&lt;br /&gt;
&lt;br /&gt;
This section shows how to use the &#039;&#039;scan@dateFormatMark&#039;&#039; attribute along with other search criteria in order to extract and sort datasets by a timestamp encoded in the filename.  All that is required is that the timestamp be parseable by a pattern recognized by the Java language &amp;quot;SimpleDateFormat&amp;quot; class ([http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html java.text.SimpleDateFormat]), which has also been implemented in C++ in the [http://site.icu-project.org/  International Components for Unicode] library which we use.&lt;br /&gt;
&lt;br /&gt;
We base this example from the Unidata site [http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Aggregation.html Aggregation Tutorial].  Here we have a directory with four files whose filenames contain a timestamp describable by a SimpleDataFormat (SDF) pattern.  We will also use a regular expression criterion and suffix criterion in addition to the dateFormatMark since we have other files in the same directory and only wish to match those starting with the characters &amp;quot;CG&amp;quot; that have suffix &amp;quot;.nc&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
Here&#039;s the list of files (relative to the BES data root dir):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
data/ncml/agg/dated/CG2006158_120000h_usfc.nc&lt;br /&gt;
data/ncml/agg/dated/CG2006158_130000h_usfc.nc&lt;br /&gt;
data/ncml/agg/dated/CG2006158_140000h_usfc.nc&lt;br /&gt;
data/ncml/agg/dated/CG2006158_150000h_usfc.nc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;Test of joinNew aggregation using the scan element and dateFormatMark&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;fileTime&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;CGusfc&amp;quot;/&amp;gt;  &lt;br /&gt;
    &amp;lt;scan location=&amp;quot;data/ncml/agg/dated&amp;quot; &lt;br /&gt;
	  suffix=&amp;quot;.nc&amp;quot; &lt;br /&gt;
	  subdirs=&amp;quot;false&amp;quot;&lt;br /&gt;
	  regExp=&amp;quot;^.*/CG[^/]*&amp;quot;&lt;br /&gt;
	  dateFormatMark=&amp;quot;CG#yyyyDDD_HHmmss&amp;quot;&lt;br /&gt;
	  /&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So here we joinNew on the new outer dimension &#039;&#039;fileTime&#039;&#039;.  The new coordinate variable &#039;&#039;&#039;fileTime&#039;&#039;&#039;[&#039;&#039;fileTime&#039;&#039;] for this dimension will be an Array of type String that will contain the parsed [http://en.wikipedia.org/wiki/ISO_8601 ISO 8601] timestamps we will extract from the matching filenames.  &lt;br /&gt;
&lt;br /&gt;
We have specified that we want only Netcdf files (suffix &amp;quot;.nc&amp;quot;) which match the regular expression &amp;quot;^.*/CG[^/]*&amp;quot;.  This means match the start of the string, then any number of characters that end with a &amp;quot;/&amp;quot; (the path portion of the filename), then the letters &amp;quot;CG&amp;quot;, then some number of characters that do &#039;&#039;not&#039;&#039; include the &amp;quot;/&amp;quot; character (which is what &amp;quot;[^/]*&amp;quot; means).  Essentially, we want files whose basename (path stripped) start with &amp;quot;CG&amp;quot; and end with &amp;quot;.nc&amp;quot;.   We also do not want to recurse, but only look in the location directory &amp;quot;/data/ncml/agg/dated&amp;quot; for the files.&lt;br /&gt;
&lt;br /&gt;
Finally, we specify the &#039;&#039;scan@dateFormatMark&#039;&#039; pattern to describe how to parse the filename into an ISO 8601 date.  The &#039;&#039;dateFormatMark&#039;&#039; is processed as follows:&lt;br /&gt;
&lt;br /&gt;
* Skip the &#039;&#039;number&#039;&#039; of characters prior to the &amp;quot;#&amp;quot; mark in the pattern while scanning the base filename (no path)&lt;br /&gt;
* Interpret the next characters of the file basename using the given SimpleDateFormat string&lt;br /&gt;
* Ignore any characters after the SDF portion of the filename (such as the suffix)&lt;br /&gt;
&lt;br /&gt;
First, note that we &#039;&#039;&#039;do not match&#039;&#039;&#039; the characters in the dateFormatMark --- they are simply counted and skipped.  So rather than &amp;quot;CG#&amp;quot; specifying the prefix before the SDF, we could have also used &amp;quot;XX#&amp;quot;.  This is why we must also use a regular expression to filter out files with other prefixes that we do not want in the aggregation.  Note that the &amp;quot;#&amp;quot; is just a marker for the start of the SDF pattern and doesn&#039;t count as an actual character in the matching process.&lt;br /&gt;
&lt;br /&gt;
Second, we specify the dateFormatMark (DFM) as the following SDF pattern: &amp;quot;yyyyDDD_HHmmss&amp;quot;.  This means that we use the four digit year, then the day of the year (a three digit number), then an underscore (&amp;quot;_&amp;quot;) separator, then the 24 hour time as 6 digits.  Let&#039;s take the basename of the first file as an example:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;CG2006158_120000h_usfc.nc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
We skip two characters due to the &amp;quot;CG#&amp;quot; in the DFM.  Then we want to match the &amp;quot;yyyy&amp;quot; pattern for the year with: &amp;quot;2006&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
We then match the day of the year as &amp;quot;DDD&amp;quot; which is &amp;quot;158&amp;quot;, the 158th day of the year for 2006.&lt;br /&gt;
&lt;br /&gt;
We then match the underscore character &amp;quot;_&amp;quot; which is only a separator.&lt;br /&gt;
&lt;br /&gt;
Next, we match the 24 hour time &amp;quot;HHmmss&amp;quot; as 12:00:00 hours:mins:secs (i.e. noon).&lt;br /&gt;
&lt;br /&gt;
Finally, any characters after the DFM are ignored, here &amp;quot;h_usfc.nc&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
We see that the four dataset files are on the same day, but sampled each hour from noon to 3 pm.&lt;br /&gt;
&lt;br /&gt;
These parsed timestamps are then converted to an ISO 8601 date string which is used as the value for the coordinate variable element corresponding to that aggregation member.  The first file would thus have the time value &amp;quot;2006-06-07T12:00:00Z&amp;quot;, which is 7 June 2006 at noon in the GMT timezone.  &lt;br /&gt;
&lt;br /&gt;
The matched files are then &#039;&#039;&#039;sorted using the ISO 8601 timestamp as the sort key&#039;&#039;&#039; and added to the aggregation in this order.  Since ISO 8601 is designed such that lexicographic order is isomorphic to chronological order, this orders the datasets monotonically in time from past to future.  This is different from the &amp;lt;scan&amp;gt; behavior &#039;&#039;without&#039;&#039; a dateFormatMark specified, where files are ordered lexicographically (alphanumerically by full pathname) --- this order may or may not match chronological order.  &lt;br /&gt;
&lt;br /&gt;
If we project out the ASCII dods response for the new coordinate variable, we see all of the parsed timestamps and that they are in chronological order:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
String fileTime[fileTime = 4] = {&amp;quot;2006-06-07T12:00:00Z&amp;quot;, &lt;br /&gt;
&amp;quot;2006-06-07T13:00:00Z&amp;quot;,&lt;br /&gt;
 &amp;quot;2006-06-07T14:00:00Z&amp;quot;, &lt;br /&gt;
&amp;quot;2006-06-07T15:00:00Z&amp;quot;};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also check the resulting DDS to see that it is added as a map vector to the Grid as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Float32 CGusfc[fileTime = 4][time = 1][altitude = 1][lat = 29][lon = 26]&lt;br /&gt;
;&lt;br /&gt;
      Maps:&lt;br /&gt;
        String fileTime[fileTime = 4];&lt;br /&gt;
        Float64 time[time = 1];&lt;br /&gt;
        Float32 altitude[altitude = 1];&lt;br /&gt;
        Float32 lat[lat = 29];&lt;br /&gt;
        Float32 lon[lon = 26];&lt;br /&gt;
    } CGusfc;&lt;br /&gt;
    String fileTime[fileTime = 4];&lt;br /&gt;
} joinNew_scan_dfm.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, we look at the DAS with global metadata removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
  CGusfc {&lt;br /&gt;
        Float32 _FillValue -1.000000033e+32;&lt;br /&gt;
        Float32 missing_value -1.000000033e+32;&lt;br /&gt;
        Int32 numberOfObservations 303;&lt;br /&gt;
        Float32 actual_range -0.2876400054, 0.2763200104;&lt;br /&gt;
        fileTime {&lt;br /&gt;
---&amp;gt;            String _CoordinateAxisType &amp;quot;Time&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        CGusfc {&lt;br /&gt;
        }&lt;br /&gt;
        time {&lt;br /&gt;
            String long_name &amp;quot;End Time&amp;quot;;&lt;br /&gt;
            String standard_name &amp;quot;time&amp;quot;;&lt;br /&gt;
            String units &amp;quot;seconds since 1970-01-01T00:00:00Z&amp;quot;;&lt;br /&gt;
            Float64 actual_range 1149681600.0000000, 1149681600.0000000;&lt;br /&gt;
        }&lt;br /&gt;
        altitude {&lt;br /&gt;
            String long_name &amp;quot;Altitude&amp;quot;;&lt;br /&gt;
            String standard_name &amp;quot;altitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;m&amp;quot;;&lt;br /&gt;
            Float32 actual_range 0.000000000, 0.000000000;&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
            String standard_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
            String point_spacing &amp;quot;even&amp;quot;;&lt;br /&gt;
            Float32 actual_range 37.26869965, 38.02470016;&lt;br /&gt;
            String coordsys &amp;quot;geographic&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
            String standard_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
            String point_spacing &amp;quot;even&amp;quot;;&lt;br /&gt;
            Float32 actual_range 236.5800018, 237.4799957;&lt;br /&gt;
            String coordsys &amp;quot;geographic&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    fileTime {&lt;br /&gt;
---&amp;gt;     String _CoordinateAxisType &amp;quot;Time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that the aggregation has also automatically added the &amp;quot;_CoordinateAxisType&amp;quot; attribute and set it to &amp;quot;Time&amp;quot; (denoted by the &amp;quot;--&amp;gt;&amp;quot;) as defined by the NcML 2.2 specification.  The author may add other metadata to the new coordinate variable as discussed previously.&lt;br /&gt;
&lt;br /&gt;
=== Order of Inclusion ===&lt;br /&gt;
&lt;br /&gt;
In cases where a dateFormatMark is &#039;&#039;not&#039;&#039; specified, the member datasets are added to the aggregation in alphabetical order &#039;&#039;on the full pathname&#039;&#039;.  This is important in the case of subdirectories since the path of the subdirectory is taken into account in the sort.&lt;br /&gt;
&lt;br /&gt;
In cases where a dateFormatMark &#039;&#039;is&#039;&#039; specified, the extracted ISO 8601 timestamp is used as the sorting criterion, with older files being added before newer files.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
	<entry>
		<id>https://docs.opendap.org/index.php?title=Dynamic_Aggregation_Tutorial&amp;diff=5585</id>
		<title>Dynamic Aggregation Tutorial</title>
		<link rel="alternate" type="text/html" href="https://docs.opendap.org/index.php?title=Dynamic_Aggregation_Tutorial&amp;diff=5585"/>
		<updated>2010-04-20T19:22:54Z</updated>

		<summary type="html">&lt;p&gt;Mjohnson: New page: === Location (Location Location...) ===  The most important attribute of the scan element is the &amp;#039;&amp;#039;scan@location&amp;#039;&amp;#039; element that specifies the top-level search directory for the scan, relat...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Location (Location Location...) ===&lt;br /&gt;
&lt;br /&gt;
The most important attribute of the scan element is the &#039;&#039;scan@location&#039;&#039; element that specifies the top-level search directory for the scan, relative to the BES data root directory specified in the BES configuration.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;IMPORTANT&#039;&#039;&#039;:  &#039;&#039;ALL&#039;&#039; locations are interpreted relative to the BES root directory and &#039;&#039;&#039;NOT&#039;&#039;&#039; relative to the location of the NcML file itself!  This means that all data to be aggregated &#039;&#039;&#039;must&#039;&#039;&#039; be in a subdirectory of the BES root data directory and that these directories &#039;&#039;must&#039;&#039; be specified fully, not relative to the NcML file.  &lt;br /&gt;
&lt;br /&gt;
For example, if the BES root data dir is &amp;quot;/usr/local/share/hyrax&amp;quot;, let ${BES_DATA_ROOT} refer to this location.  If the NcML aggregation file is in &amp;quot;${BES_DATA_ROOT}/data/ncml/myAgg.ncml&amp;quot; and the aggregation member datasets are in &amp;quot;${BES_DATA_ROOT}/data/hdf4/myAggDatasets&amp;quot;, then the location in the NcML file for the aggregation data directory would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;scan location=&amp;quot;data/hdf4/myAggDatasets&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which specifies the data directory relative to the BES data root as required.&lt;br /&gt;
&lt;br /&gt;
Again, due to security reasons, the data is always searched under the BES data root.  Trying to specify an absolute filesystem path, such as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;scan location=&amp;quot;/usr/local/share/data&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will &#039;&#039;NOT&#039;&#039; work.  This directory will also be assumed to be a subdirectory of the ${BES_DATA_ROOT}, regardless of the preceding &amp;quot;/&amp;quot; character.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Suffix Criterion ===&lt;br /&gt;
&lt;br /&gt;
The simplest criterion is to match only files of a certain datatype in a given directory.  This is useful for filtering out text files and other files that may exist in the directory but which do not form part of the aggregation data.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s a simple example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;Example of joinNew Grid aggregation using the scan element.&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;scan location=&amp;quot;data/ncml/agg/grids&amp;quot; suffix=&amp;quot;.hdf&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assuming that the specified location &amp;quot;data/ncml/agg/grids&amp;quot; contains no subdirectories, this NcML will return all files in that directory that end in &amp;quot;.hdf&amp;quot; in alphanumerical order.  In the case of our installed example data, there are four HDF4 files in that directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
data/ncml/agg/grids/f97182070958.hdf&lt;br /&gt;
data/ncml/agg/grids/f97182183448.hdf&lt;br /&gt;
data/ncml/agg/grids/f97183065853.hdf&lt;br /&gt;
data/ncml/agg/grids/f97183182355.hdf &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These will be included in alphanumerical order, so the scan element will in effect be equivalent to the following list of &amp;lt;netcdf&amp;gt; elements:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182183448.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183065853.hdf&amp;quot;/&amp;gt;  &lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183182355.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default, scan will search subdirectories, which is why we mentioned &amp;quot;grids has no subdirectories&amp;quot;.  We discuss this in the next section.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Subdirectory Searching (The Default!) ===&lt;br /&gt;
&lt;br /&gt;
If the author specifies the &#039;&#039;scan@subdirs&#039;&#039; attribute to the value &amp;quot;true&amp;quot; (which is the default!), then the criteria will be applied recursively to any subdirectories of the &#039;&#039;scan@location&#039;&#039; base scan directory as well as to any regular files in the base directory.  &lt;br /&gt;
&lt;br /&gt;
For example, continuing our previous example, but giving a higher level location:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinNew Grid aggregation using the scan element.&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;!-- This will recurse into the &amp;quot;grids&amp;quot; subdir and grab all *.hdf files there --&amp;gt;&lt;br /&gt;
    &amp;lt;scan location=&amp;quot;data/ncml/agg/&amp;quot; suffix=&amp;quot;.hdf&amp;quot; subdirs=&amp;quot;true&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assuming that only the &amp;quot;grids&amp;quot; subdir of &amp;quot;/data/ncml/agg&amp;quot; contains HDF4 files with that extension, the same aggregation as prior will be created, i.e. an aggregation isomorphic to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182070958.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97182183448.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183065853.hdf&amp;quot;/&amp;gt;  &lt;br /&gt;
&amp;lt;netcdf location=&amp;quot;data/ncml/agg/grids/f97183182355.hdf&amp;quot;/&amp;gt; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;scan@subdirs&#039;&#039; attribute is much for useful for turning off the default recursion.  For example, if recursion is &#039;&#039;&#039;NOT&#039;&#039;&#039; desired, but only files with the given suffix in the given directory are required, the following will do that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinNew Grid aggregation using the scan element.&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;!-- Find *.hdf files ONLY in the given location and NOT in subdirs --&amp;gt;&lt;br /&gt;
    &amp;lt;scan location=&amp;quot;data/ncml/agg/grids&amp;quot; suffix=&amp;quot;.hdf&amp;quot; subdirs=&amp;quot;false&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== OlderThan Criterion ===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;scan@olderThan&#039;&#039; attribute can be used to filter out files that are &amp;quot;too new&amp;quot;.  This feature is useful for excluding partial files currently being written by a daemon process, for example.  &lt;br /&gt;
&lt;br /&gt;
The value of the attribute is a duration specified by a number followed by a basic time unit.  The time units recognized are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;seconds&#039;&#039;&#039;: { s, sec, secs, second, seconds }&lt;br /&gt;
* &#039;&#039;&#039;minutes&#039;&#039;&#039;: { m, min, mins, minute, minutes }&lt;br /&gt;
* &#039;&#039;&#039;hours&#039;&#039;&#039;: { h, hour, hours }&lt;br /&gt;
* &#039;&#039;&#039;days&#039;&#039;&#039;: { day, days }&lt;br /&gt;
* &#039;&#039;&#039;months&#039;&#039;&#039;: { month, months }&lt;br /&gt;
* &#039;&#039;&#039;years&#039;&#039;&#039;: { year, years }&lt;br /&gt;
&lt;br /&gt;
The strings inside { } are all recognized as referring to the given time unit.  &lt;br /&gt;
&lt;br /&gt;
For example, if we are following our previous example, but we suspect a new HDF file may be written at any time and usually takes 5 minutes to do so, we might use the following NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;joinNew Grid aggregation using the scan element.&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;scan location=&amp;quot;data/ncml/agg/grids&amp;quot; suffix=&amp;quot;.hdf&amp;quot; subdirs=&amp;quot;false&amp;quot; olderThan=&amp;quot;10 mins&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Assuming the file will always be written withing 10 minutes, this files does what we wish.  Only files whose modification date is older than the given duration from the current system time are included.   &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039; that the modification date of the file, not the creation date, is used for the test. &lt;br /&gt;
&lt;br /&gt;
=== Regular Expression Criterion ===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;scan@regExp&#039;&#039; attribute may be used for more complicated filename matching tests where data for multiple variables, for example, may live in the same directory by whose filenames can be used to distinguish which are desired in the aggregation.  Additionally, since the pathname including the location is used for the test, a regular expression test may be used in conjunction with a recursive directory search to find files in subdirectories where the directory name itself is specified in the regular expression, not just the filename.  We&#039;ll give examples of both of these cases.  &lt;br /&gt;
&lt;br /&gt;
We also reiterate that this test is used &#039;&#039;in conjunction&#039;&#039; with any other tests --- the author may also include a suffix and an olderThan test if they wish.  All criteria must match for the file to be included in the aggregation.&lt;br /&gt;
&lt;br /&gt;
We recognize the POSIX regular expression syntax.  For more information on regular expressions and the POSIX syntax, please see: http://en.wikipedia.org/wiki/Regular_expression.&lt;br /&gt;
&lt;br /&gt;
We will give two basic examples: &lt;br /&gt;
&lt;br /&gt;
* Finding all subdirectories with a given name&lt;br /&gt;
* Matching a filename starting with a certain substring&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Matching a Subdirectory Name ====&lt;br /&gt;
Here&#039;s an example where we use a subdirectory search to find &amp;quot;.hdf&amp;quot; files in all subdirectories named &amp;quot;grids&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;Example of joinNew Grid aggregation using the scan element with a regexp&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;!-- Scan from the top for files in a grids subdir and ending in .hdf.&lt;br /&gt;
              We are also using a regexp to match on a path that ends in &amp;quot;grids&amp;quot; &lt;br /&gt;
              and has a suffix of hdf. --&amp;gt;&lt;br /&gt;
    &amp;lt;scan &lt;br /&gt;
       location=&amp;quot;data/&amp;quot; &lt;br /&gt;
       subdirs=&amp;quot;true&amp;quot; &lt;br /&gt;
       regExp=&amp;quot;^.*/grids/.+\.hdf$&amp;quot;&lt;br /&gt;
       /&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The regular expression here is &amp;quot;^.*/grids/.+\/hdf&amp;quot;.  Let&#039;s pull it apart quickly (this is not intended to be a regular expression tutorial):&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;^&amp;quot; matching the beginning of the string, so starts at the beginning of the location pathname.   (without this we can match substrings in the middle of strings, etc)&lt;br /&gt;
&lt;br /&gt;
We then match &amp;quot;.*&amp;quot; meaning 0 or more of any character.&lt;br /&gt;
&lt;br /&gt;
We then match the &amp;quot;/grids/&amp;quot; string explicitly, meaning we want all pathnames that contain &amp;quot;/grids/&amp;quot; as a subdirectory.  &lt;br /&gt;
&lt;br /&gt;
We then match &amp;quot;.+&amp;quot; meaning 1 or more of any character.&lt;br /&gt;
&lt;br /&gt;
We then match &amp;quot;\.&amp;quot; meaning a literal &amp;quot;.&amp;quot; character (the backslash &amp;quot;escapes&amp;quot; it).&lt;br /&gt;
&lt;br /&gt;
We then match the suffix &amp;quot;hdf&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Finally, we match &amp;quot;$&amp;quot; meaning the end of the string.&lt;br /&gt;
&lt;br /&gt;
So ultimately, this regular expression finds all filenames ending in &amp;quot;.hdf&amp;quot; that exist in some subdirectory named &amp;quot;grids&amp;quot; of the top-level location.&lt;br /&gt;
&lt;br /&gt;
In following with our previous example, if there was only the one &amp;quot;grids&amp;quot; subdirectory in the ${BES_DATA_ROOT} with our four familiar files, we&#039;d get the same aggregation as before.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Matching a partial filename ====&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we have a given directory full of data files whose filename prefix specifies which variable they refer to.  For example, let&#039;s say our &amp;quot;grids&amp;quot; directory has files that start with &amp;quot;grad&amp;quot; as well as the files that start with &amp;quot;f&amp;quot; we have seen in our examples.  We still want just the files starting with &amp;quot;f&amp;quot; to filter out the others.  Here&#039;s an example for that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;Example of joinNew Grid aggregation using the scan element with a regexp&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;filename&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;dsp_band_1&amp;quot;/&amp;gt; &lt;br /&gt;
    &amp;lt;!-- Scan from the top for files in a grids subdir and starting with &amp;quot;f&amp;quot; and ending in &amp;quot;.hdf&amp;quot;.&lt;br /&gt;
        --&amp;gt;&lt;br /&gt;
    &amp;lt;scan &lt;br /&gt;
       location=&amp;quot;data/&amp;quot; &lt;br /&gt;
       subdirs=&amp;quot;true&amp;quot; &lt;br /&gt;
       regExp=&amp;quot;^.*/grids/f.+\.hdf$&amp;quot;&lt;br /&gt;
       /&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we match all pathnames ending in &amp;quot;grids&amp;quot; and files that start with the letter &amp;quot;f&amp;quot; and end with &amp;quot;.hdf&amp;quot; as we desire.&lt;br /&gt;
&lt;br /&gt;
=== Date Format Mark and Timestamp Extraction ===&lt;br /&gt;
&lt;br /&gt;
This section shows how to use the &#039;&#039;scan@dateFormatMark&#039;&#039; attribute along with other search criteria in order to extract and sort datasets by a timestamp encoded in the filename.  All that is required is that the timestamp be parseable by a pattern recognized by the Java language &amp;quot;SimpleDateFormat&amp;quot; class ([http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html java.text.SimpleDateFormat]), which has also been implemented in C++ in the [http://site.icu-project.org/  International Components for Unicode] library which we use.&lt;br /&gt;
&lt;br /&gt;
We base this example from the Unidata site [http://www.unidata.ucar.edu/software/netcdf/ncml/v2.2/Aggregation.html Aggregation Tutorial].  Here we have a directory with four files whose filenames contain a timestamp describable by a SimpleDataFormat (SDF) pattern.  We will also use a regular expression criterion and suffix criterion in addition to the dateFormatMark since we have other files in the same directory and only wish to match those starting with the characters &amp;quot;CG&amp;quot; that have suffix &amp;quot;.nc&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
Here&#039;s the list of files (relative to the BES data root dir):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
data/ncml/agg/dated/CG2006158_120000h_usfc.nc&lt;br /&gt;
data/ncml/agg/dated/CG2006158_130000h_usfc.nc&lt;br /&gt;
data/ncml/agg/dated/CG2006158_140000h_usfc.nc&lt;br /&gt;
data/ncml/agg/dated/CG2006158_150000h_usfc.nc&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the NcML:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;netcdf title=&amp;quot;Test of joinNew aggregation using the scan element and dateFormatMark&amp;quot;&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  &amp;lt;aggregation type=&amp;quot;joinNew&amp;quot; dimName=&amp;quot;fileTime&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;variableAgg name=&amp;quot;CGusfc&amp;quot;/&amp;gt;  &lt;br /&gt;
    &amp;lt;scan location=&amp;quot;data/ncml/agg/dated&amp;quot; &lt;br /&gt;
	  suffix=&amp;quot;.nc&amp;quot; &lt;br /&gt;
	  subdirs=&amp;quot;false&amp;quot;&lt;br /&gt;
	  regExp=&amp;quot;^.*/CG[^/]*&amp;quot;&lt;br /&gt;
	  dateFormatMark=&amp;quot;CG#yyyyDDD_HHmmss&amp;quot;&lt;br /&gt;
	  /&amp;gt;&lt;br /&gt;
  &amp;lt;/aggregation&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/netcdf&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So here we joinNew on the new outer dimension &#039;&#039;fileTime&#039;&#039;.  The new coordinate variable &#039;&#039;&#039;fileTime&#039;&#039;&#039;[&#039;&#039;fileTime&#039;&#039;] for this dimension will be an Array of type String that will contain the parsed [http://en.wikipedia.org/wiki/ISO_8601 ISO 8601] timestamps we will extract from the matching filenames.  &lt;br /&gt;
&lt;br /&gt;
We have specified that we want only Netcdf files (suffix &amp;quot;.nc&amp;quot;) which match the regular expression &amp;quot;^.*/CG[^/]*&amp;quot;.  This means match the start of the string, then any number of characters that end with a &amp;quot;/&amp;quot; (the path portion of the filename), then the letters &amp;quot;CG&amp;quot;, then some number of characters that do &#039;&#039;not&#039;&#039; include the &amp;quot;/&amp;quot; character (which is what &amp;quot;[^/]*&amp;quot; means).  Essentially, we want files whose basename (path stripped) start with &amp;quot;CG&amp;quot; and end with &amp;quot;.nc&amp;quot;.   We also do not want to recurse, but only look in the location directory &amp;quot;/data/ncml/agg/dated&amp;quot; for the files.&lt;br /&gt;
&lt;br /&gt;
Finally, we specify the &#039;&#039;scan@dateFormatMark&#039;&#039; pattern to describe how to parse the filename into an ISO 8601 date.  The &#039;&#039;dateFormatMark&#039;&#039; is processed as follows:&lt;br /&gt;
&lt;br /&gt;
* Skip the &#039;&#039;number&#039;&#039; of characters prior to the &amp;quot;#&amp;quot; mark in the pattern while scanning the base filename (no path)&lt;br /&gt;
* Interpret the next characters of the file basename using the given SimpleDateFormat string&lt;br /&gt;
* Ignore any characters after the SDF portion of the filename (such as the suffix)&lt;br /&gt;
&lt;br /&gt;
First, note that we &#039;&#039;&#039;do not match&#039;&#039;&#039; the characters in the dateFormatMark --- they are simply counted and skipped.  So rather than &amp;quot;CG#&amp;quot; specifying the prefix before the SDF, we could have also used &amp;quot;XX#&amp;quot;.  This is why we must also use a regular expression to filter out files with other prefixes that we do not want in the aggregation.  Note that the &amp;quot;#&amp;quot; is just a marker for the start of the SDF pattern and doesn&#039;t count as an actual character in the matching process.&lt;br /&gt;
&lt;br /&gt;
Second, we specify the dateFormatMark (DFM) as the following SDF pattern: &amp;quot;yyyyDDD_HHmmss&amp;quot;.  This means that we use the four digit year, then the day of the year (a three digit number), then an underscore (&amp;quot;_&amp;quot;) separator, then the 24 hour time as 6 digits.  Let&#039;s take the basename of the first file as an example:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;CG2006158_120000h_usfc.nc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
We skip two characters due to the &amp;quot;CG#&amp;quot; in the DFM.  Then we want to match the &amp;quot;yyyy&amp;quot; pattern for the year with: &amp;quot;2006&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
We then match the day of the year as &amp;quot;DDD&amp;quot; which is &amp;quot;158&amp;quot;, the 158th day of the year for 2006.&lt;br /&gt;
&lt;br /&gt;
We then match the underscore character &amp;quot;_&amp;quot; which is only a separator.&lt;br /&gt;
&lt;br /&gt;
Next, we match the 24 hour time &amp;quot;HHmmss&amp;quot; as 12:00:00 hours:mins:secs (i.e. noon).&lt;br /&gt;
&lt;br /&gt;
Finally, any characters after the DFM are ignored, here &amp;quot;h_usfc.nc&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
We see that the four dataset files are on the same day, but sampled each hour from noon to 3 pm.&lt;br /&gt;
&lt;br /&gt;
These parsed timestamps are then converted to an ISO 8601 date string which is used as the value for the coordinate variable element corresponding to that aggregation member.  The first file would thus have the time value &amp;quot;2006-06-07T12:00:00Z&amp;quot;, which is 7 June 2006 at noon in the GMT timezone.  &lt;br /&gt;
&lt;br /&gt;
The matched files are then &#039;&#039;&#039;sorted using the ISO 8601 timestamp as the sort key&#039;&#039;&#039; and added to the aggregation in this order.  Since ISO 8601 is designed such that lexicographic order is isomorphic to chronological order, this orders the datasets monotonically in time from past to future.  This is different from the &amp;lt;scan&amp;gt; behavior &#039;&#039;without&#039;&#039; a dateFormatMark specified, where files are ordered lexicographically (alphanumerically by full pathname) --- this order may or may not match chronological order.  &lt;br /&gt;
&lt;br /&gt;
If we project out the ASCII dods response for the new coordinate variable, we see all of the parsed timestamps and that they are in chronological order:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
String fileTime[fileTime = 4] = {&amp;quot;2006-06-07T12:00:00Z&amp;quot;, &lt;br /&gt;
&amp;quot;2006-06-07T13:00:00Z&amp;quot;,&lt;br /&gt;
 &amp;quot;2006-06-07T14:00:00Z&amp;quot;, &lt;br /&gt;
&amp;quot;2006-06-07T15:00:00Z&amp;quot;};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We also check the resulting DDS to see that it is added as a map vector to the Grid as well:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Dataset {&lt;br /&gt;
    Grid {&lt;br /&gt;
      Array:&lt;br /&gt;
        Float32 CGusfc[fileTime = 4][time = 1][altitude = 1][lat = 29][lon = 26]&lt;br /&gt;
;&lt;br /&gt;
      Maps:&lt;br /&gt;
        String fileTime[fileTime = 4];&lt;br /&gt;
        Float64 time[time = 1];&lt;br /&gt;
        Float32 altitude[altitude = 1];&lt;br /&gt;
        Float32 lat[lat = 29];&lt;br /&gt;
        Float32 lon[lon = 26];&lt;br /&gt;
    } CGusfc;&lt;br /&gt;
    String fileTime[fileTime = 4];&lt;br /&gt;
} joinNew_scan_dfm.ncml;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, we look at the DAS with global metadata removed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Attributes {&lt;br /&gt;
  CGusfc {&lt;br /&gt;
        Float32 _FillValue -1.000000033e+32;&lt;br /&gt;
        Float32 missing_value -1.000000033e+32;&lt;br /&gt;
        Int32 numberOfObservations 303;&lt;br /&gt;
        Float32 actual_range -0.2876400054, 0.2763200104;&lt;br /&gt;
        fileTime {&lt;br /&gt;
---&amp;gt;            String _CoordinateAxisType &amp;quot;Time&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        CGusfc {&lt;br /&gt;
        }&lt;br /&gt;
        time {&lt;br /&gt;
            String long_name &amp;quot;End Time&amp;quot;;&lt;br /&gt;
            String standard_name &amp;quot;time&amp;quot;;&lt;br /&gt;
            String units &amp;quot;seconds since 1970-01-01T00:00:00Z&amp;quot;;&lt;br /&gt;
            Float64 actual_range 1149681600.0000000, 1149681600.0000000;&lt;br /&gt;
        }&lt;br /&gt;
        altitude {&lt;br /&gt;
            String long_name &amp;quot;Altitude&amp;quot;;&lt;br /&gt;
            String standard_name &amp;quot;altitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;m&amp;quot;;&lt;br /&gt;
            Float32 actual_range 0.000000000, 0.000000000;&lt;br /&gt;
        }&lt;br /&gt;
        lat {&lt;br /&gt;
            String long_name &amp;quot;Latitude&amp;quot;;&lt;br /&gt;
            String standard_name &amp;quot;latitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_north&amp;quot;;&lt;br /&gt;
            String point_spacing &amp;quot;even&amp;quot;;&lt;br /&gt;
            Float32 actual_range 37.26869965, 38.02470016;&lt;br /&gt;
            String coordsys &amp;quot;geographic&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        lon {&lt;br /&gt;
            String long_name &amp;quot;Longitude&amp;quot;;&lt;br /&gt;
            String standard_name &amp;quot;longitude&amp;quot;;&lt;br /&gt;
            String units &amp;quot;degrees_east&amp;quot;;&lt;br /&gt;
            String point_spacing &amp;quot;even&amp;quot;;&lt;br /&gt;
            Float32 actual_range 236.5800018, 237.4799957;&lt;br /&gt;
            String coordsys &amp;quot;geographic&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    fileTime {&lt;br /&gt;
---&amp;gt;     String _CoordinateAxisType &amp;quot;Time&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We see that the aggregation has also automatically added the &amp;quot;_CoordinateAxisType&amp;quot; attribute and set it to &amp;quot;Time&amp;quot; (denoted by the &amp;quot;--&amp;gt;&amp;quot;) as defined by the NcML 2.2 specification.  The author may add other metadata to the new coordinate variable as discussed previously.&lt;br /&gt;
&lt;br /&gt;
=== Order of Inclusion ===&lt;br /&gt;
&lt;br /&gt;
In cases where a dateFormatMark is &#039;&#039;not&#039;&#039; specified, the member datasets are added to the aggregation in alphabetical order &#039;&#039;on the full pathname&#039;&#039;.  This is important in the case of subdirectories since the path of the subdirectory is taken into account in the sort.&lt;br /&gt;
&lt;br /&gt;
In cases where a dateFormatMark &#039;&#039;is&#039;&#039; specified, the extracted ISO 8601 timestamp is used as the sorting criterion, with older files being added before newer files.&lt;/div&gt;</summary>
		<author><name>Mjohnson</name></author>
	</entry>
</feed>