Goal

In this article, we use extended ISO 19139 XML types to create a custom ISO 19115 metadata extension, as specified by the ISO 19139:2007 standard, chapter 8.5.3. We also show how you can configure the TLcdISO19139MetadataDecoder and TLcdISO19139MetadataEncoder to handle this kind of metadata.

Define the custom extension

For the purpose of this tutorial, we’re going to extend MD_DataIdentification and add an extra license property. The new 'license' property expresses the name of the license that applies to the data resource. Conceptually, the diagram Figure 1, “Extension of the MD_DataIdentification element” shows where we defined the new EXT_DataIdentification element.

extension
Figure 1. Extension of the MD_DataIdentification element

In an ISO 19139 XML file, this extension corresponds to an EXT_DataIdentification XML element with a license sub-element. This element can replace the MD_DataIdentification element, as shown in the Example ISO 19139 XML file.

Example ISO 19139 XML file
<gmd:MD_Metadata xmlns:gmd="http://www.isotc211.org/2005/gmd"
                 xmlns:gco="http://www.isotc211.org/2005/gco"
                 xmlns:ext="http://mycompany.com/xsd/metadata"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://mycompany.com/xsd/metadata schema.xsd">
  <gmd:identificationInfo>
    <ext:EXT_DataIdentification gco:isoType="MD_DataIdentification">
      <gmd:citation>
        <gmd:CI_Citation>
          <gmd:title>
            <gco:CharacterString>Sample test file</gco:CharacterString>
          </gmd:title>
        </gmd:CI_Citation>
      </gmd:citation>
      <ext:license>
        <gco:CharacterString>Apache License, Version 2.0</gco:CharacterString>
      </ext:license>
    </ext:EXT_DataIdentification>
  </gmd:identificationInfo>
</gmd:MD_Metadata>

The TLcdISO19139MetadataDecoder supports this kind of ISO metadata extension. In the next steps, we show how to extract the license value from this example metadata file.

Define the XML schema

We start by creating an XML schema for this extension. The TLcdISO19139MetadataDecoder and TLcdISO19139MetadataEncoder use this schema to handle our extension.

First, we import the standard ISO 19139 namespaces that we need for this sample:

Importing ISO 19139 namespaces
<xs:schema targetNamespace="http://mycompany.com/xsd/metadata"
           elementFormDefault="qualified"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:gmd="http://www.isotc211.org/2005/gmd"
           xmlns:gco="http://www.isotc211.org/2005/gco"
           xmlns:ext="http://mycompany.com/xsd/metadata">
  <xs:import namespace="http://www.isotc211.org/2005/gco"/>
  <xs:import namespace="http://www.isotc211.org/2005/gmd"/>

Then, we create an XML type for our EXT_DataIdentification element with a license child element. This name of this new type is EXT_DataIdentification_Type and it extends the default MD_DataIdentification_Type type.

Create the extended XML type
<xs:element name="EXT_DataIdentification" substitutionGroup="gmd:AbstractMD_Identification" type="ext:EXT_DataIdentification_Type"/>
<xs:complexType name="EXT_DataIdentification_Type">
  <xs:complexContent>
    <xs:extension base="gmd:MD_DataIdentification_Type">
      <xs:sequence>
        <xs:element name="license" type="gco:CharacterString_PropertyType" minOccurs="0" />
      </xs:sequence>
      <xs:attribute ref="gco:isoType" use="required" fixed="MD_DataIdentification"/>
    </xs:extension>
  </xs:complexContent>
</xs:complexType>

Define the data model

To configure the TLcdISO19139MetadataDecoder and TLcdISO19139MetadataEncoder to use the XML schema defined in the XML schema section, we must load it into a TLcdDataModel. To create such a model, we use a TLcdXMLDataModelBuilder, and we provide it with our XML schema to build the data model.

Creating the data model
TLcdDataModelBuilder dataModelBuilder = new TLcdDataModelBuilder("http://mycompany.com/xsd/metadata");
TLcdXMLDataModelBuilder xmlBuilder = new TLcdXMLDataModelBuilder(TLcdISO19115DataTypes.getDataModel());
xmlBuilder.buildDataModel(
    dataModelBuilder,
    "http://mycompany.com/xsd/metadata",
    "/path/to/extension/schema.xsd");
TLcdDataModel dataModel = dataModelBuilder.createDataModel();
return dataModel;

The Creating the data model code generates a TLcdDataModel containing all the standard ISO types, together with the types of our extension. However, it doesn’t map our own types to specific classes, but to their ISO parent type. For instance, because our EXT_DataIdentification_Type type extends from the standard ISO MD_DataIdentification_Type, it’s mapped to a TLcdISO19115DataIdentification instance, which is its parent type. This class implements the ILcdDataObject interface, which we can use to get value of the license property in a generic way.

It’s more convenient to assign a dedicated class to our EXT_DataIdentification element. In that dedicated class, we can also encapsulate the logic to access our license property. To do so, we start by creating a utility class that holds our data model and gives easy access to our custom EXT_DataIdentification_Type type.

Creating a dedicated class for the data model
import com.luciad.datamodel.TLcdDataModel;
import com.luciad.datamodel.TLcdDataModelBuilder;
import com.luciad.datamodel.TLcdDataType;
import com.luciad.format.metadata.model.TLcdISO19115DataTypes;
import com.luciad.format.xml.bind.schema.dataobject.TLcdXMLDataModelBuilder;

public class CustomExtensionDataTypes {

  public static final TLcdDataType EXT_DataIdentification_Type;
  private static final TLcdDataModel DATAMODEL;

  static {
    DATAMODEL = createDataModel();
    EXT_DataIdentification_Type = DATAMODEL.getDeclaredType("EXT_DataIdentification_Type");
  }

  private CustomExtensionDataTypes() {
  }

  public static TLcdDataModel getDataModel() {
    return DATAMODEL;
  }

  private static TLcdDataModel createDataModel() {
    TLcdDataModelBuilder dataModelBuilder = new TLcdDataModelBuilder("http://mycompany.com/xsd/metadata");
    TLcdXMLDataModelBuilder xmlBuilder = new TLcdXMLDataModelBuilder(TLcdISO19115DataTypes.getDataModel());
    xmlBuilder.buildDataModel(
        dataModelBuilder,
        "http://mycompany.com/xsd/metadata",
        "/path/to/extension/schema.xsd");
    dataModelBuilder.typeBuilder("EXT_DataIdentification_Type").instanceClass(ExtendedDataIdentification.class);
    TLcdDataModel dataModel = dataModelBuilder.createDataModel();
    return dataModel;
  }
}

Now we create the dedicated class for our EXT_DataIdentification element. This class extends from TLcdISO19115DataIdentification. We also add a getter and setter method for the license property so that we can easily retrieve its value while decoding or encoding.

Creating a dedicated class for the extended element
public class ExtendedDataIdentification extends TLcdISO19115DataIdentification {

  private static final TLcdDataProperty LICENSE_PROPERTY =
      CustomExtensionDataTypes.EXT_DataIdentification_Type.getProperty("license");

  private static final TLcdDataType STRING_TYPE =
      TLcdXMLDataModelBuilder.getDataObjectTypeForPrimitiveType(TLcdCoreDataTypes.STRING_TYPE);

  public ExtendedDataIdentification() {
    super(CustomExtensionDataTypes.EXT_DataIdentification_Type);
  }

  public String getLicense() {
    TLcdISO19115Optional<?> licenseDataObject = (TLcdISO19115Optional<?>) getValue(LICENSE_PROPERTY);
    if (licenseDataObject == null) {
      return null;
    }

    ILcdDataObject characterString = (ILcdDataObject) licenseDataObject.getValueObject();
    if (characterString == null) {
      return null;
    }

    return (String) characterString.getValue(STRING_TYPE.getProperty("value"));
  }

  public void setLicense(String aLicense) {
    if (aLicense == null) {
      setValue(LICENSE_PROPERTY, null);
      return;
    }

    ILcdDataObject licenseCharacterString = STRING_TYPE.newInstance();
    licenseCharacterString.setValue("value", aLicense);

    TLcdISO19115Optional<Object> license = new TLcdISO19115Optional<>(LICENSE_PROPERTY.getType());
    license.setValueObject(licenseCharacterString);
    setValue(LICENSE_PROPERTY, license);
  }
}

We use these classes in the examples that follow.

Decode our extended metadata

If the XML documents properly refer to extension schemas in their xsi:schemaLocation attribute, the TLcdISO19139MetadataDecoder automatically detects the extension schemas and configures itself accordingly. However, in our case, we also want to make use of our new ExtendedDataIdentification class, so we pass our own data model when we create a TLcdISO19139MetadataDecoder.

Decode custom metadata
TLcdISO19139MetadataDecoder decoder = new TLcdISO19139MetadataDecoder(CustomExtensionDataTypes.getDataModel());
TLcdISO19115Metadata metadata = decoder.decodeMetadata(xmlFile);

The MD_Metadata element holds the identification elements in a list. We can retrieve it directly from the metadata variable. In our example, we assume it’s the first one in the list. Because we created the decoder with our custom data model, we can cast the identification element to our dedicated class and easily get the value of the license property.

Getting the license property value
ExtendedDataIdentification identification = (ExtendedDataIdentification) metadata.getIdentificationInfo().get(0);
String license = identification.getLicense();

Encode our extended metadata

Let’s start by building the metadata in code. First, we create our extended identification and set the license. This is straightforward because we can use our dedicated ExtendedDataIdentification class. Next, we create a TLcdISO19115Metadata object and add our extended identification to it.

Using the extended identification with a license for the data model
ExtendedDataIdentification identification = new ExtendedDataIdentification();

// set the license information
identification.setLicense("Test license");

// set the title
TLcdISO19115Citation citation = new TLcdISO19115Citation();
citation.setTitle("Sample test file");
identification.setCitation(citation);

TLcdISO19115Metadata metadata = new TLcdISO19115Metadata();
metadata.getIdentificationInfo().add(identification);

To encode this metadata into a ISO 19139 XML file, we create a TLcdISO19139MetadataEncoder with our custom data model.

Creating the metadata encoder
TLcdISO19139MetadataEncoder encoder = new TLcdISO19139MetadataEncoder(CustomExtensionDataTypes.getDataModel());
encoder.encodeMetadata(metadata, xmlFile);