Author: desruisseaux Date: Fri Nov 30 08:53:47 2012 New Revision: 1415547 URL: http://svn.apache.org/viewvc?rev=1415547&view=rev Log: Updated the developer guide for the code commited in the last month.
Modified: sis/branches/JDK7/src/main/docbook/book.xsl sis/branches/JDK7/src/main/docbook/fr/XML.xml sis/branches/JDK7/src/main/docbook/fr/utility.xml sis/branches/JDK7/src/site/resources/book/book.css Modified: sis/branches/JDK7/src/main/docbook/book.xsl URL: http://svn.apache.org/viewvc/sis/branches/JDK7/src/main/docbook/book.xsl?rev=1415547&r1=1415546&r2=1415547&view=diff ============================================================================== --- sis/branches/JDK7/src/main/docbook/book.xsl (original) +++ sis/branches/JDK7/src/main/docbook/book.xsl Fri Nov 30 08:53:47 2012 @@ -95,6 +95,9 @@ <xsl:template match= "d:function[@role = 'OGC']" mode="class.value"> <xsl:value-of select="'OGC'" /> </xsl:template> <xsl:template match= "d:function[@role = 'GeoAPI']" mode="class.value"> <xsl:value-of select="'GeoAPI'"/> </xsl:template> <xsl:template match= "d:function[@role = 'SIS']" mode="class.value"> <xsl:value-of select="'SIS'" /> </xsl:template> + <xsl:template match= "d:constant[@role = 'OGC']" mode="class.value"> <xsl:value-of select="'OGC'" /> </xsl:template> + <xsl:template match= "d:constant[@role = 'GeoAPI']" mode="class.value"> <xsl:value-of select="'GeoAPI'"/> </xsl:template> + <xsl:template match= "d:constant[@role = 'SIS']" mode="class.value"> <xsl:value-of select="'SIS'" /> </xsl:template> <xsl:template match= "d:literal[@role = 'OGC']" mode="class.value"> <xsl:value-of select="'OGC'" /> </xsl:template> <xsl:template match= "d:literal[@role = 'GeoAPI']" mode="class.value"> <xsl:value-of select="'GeoAPI'"/> </xsl:template> <xsl:template match= "d:literal[@role = 'SIS']" mode="class.value"> <xsl:value-of select="'SIS'" /> </xsl:template> Modified: sis/branches/JDK7/src/main/docbook/fr/XML.xml URL: http://svn.apache.org/viewvc/sis/branches/JDK7/src/main/docbook/fr/XML.xml?rev=1415547&r1=1415546&r2=1415547&view=diff ============================================================================== --- sis/branches/JDK7/src/main/docbook/fr/XML.xml (original) +++ sis/branches/JDK7/src/main/docbook/fr/XML.xml Fri Nov 30 08:53:47 2012 @@ -226,5 +226,64 @@ public class MyClass { où peuvent être manipulés tous types dâidentifiants (pas seulement <acronym>XML</acronym>) associés à un objet. </para> </section> + + <section> + <title>Représentation de valeurs manquantes</title> + <para> + Lorsquâun attribut nâest pas défini, la méthode correspondante de GeoAPI retourne généralement <literal>null</literal>. + Toutefois les choses se compliquent lorsque lâattribut manquant est une valeur considérée comme obligatoire par le standard <acronym>ISO</acronym> 19115. + Le standard <acronym>ISO</acronym> 19139 autorise lâomission dâattributs obligatoires à la condition dâindiquer pourquoi la valeur est manquante. + Les raisons peuvent être que lâattribut ne sâapplique pas (<constant role="OGC">inapplicable</constant>), + que la valeur existe probablement mais nâest pas connue (<constant role="OGC">unknown</constant>), + que la valeur pourrait ne pas exister (<constant role="OGC">missing</constant>), + quâelle ne peut pas être divulguée (<constant role="OGC">withheld</constant>), <foreignphrase>etc.</foreignphrase> + La transmission de cette information nécessite lâutilisation dâun objet non-nul même lorsque la valeur est manquante. + <acronym>SIS</acronym> procède en retournant un objet qui, en plus dâimplémenter lâinterface GeoAPI attendue, + implémente aussi lâinterface <classname role="SIS">org.apache.xml.NilObject</classname>. + Cette interface marque les instances dont toutes les méthodes retournent une collection vide, + un tableau vide, <literal>null</literal>, <literal>NaN</literal>, <literal>0</literal> ou <literal>false</literal>, + dans cet ordre de préférence selon ce que les types de retours des méthodes permettent. + Chaque instance implémentant <classname role="SIS">NilObject</classname> fournit une méthode + <classname role="SIS">getNilReason()</classname> indiquant pourquoi lâobjet est nul. + </para> + <para> + Dans lâexemple suivant, la partie gauche montre un élément <classname role="OGC">CI_Citation</classname> + contenant un élément <classname role="OGC">CI_Series</classname>, alors que dans la partie droite la série est inconnue. + Si lâélément <classname role="OGC">CI_Series</classname> avait été complètement omis + (ce qui est illégal selon les standards <acronym>ISO</acronym> mais toléré par <acronym>SIS</acronym>), + alors la méthode <function role="GeoAPI">Citation.getSeries()</function> retournerait <literal>null</literal> en Java. + Mais en présence dâun attribut <literal role="OGC">nilReason</literal>, lâimplémentation <acronym>SIS</acronym> + de <function role="SIS">getSeries()</function> retournera plutôt un objet implémentant à la fois les interfaces + <classname role="GeoAPI">Series</classname> et <classname role="SIS">NilReason</classname>, + et dont la méthode <function role="SIS">getNilReason()</function> retournera la constante <constant role="SIS">UNKNOWN</constant>. + </para> + <example> + <title>Ãlément obligatoire marqué comme inconnu dans une méta-donnée</title> + <informaltable frame="none"> + <tgroup cols="2"> + <colspec colwidth="50%"/> + <colspec colwidth="50%"/> + <tbody> + <row> + <entry> + <programlisting language="xml"><gmd:CI_Citation> + <gmd:series> + <gmd:CI_Series> + <!-- Some content here --> + </gmd:CI_Series> + </gmd:series> +</gmd:CI_Citation></programlisting> + </entry> + <entry> + <programlisting language="xml"><gmd:CI_Citation> + <gmd:series nilReason="unknown"/> +</gmd:CI_Citation></programlisting> + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + </example> + </section> </section> </chapter> Modified: sis/branches/JDK7/src/main/docbook/fr/utility.xml URL: http://svn.apache.org/viewvc/sis/branches/JDK7/src/main/docbook/fr/utility.xml?rev=1415547&r1=1415546&r2=1415547&view=diff ============================================================================== --- sis/branches/JDK7/src/main/docbook/fr/utility.xml (original) +++ sis/branches/JDK7/src/main/docbook/fr/utility.xml Fri Nov 30 08:53:47 2012 @@ -13,6 +13,72 @@ </para> <section> + <title>Modes de comparaisons des objets</title> + <para> + Il existe différentes opinions sur la façon dâimplémenter la méthode <function>Object.equals(Object)</function> du Java standard. + Selon certains, il doit être possible de comparer différentes implémentations dâune même interface ou classe de base. + Mais cette politique nécessite que chaque interface ou classe de base définisse entièrement dans sa Javadoc les critères ou calculs + que doivent employer les méthodes <function>equals(Object)</function> et <function>hashCode()</function> dans toutes les implémentations. + Cette approche est choisie notamment par <classname>java.util.Collection</classname> et ses interfaces filles. + Elle se fait toutefois au détriment de la possibilité de prendre en compte des attributs supplémentaires dans les interfaces filles, + si cette possibilité nâa pas été spécifiée dans lâinterface parente. + Cette contrainte découle des points suivants du contrat des méthodes <function>equals(Object)</function> et <function>hashCode()</function>: + </para> + <itemizedlist> + <listitem><literal>A.equals(B)</literal> implique <literal>B.equals(A)</literal> (symétrie);</listitem> + <listitem><literal>A.equals(B)</literal> et <literal>B.equals(C)</literal> implique <literal>A.equals(C)</literal> (transitivité);</listitem> + <listitem><literal>A.equals(B)</literal> implique <literal>A.hashCode() == B.hashCode()</literal>.</listitem> + </itemizedlist> + <para> + Par exemple ces trois contraintes sont violées si <varname>A</varname> (et éventuellement <varname>C</varname>) + peuvent contenir des attributs que <varname>B</varname> ignore. + Pour contourner cette difficulté, une approche alternative consiste à exiger que les objets comparés par la méthode + <function>Object.equals(Object)</function> soient exactement de la même classe, câest-à -dire que <literal>A.getClass() == B.getClass()</literal>. + Cette approche est parfois considérée contraire aux principes de la programmation orientée objets. + Dans la pratique, pour des applications relativement complexes, ça dépend du contexte dans lequel les objets sont comparés: + si les objets sont ajoutés à un <classname>HashSet</classname> ou utilisés comme clés dans un <classname>HashMap</classname>, + alors nous avons besoin dâun strict respect du contrat de <function>equals(Object)</function> et <function>hashCode()</function>. + Mais si le développeur compare les objets lui-même, par exemple pour vérifier si des informations qui lâintéresse ont changées, + alors les contraintes de symétrie, transitivité ou de cohérence avec les valeurs de hachages peuvent ne pas être pertinentes pour lui. + Des comparaisons plus permissives peuvent être souhaitables, allant parfois jusquâà tolérer de légers écarts dans les valeurs numériques. + </para> + <para> + Afin de donner une certaine flexibilité aux développeurs, un grand nombre de classes de la bibliothèque <acronym>SIS</acronym> + implémentent lâinterface <classname role="SIS">org.apache.sis.util.LenientComparable</classname>, qui défini une méthode <function role="SIS">equals(Object, ComparisonMode)</function>. + Les principaux modes de comparaisons sont: + </para> + <itemizedlist> + <listitem><para> + <emphasis role="bold"><constant role="SIS">STRICT</constant></emphasis> â Les objets comparés doivent être de la même classe + et tous leurs attributs strictement égaux, y compris dâéventuels attributs publics propres à lâimplémentation. + </para></listitem> + <listitem><para> + <emphasis role="bold"><constant role="SIS">BY_CONTRACT</constant></emphasis> â Les objets comparés doivent implémenter la même interface de GeoAPI (ou tout autre standard), + mais nâont pas besoin dâêtre de la même classe dâimplémentation. Seuls les attributs définis dans lâinterface sont comparés; + tout autres attributs propres à lâimplémentation â même sâils sont publics â sont ignorés. + </para></listitem> + <listitem><para> + <emphasis role="bold"><constant role="SIS">IGNORE_METADATA</constant></emphasis> â Comme <constant role="SIS">BY_CONTRACT</constant>, + mais ne compare que les attributs qui influencent les opérations (calculs numériques ou autre) effectuées par lâobjet. + Par exemple dans un référentiel géodésique, la longitude (par rapport à Greenwich) du méridien dâorigine sera pris en compte + alors que le nom de ce méridien sera ignoré. + </para></listitem> + <listitem><para> + <emphasis role="bold"><constant role="SIS">APPROXIMATIVE</constant></emphasis> â Comme <constant role="SIS">IGNORE_METADATA</constant>, + mais tolère de légères différences dans les valeurs numériques. + </para></listitem> + </itemizedlist> + <para> + Le mode par défaut, utilisé par les toutes les méthodes <function>equals(Object)</function> de <acronym>SIS</acronym>, + est <constant role="SIS">STRICT</constant>. Ce mode est choisi à la fois pour une utilisation plus sécuritaire avec <classname>HashMap</classname>, + et aussi parce que définir rigoureusement le contrat des méthodes <function>equals(Object)</function> et <function>hashCode()</function> + dans les centaines dâinterfaces de GeoAPI semble une entreprise peu réaliste, qui risque dâêtre assez peu suivit par les diverses implémentations. + </para> + </section> + + + + <section> <title>Internationalisation</title> <para> Dans une architecture où un programme exécuté sur un serveur fournit ses données à plusieurs clients, @@ -26,7 +92,7 @@ </para> <section> - <title>Instances distinctes pour chaque conventions locales</title> + <title>Chaînes de caractères distinctes pour chaque conventions locales</title> <para> Certaines classes ne sont conçues que pour fonctionner selon une convention locale à la fois. Câest évidemment le cas des implémentations standards de <classname>java.text.Format</classname>, @@ -34,7 +100,7 @@ Mais câest aussi le cas de dâautres classes moins évidentes comme <classname>javax.imageio.ImageReader</classname>/<classname>ImageWriter</classname> ainsi que les exceptions. Lorsque une de ces classes est implémentée par <acronym>SIS</acronym>, - nous lâidentifions en implémentant lâinterface <classname role="SIS">Localized</classname>. + nous lâidentifions en implémentant lâinterface <classname role="SIS">org.apache.sis.util.Localized</classname>. La méthode <function role="SIS">getLocale()</function> de cette interface permet alors de déterminer selon quelles conventions locales lâinstance produira ses messages. </para> @@ -99,5 +165,95 @@ pour des raisons dâéconomie de mémoire. </para> </section> + + <section> + <title>Traitement des caractères</title> + <para> + Les chaînes de caractères en Java utilisent lâencodage UTF-16. Il existe une correspondance directe + entre les valeurs de type <classname>char</classname> et la très grande majorité des caractères, ce + qui facilite lâutilisation des chaînes lorsque ces caractères suffisent. + Mais certains caractères Unicode ne sont pas représentables par un seul <classname>char</classname>. + Ces <firstterm>caractères supplémentaires</firstterm> comprennent certains idéogrammes, + mais aussi des symboles routiers et géographiques dans la plage 1F680 à 1F700. + Le support de ces caractères supplémentaires nécessite des itérations un peu plus complexes + que le cas classique où lâon supposait une correspondance directe. + Ainsi, au lieu de la boucle de gauche ci-dessous, les applications internationales devraient + généralement utiliser la boucle de droite: + </para> + <example> + <title>Boucle sur une chaîne pouvant contenir des caractères supplémentaires</title> + <informaltable frame="none"> + <tgroup cols="2"> + <colspec colwidth="50%"/> + <colspec colwidth="50%"/> + <tbody> + <row> + <entry> + <programlisting language="java">for (int i=0; i<string.length(); i++) { + char c = string.charAt(i); + if (Character.isWhitespace(c)) { + // Un espace blanc a été trouvé. + } +}</programlisting> + </entry> + <entry> + <programlisting language="java">for (int i=0; i<string.length();) { + int c = string.codePointAt(i); + if (Character.isWhitespace(c)) { + // Un espace blanc a été trouvé. + } + i += Character.charCount(c); +}</programlisting> + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + </example> + <para> + <acronym>SIS</acronym> supporte les caractères supplémentaires en utilisant la boucle de droite lorsque nécessaire. + Mais la boucle de gauche reste occasionnellement utilisée lorsquâil est connu que les caractères recherchés ne sont + pas des caractères supplémentaires, même si la chaîne dans laquelle on fait la recherche peut en contenir. + </para> + + <section> + <title>Interprétation des espaces blancs</title> + <para> + Le Java standard fournit deux méthodes pour déterminer si un caractères est un espace blanc: + <function>Character.isWhitespace(â¦)</function> et <function>Character.isSpaceChar(â¦)</function>. + Ces deux méthodes diffèrent dans leurs interprétations des espaces insécables, des tabulations et des retours à la ligne. + La première méthode est conforme à lâinterprétation couramment utilisée dans des langages telles que le Java, C/C++ et XML, + qui considère les tabulations et retours à la ligne comme des espaces blancs, + alors que les espaces insécables sont interprétés comme des caractères non-blanc. + La seconde méthode â strictement conforme à la définition Unicode â fait lâinterprétation inverse. + </para> + <para> + <acronym>SIS</acronym> emploie ces deux méthodes dans des contextes différents. + <function>isWhitespace(â¦)</function> est utilisée pour <emphasis>séparer</emphasis> + les éléments dâune liste (nombres, dates, mots, <foreignphrase>etc.</foreignphrase>), + tandis que <function>isSpaceChar(â¦)</function> est utilisée pour ignorer les espaces + blancs <emphasis>à lâintérieur</emphasis> dâun seul élément. + </para> + <informalexample><para> + <emphasis role="bold">Exemple:</emphasis> + Supposons une liste de nombres représentés selon les conventions françaises. + Chaque nombre peut contenir des <emphasis>espace insécables</emphasis> comme séparateurs des milliers, + tandis que les différents nombres de la liste peuvent être séparés par des espaces ordinaires, des tabulations ou des retours à la ligne. + Pendant lâanalyse dâun nombre, on veut considérer les espaces insécables comme faisant partie du nombre, + alors quâune tabulation ou un retour à la ligne indique très probablement une séparation entre ce nombre et le nombre suivant. + On utilisera donc <function>isSpaceChar(â¦)</function>. + Inversement, lors de la séparation des nombres de la liste, on veut considérer les tabulations et + les retours à la ligne comme des séparateurs mais pas les espaces insécables. + On utilisera donc <function>isWhitespace(â¦)</function>. + Le rôle des espaces ordinaires, qui pourraient sâappliquer aux deux cas, doit être décidé en amont. + </para></informalexample> + <para> + Dans la pratique, cette distinction se traduit pas une utilisation de <function>isSpaceChar(â¦)</function> + dans les implémentations de <classname>java.text.Format</classname>, + et une utilisation de <function>isWhitespace(â¦)</function> dans pratiquement tout le reste + de la bibliothèque <acronym>SIS</acronym>. + </para> + </section> + </section> </section> </chapter> Modified: sis/branches/JDK7/src/site/resources/book/book.css URL: http://svn.apache.org/viewvc/sis/branches/JDK7/src/site/resources/book/book.css?rev=1415547&r1=1415546&r2=1415547&view=diff ============================================================================== --- sis/branches/JDK7/src/site/resources/book/book.css (original) +++ sis/branches/JDK7/src/site/resources/book/book.css Fri Nov 30 08:53:47 2012 @@ -54,10 +54,18 @@ p { */ pre.programlisting { border-style: solid; + border-color: gray; border-width: 1pt; padding: 9pt; } +/* If inside a table, rely on the table border instead. */ +table pre.programlisting { + border-style: none; + margin: 0pt; + padding: 0pt; +} + div.sidebar { margin-left: 1.25cm; margin-right: 1.5cm; @@ -79,11 +87,22 @@ div.informalexample { /* * Tables. */ +div.informaltable table tr { + vertical-align: top; +} + +div.informaltable table tr td { + border-style: solid; + border-color: gray; + border-width: 1pt; + padding: 9pt; +} + div.table p.title { text-align: center; } -table { +div.table-contents table { margin-left: auto; margin-right: auto; border-style: solid; @@ -91,25 +110,25 @@ table { border-spacing: 0pt; } -table tr th { +div.table-contents table tr th { background-color: #B9DCFF; border-bottom-style: solid; border-bottom-width: 1pt; padding: 3pt; } -table tr td { +div.table-contents table tr td { padding-left: 9pt; padding-right: 9pt; } -table tr td.leftBorder { +div.table-contents table tr td.leftBorder { border-left-style: solid; border-left-width: 1pt; border-left-color: lightgray; } -table tr td.separator { +div.table-contents table tr td.separator { text-align: center; font-weight: bold; background-color: #EEEEFF;