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.
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.
<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:
<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.
<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.
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.
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.
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
.
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.
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.
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.
TLcdISO19139MetadataEncoder encoder = new TLcdISO19139MetadataEncoder(CustomExtensionDataTypes.getDataModel());
encoder.encodeMetadata(metadata, xmlFile);