# RFC 43: GDALMajorObject::GetMetadataDomainList

Author: Even Rouault

Contact: even dot rouault at spatialys.com

## Summary

This (mini)RFC proposes a new virtual method, GetMetadataDomainList(), in the GDALMajorObject class (and a C API) to return the list of all available metadata domains.

## Background

GDALMajorObject currently offers the GetMetadata() and GetMetadataItem() methods that both accept a metadata domain argument. But there is no way to auto-discover which metadata domains are valid for a given GDALMajorObject (i.e. a dataset or raster band). This make it impossible to have generic code that can exhaustively discover all metadata in a dataset/raster band.

## Implementation

The base implementation in GDALMajorObject just calls GetDomainList() on the internal oMDMD member.

    /************************************************************************/
    /*                      GetMetadataDomainList()                         */
    /************************************************************************/

    /**
     * \brief Fetch list of metadata domains.
     *
     * The returned string list is the list of (non-empty) metadata domains.
     *
     * This method does the same thing as the C function GDALGetMetadataDomainList().
     *
     * @return NULL or a string list. Must be freed with CSLDestroy()
     *
     * @since GDAL 1.11
     */

    char **GDALMajorObject::GetMetadataDomainList()
    {
        return CSLDuplicate(oMDMD.GetDomainList());
    }

This method is also available in the C API ( char ** CPL_STDCALL GDALGetMetadataDomainList( GDALMajorObjectH hObject) ) and Swig bindings.

## Impacted drivers

Drivers that have custom implementations of GetMetadata() and/or GetMetadataItem() will generally have to also implement GetMetadataDomainList(), when they don't modify the oMDMD member.

To make it easy to implement the specialized GetMetadataDomainList(), GDALMajorObject will offer a protected BuildMetadataDomainList() method that can be used like the following :

    /************************************************************************/
    /*                      GetMetadataDomainList()                         */
    /************************************************************************/

    char **NITFDataset::GetMetadataDomainList()
    {
        return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
                                       TRUE,
                                       "NITF_METADATA", "NITF_DES", "NITF_DES_METADATA",
                                       "NITF_FILE_HEADER_TRES", "NITF_IMAGE_SEGMENT_TRES",
                                       "CGM", "TEXT", "TRE", "xml:TRE", "OVERVIEWS", NULL);
    }

The TRUE parameter means that the list of domains that follows are potential domains, and thus BuildMetadataDomainList() will check for each one that GetMetadata() returns a non-NULL value.

An exhaustive search in GDAL drivers has been made and all drivers that needed to be updated to implement GetMetadataDomainList() have been updated: ADRG, BAG, CEOS2, DIMAP, ECW, ENVISAT, ERS, GeoRaster (cannot check myself that it compiles), GIF, GTiff, HDF4, JPEG, MBTILES, netCDF, NITF, OGDI, PCIDSK, PDF, PNG, PostgisRaster, RasterLite, RS2, VRT, WCS, WebP, WMS.

A few caveats :

- For MBTiles, WMS and VRT, GetMetadataDomainList(), at the band level, will return "LocationInfo" as a valid metadata domain (used by the gdallocationinfo utility), even if GetMetadata("LocationInfo") itself does not return metadata : you have to call GetMetadataItem("Pixel_someX_someY", "LocationInfo") or GetMetadataItem("GeoPixel_someX_someY", "LocationInfo").

- For CEOS2 and ENVISAT, the list of metadata domains cannot be established easily. GetMetadataDomainList() will return the pattern of accepted domain names.

## Impacted utilities

The gdalinfo utility is extended to accept :

- a "-listmdd" option that will print the metadata domains available,

    $ gdalinfo ../autotest/gdrivers/data/byte_with_xmp.jpg -listmdd

    Driver: JPEG/JPEG JFIF
    Files: ../autotest/gdrivers/data/byte_with_xmp.jpg
    Size is 20, 20
    Coordinate System is `'
    Metadata domains:
      xml:XMP
    Corner Coordinates:
    Upper Left  (    0.0,    0.0)
    Lower Left  (    0.0,   20.0)
    Upper Right (   20.0,    0.0)
    Lower Right (   20.0,   20.0)
    Center      (   10.0,   10.0)
    Band 1 Block=20x1 Type=Byte, ColorInterp=Gray
      Metadata domains:
        IMAGE_STRUCTURE
      Image Structure Metadata:
        COMPRESSION=JPEG

- and "-mdd all" will display the content of all metadata domains.

    $ gdalinfo ../autotest/gdrivers/data/byte_with_xmp.jpg -mdd all

    Driver: JPEG/JPEG JFIF
    Files: ../autotest/gdrivers/data/byte_with_xmp.jpg
    Size is 20, 20
    Coordinate System is `'
    Metadata (xml:XMP):
    <?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
    <x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 7.89'>
    <rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>

     <rdf:Description rdf:about=''
      xmlns:dc='http://purl.org/dc/elements/1.1/'>
      <dc:description>
       <rdf:Alt>
        <rdf:li xml:lang='x-default'>Description</rdf:li>
       </rdf:Alt>
      </dc:description>
      <dc:subject>
       <rdf:Bag>
        <rdf:li>XMP</rdf:li>
        <rdf:li>Test</rdf:li>
       </rdf:Bag>
      </dc:subject>
      <dc:title>
       </rdf:Alt>
      </dc:title>
     </rdf:Description>

     <rdf:Description rdf:about=''
      xmlns:tiff='http://ns.adobe.com/tiff/1.0/'>
      <tiff:BitsPerSample>
       <rdf:Seq>
        <rdf:li>8</rdf:li>
       </rdf:Seq>
      </tiff:BitsPerSample>
      <tiff:Compression>1</tiff:Compression>
      <tiff:ImageLength>20</tiff:ImageLength>
      <tiff:ImageWidth>20</tiff:ImageWidth>
      <tiff:PhotometricInterpretation>1</tiff:PhotometricInterpretation>
      <tiff:PlanarConfiguration>1</tiff:PlanarConfiguration>
      <tiff:SamplesPerPixel>1</tiff:SamplesPerPixel>
     </rdf:Description>
    </rdf:RDF>
    </x:xmpmeta>

    <?xpacket end='w'?>
    Corner Coordinates:
    Upper Left  (    0.0,    0.0)
    Lower Left  (    0.0,   20.0)
    Upper Right (   20.0,    0.0)
    Lower Right (   20.0,   20.0)
    Center      (   10.0,   10.0)
    Band 1 Block=20x1 Type=Byte, ColorInterp=Gray
      Image Structure Metadata:
        COMPRESSION=JPEG

## Backward Compatibility

This change has no impact on backward compatibility at the C API/ABI and C++ API levels. But it impacts C++ ABI, so it requires a full rebuild of all GDAL drivers.

## Testing

The Python autotest suite will be extended to test the new API in a few drivers.

## Ticket

Ticket #5275 has been opened to track the progress of this RFC.

The implementation is available in an attachment to ticket 5275.

## Voting history

+1 from EvenR, DanielM and JukkaR