content/fr/developer-guide/storage/XML-ISO-19115.html (232 lines of code) (raw):
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
<head>
<title>XML-ISO-19115</title>
<meta charset="UTF-8"/>
<link rel="stylesheet" type="text/css" href="../book.css"/>
</head>
<body>
<!--
Content below this point is copied in "/static/book/fr/developer-guide.html" file
by the 'org.apache.sis.internal.book.Assembler' class in 'sis-build-helper' module.
-->
<section>
<header>
<h3 id="XML-ISO-19115">Représentation des méta-données selon <abbr>ISO</abbr> 19115-3</h3>
</header>
<p>
Pour chaque classe de méta-donnée, il existe un type <abbr>XML</abbr> portant le même nom que dans la spécification abstraite
(par exemple <code>mdb:MD_Metadata</code> et <code>cit:CI_Citation</code>).
Tous ces types peuvent être employés comme racine d’un document <abbr>XML</abbr>.
Ainsi, il est possible d’écrire un document représentant un objet <code>MD_Metadata</code> complet,
ou d’écrire un document représentant seulement un objet <code>CI_Citation</code>.
</p>
<p>
Le standard <abbr>ISO</abbr> 19139 dispose le contenu de ces objets d’une manière inhabituelle:
pour chaque propriété dont le type de la valeur est lui-même une autre classe du standard <abbr>ISO</abbr> 19139,
la valeur est enveloppée dans un élément qui représente son type plutôt que d’être écrite directement.
Par exemple dans un objet de type <code>CI_Citation</code>,
la valeur de la propriété <code class="OGC">citedResponsibleParty</code>
est enveloppée dans un élément <code>CI_Responsibility</code>.
Cette pratique double la profondeur de l’arborescence, en introduisant une duplication
à tous les niveaux pour chaque valeur, comme dans l’exemple suivant:
</p>
<pre><samp class="xml"><b><MD_Metadata></b>
<identificationInfo>
<b><MD_DataIdentification></b>
<citation>
<b><CI_Citation></b>
<citedResponsibleParty>
<b><CI_Responsibility></b>
<party>
<b><CI_Party></b>
<contactInfo>
<b><CI_Contact></b>
<onlineResource>
<b><CI_OnlineResource></b>
<linkage>
<URL>https://www.ogc.org</URL>
</linkage>
<b></CI_OnlineResource></b>
</onlineResource>
<b></CI_Contact></b>
</contactInfo>
<b></CI_Party></b>
</party>
<b></CI_Responsibility></b>
</citedResponsibleParty>
<b></CI_Citation></b>
</citation>
<b></MD_DataIdentification></b>
</identificationInfo>
<b></MD_Metadata></b></samp></pre>
<p>
L’exemple précédent, comme tous les documents conformes à <abbr>ISO</abbr> 19139,
est donc constitué d’une alternance systématique de deux types d’éléments <abbr>XML</abbr> imbriqués:
</p>
<ol>
<li><p>
Il y a d’abord le nom de la propriété, qui commence toujours par une lettre minuscule (en ignorant les préfixes).
Dans les <abbr>API</abbr> Java, chaque propriété correspond à une méthode de la classe englobante.
Dans l’exemple ci-haut, <code>mdb:identificationInfo</code> (une propriété de la classe <code>MD_Metadata</code>)
correspond à la méthode <code>Metadata.getIdentificationInfo()</code>.
</p></li>
<li><p>
Sous chaque propriété se trouve le type de la valeur, sauf si elle a été remplacée par une référence
(la <a href="#gco-id">sous-section suivante</a> suivante approfondira ce sujet).
Le type de la valeur est un élément <abbr>XML</abbr> dont le nom commence toujours par une lettre majuscule, en ignorant les préfixes.
Dans l’exemple ci-haut nous avions <code>MD_DataIdentification</code>, qui correspond à l’interface Java <code>DataIdentification</code>.
C’est cet élément <abbr>XML</abbr> qui contient les valeurs de la propriété.
</p></li>
</ol>
<p>
Afin de réduire la complexité des bibliothèques, GeoAPI et Apache <abbr>SIS</abbr>
n’exposent publiquement qu’une vision unifiée de ces deux types d’éléments.
L’<abbr>API</abbr> public correspond essentiellement au deuxième groupe.
Toutefois, lors de l’écriture d’un document <abbr>XML</abbr>, des éléments du premier groupe doivent être temporairement recréés.
Les classes qui y correspondent sont définies dans des paquets internes de <abbr>SIS</abbr>.
Ces classes peuvent être ignorées, sauf si le développeur souhaite implémenter ses propres classes
dont les instances devront être lues et écrites par <abbr>JAXB</abbr>.
</p>
<aside id="XML-SIS">
<h3>Stratégie d’implémentation dans Apache <abbr>SIS</abbr></h3>
<p>
Les paquets <code>org.apache.sis.internal.jaxb.*</code> (non-publiques)
définissent des adaptateurs <abbr>JAXB</abbr> pour tous les types d’objet <abbr>ISO</abbr>.
Ces adaptateurs sont de toute façon nécessaires pour permettre à <abbr>JAXB</abbr>
d’obtenir les classes <abbr>SIS</abbr> implémentant les interfaces de GeoAPI.
De manière opportuniste, <abbr>SIS</abbr> en fait à la fois des adaptateurs <abbr>JAXB</abbr>
et des objets enveloppants le “vrai” objet à lire ou écrire.
Cette utilisation double permet d’éviter d’avoir à doubler le nombre de classes
(déjà très élevé) présents dans les paquets internes.
</p>
<h4>Convention de nommage dans les schémas <abbr>XSD</abbr></h4>
<p>
Les schémas <abbr>XSD</abbr> de l’<abbr>OGC</abbr> définissent pour chaque élément du premier groupe
un type dont le nom se termine par “<code class="OGC">_PropertyType</code>”.
Pour le second groupe, chaque élément a un type dont le nom se termine par “<code class="OGC">_Type</code>”.
Les “<code class="OGC">_PropertyType</code>” peuvent avoir un groupe d’attributs
(notamment <code>gco:uuidref</code> et <code>xlink:href</code>)
que les schémas <abbr>XSD</abbr> nomment collectivement <code>gco:ObjectReference</code>.
Ces attributs n’ont pas de méthodes Java dédiées, mais sont accessibles indirectement via l’interface
<code class="SIS">IdentifiedObject</code> décrite dans la sous-section suivante.
</p>
</aside>
<h4 id="gco-id">Identification d’instances déjà définies</h4>
<p>
L’élément englobant peut contenir un attribut <code class="OGC">id</code> ou <code class="OGC">uuid</code>.
Si un de ces attributs est présent, l’élément englobé peut être complètement omis;
il sera remplacé au moment de la lecture par l’élément référencé par l’attribut.
Dans l’exemple suivant, la partie gauche définie un élément associé à l’identifiant “<code>mon_id</code>”,
alors que la partie droite référence cet élément:
</p>
<div class="row-of-boxes">
<div>
<div class="caption">Définir un identifiant</div>
<pre style="margin-top: 6pt"><samp class="xml"><MD_MetaData>
<identificationInfo>
<MD_DataIdentification id="<b>mon_id</b>">
<!-- insérer ici des propriétés filles -->
</MD_DataIdentification>
</identificationInfo>
</MD_MetaData></samp></pre>
</div>
<div>
<div class="caption">Utiliser l’identifiant défini</div>
<pre style="margin-top: 6pt"><samp class="xml"><MD_MetaData>
<identificationInfo xlink:href="<b>#mon_id</b>"/>
</MD_MetaData></samp></pre>
</div>
</div>
<p>
Le choix de l’attribut à utiliser dépend de la portée de l’élément référencé:
</p>
<ul>
<li>
<code class="OGC">id</code> n’est valide qu’à l’intérieur du document <abbr>XML</abbr>
qui définit l’objet ainsi référencé.
</li>
<li>
<code class="OGC">uuid</code> peut être valide à l’extérieur du document <abbr>XML</abbr>,
mais quelqu’un doit maintenir une base de données fournissant les objets pour chaque UUID donnés.
</li>
<li>
<code>xlink:href</code> peut faire référence à un autre document <abbr>XML</abbr> accessible sur internet.
</li>
</ul>
<p>
Dans la bibliothèque <abbr>SIS</abbr>, tous les objets susceptibles d’être identifiés dans un document <abbr>XML</abbr>
implémentent l’interface <code>org.apache.sis.xml.IdentifiedObject</code>.
Chaque instance de cette interface fournit une vue de ses identifiants sous forme de <code>Map<Citation,String></code>,
dans lequel la clé <code>Citation</code> identifie le type d’identifiant et la valeur est l’identifiant lui-même.
Quelques constantes représentant différents types d’identifiants sont énumérées dans <code>IdentifierSpace</code>,
notamment <code class="SIS">ID</code>, <code class="SIS">UUID</code> et <code class="SIS">HREF</code>.
Chacune de ces clés peut être associée à une valeur d’un type différent (habituellement <code>String</code>,
<code>UUID</code> ou <code>URI</code>) selon la clé.
Par exemple le code suivant définit une valeur pour l’attribut <code class="OGC">uuid</code>:
</p>
<pre><code>import org.apache.sis.metadata.iso.DefaultMetadata;
import org.apache.sis.xml.IdentifierSpace;
import java.util.UUID;
public class MyClass {
public void myMethod() {
UUID identifier = UUID.randomUUID();
<code class="SIS">DefaultMetadata</code> metadata = new <code class="SIS">DefaultMetadata</code>();
metadata.<code class="SIS">getIdentifierMap().putSpecialized</code>(IdentifierSpace.UUID, identifier);
}
}</code></pre>
<p>
Bien que ce mécanisme aie été définit dans le but de mieux supporter les représentations des
attributs <abbr>XML</abbr> du groupe <code>gco:ObjectIdentification</code>,
il permet aussi de manière opportuniste de manipuler d’autres types d’identifiants.
Par exemple les attributs <code class="GeoAPI">ISBN</code> et <code class="GeoAPI">ISSN</code>
de <code>Citation</code> peuvent être manipulés de cette manière.
Les méthodes de l’interface <code class="SIS">IdentifiedObject</code> fournissent donc un endroit unique
où peuvent être manipulés tous types d’identifiants (pas seulement <abbr>XML</abbr>) associés à un objet.
</p>
<h4 id="nilReason">Représentation de valeurs manquantes</h4>
<p>
Lorsqu’une propriété n’est pas définie, la méthode correspondante de GeoAPI retourne généralement <code>null</code>.
Toutefois les choses se compliquent lorsque la propriété manquante est une valeur considérée comme obligatoire par le standard <abbr>ISO</abbr> 19115.
Le standard <abbr>ISO</abbr> 19139 autorise l’omission de propriétés obligatoires à la condition d’indiquer pourquoi la valeur est manquante.
Les raisons peuvent être que la propriété ne s’applique pas (<code class="OGC">inapplicable</code>),
que la valeur existe probablement mais n’est pas connue (<code class="OGC">unknown</code>),
que la valeur pourrait ne pas exister (<code class="OGC">missing</code>),
qu’elle ne peut pas être divulguée (<code class="OGC">withheld</code>), <i>etc.</i>
La transmission de cette information nécessite l’utilisation d’un objet non-nul même lorsque la valeur est manquante.
<abbr>SIS</abbr> procède en retournant un objet qui, en plus d’implémenter l’interface GeoAPI attendue,
implémente aussi l’interface <code>org.apache.sis.xml.NilObject</code>.
Cette interface marque les instances dont toutes les méthodes retournent une collection vide,
un tableau vide, <code>null</code>, <code>NaN</code>, <code>0</code> ou <code>false</code>,
dans cet ordre de préférence selon ce que les types de retours des méthodes permettent.
Chaque instance implémentant <code>NilObject</code> fournit une méthode
<code class="SIS">getNilReason()</code> indiquant pourquoi l’objet est nul.
</p>
<p>
Dans l’exemple suivant, la partie gauche montre un élément <code>CI_Citation</code>
contenant un élément <code>CI_Series</code>, alors que dans la partie droite la série est inconnue.
Si l’élément <code>CI_Series</code> avait été complètement omis,
alors la méthode <code>Citation.getSeries()</code> retournerait <code>null</code> en Java.
Mais en présence d’un attribut <code class="OGC">nilReason</code>, l’implémentation <abbr>SIS</abbr>
de <code class="SIS">getSeries()</code> retournera plutôt un objet implémentant à la fois les interfaces
<code>Series</code> et <code class="SIS">NilReason</code>,
et dont la méthode <code class="SIS">getNilReason()</code> retournera la constante <code class="SIS">UNKNOWN</code>.
</p>
<div class="row-of-boxes">
<div>
<div class="caption">Information présente</div>
<pre style="margin-top: 6pt"><samp class="xml"><CI_Citation>
<series>
<CI_Series>
<!-- insérer ici des propriétés filles -->
</CI_Series>
</series>
</CI_Citation></samp></pre>
</div>
<div>
<div class="caption">Information absente</div>
<pre style="margin-top: 6pt"><samp class="xml"><CI_Citation>
<series nilReason="unknown"/>
</CI_Citation></samp></pre>
</div>
</div>
</section>
</body>
</html>