content/developer-guide/annexes/geoapi/DefinitionProcess.html (345 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="en"> <head> <title>SpecificationToInterfaces</title> <meta charset="UTF-8"/> <link rel="stylesheet" type="text/css" href="../../book.css"/> </head> <body> <!-- Content below this point is copied in "/asf-staging/book/en/developer-guide.html" file by the `org.apache.sis.buildtools.book` class in `buildSrc`. --> <section> <header> <h3 id="SpecificationToInterfaces">From <abbr>OGC</abbr> specifications to Java interfaces</h3> </header> <p> GeoAPI interfaces are sometimes generated from other files provided by <abbr>OGC</abbr>, like <abbr>XSD</abbr> files. But there is always a manual revision, and often modifications compared to automatically generated Java files. It would have been possible to automatically generate Java interfaces from <abbr>OGC</abbr> standards using existing tools. For example one of the most commonly-used approaches is to transform <a href="http://schemas.opengis.net/gml/3.3/"><abbr>XSD</abbr> schemas</a> into Java interfaces using command line utility <code>xjc</code>. As this utility is included in most Java distributions (it is one of the <a href="http://jaxb.java.net"><abbr>JAXB</abbr></a> tools), this approach is favoured by many projects found on the Internet. Other approaches use tools integrated into the Eclipse Development Environment, which is based on <abbr>UML</abbr> schemas rather than <abbr>XSD</abbr> ones. A similar approach was attempted in the early days of the GeoAPI project, but was quickly abandoned. We favor a manual approach for the following reasons: </p> <ul> <li> <p> Some <abbr>XSD</abbr> schemas are much more verbose than the original <abbr>UML</abbr> schemas. Converting from <abbr>XSD</abbr> schemas introduces — at least in the case of metadata — almost double the number of interfaces actually defined by the standard, without adding any new features. <abbr>XSD</abbr> schemas also define attributes specific to <abbr>XML</abbr> documents (<code class="OGC">id</code>, <code class="OGC">uuid</code>, <code>xlink:href</code>, <i>etc.</i>), that do not exist in the original <abbr>UML</abbr> diagrams, and which we do not necessarily wish to expose in a Java <abbr>API</abbr>. Converting from <abbr>UML</abbr> schemas avoids this problem, but tools capable of performing this operation are less common. </p> <div class="example"><p><b>Example:</b> <abbr>XSD</abbr> metadata schemas insert a <code>&lt;cit:CI_Citation&gt;</code> element inside a <code class="OGC">&lt;cit:citation&gt;</code>, a <code>&lt;cit:CI_OnlineResource&gt;</code> element inside a <code class="OGC">&lt;cit:onlineResource&gt;</code>, and so on for the hundreds of classes defined by <abbr>ISO</abbr> 19115 standard. This redundancy is certainly not necessary in a Java program. </p></div> </li> <li> <p> <abbr>OGC</abbr> standards use different naming conventions than Java. In particular, the names of almost all <abbr>OGC</abbr> classes begin with a two-letter prefix, such as <code>MD_Identifier</code>. This prefixes fulfill the same role as package names in Java. GeoAPI adapts this practice by using interface names without prefixes and placing these interfaces in packages corresponding to the prefixes, but with more descriptive names. Occasionally we also change the names; for example, to avoid acronyms, or to conform to an established convention such as JavaBeans. </p> <div class="example"><p><b>Example:</b> The <abbr>OGC</abbr> class <code>MD_Identifier</code> becomes the <code>Identifier</code> interface in the <code>org.opengis.metadata</code> package. The <abbr>OGC</abbr> class <code>SC_CRS</code> becomes the <code>CoordinateReferenceSystem</code> interface, and the <code class="OGC">usesDatum</code> association becomes a <code class="API">getDatum()</code> method, rather than the “<code>getUsesDatum()</code>” that would result from an automatic conversion tool. We do not allow programs to blindly apply rules that ignore the conventions of the community whose schemas we translate. </p></div> </li> <li> <p> The standards may contain structures that do not have a direct equivalent in Java, such as unions similar to what we would find in C/C++. The strategy used to obtain an equivalent feature in Java depends on the context: multiple inheritance of interfaces, modification of the hierarchy, or simply omitting the union. These decisions are made case-by-case based on a needs analysis. </p> <div class="example"><p><b>Example:</b> <abbr>ISO</abbr> 19111 standard defines different types of coordinate systems, such as spherical, cylindrical, polar or Cartesian. It then defines several <em>subsets</em> of these types of coordinate systems systems. These subsets, represented by unions, serve to specify that a class may only be associated with a particular type of coordinate system. For example, a union of types may be associated with an image, named <code>CS_ImageCS</code>, which can only contain <code>CS_CartesianCS</code> and <code>CS_AffineCS</code>. In this case, we get the desired effect in Java through a modification of the hierarchy of classes: we define the <code>CartesianCS</code> interface as a specialization of <code>AffineCS</code>, which is semantically correct. But it is not possible to apply a similar strategy to other unions without violating the semantics. </p></div> </li> <li> <p> Several specifications overlap. GeoAPI performs the work of integration by replacing some duplicate structures with references to equivalent structures from the standards that best represent them. </p> <div class="example"><p><b>Example:</b> <abbr>ISO</abbr> 19115:2003 standard, which defines metadata structures, also attempts to describe a few structures representing coordinate reference systems (<abbr title="Coordinate Reference System">CRS</abbr>). Yet these are also the focus of another standard: <abbr>ISO</abbr> 19111. At the same time, <abbr>ISO</abbr> 19111:2007 states in section 3 that it reuses all of the elements of <abbr>ISO</abbr> 19115:2003 except <code>MD_CRS</code> and its components. GeoAPI interfaces reduce the redundancy by applying the exclusion recommended by <abbr>ISO</abbr> 19111 to the entire project. </p></div> </li> <li> <p> The complexity of some standards have increased for historical reasons rather than technical ones, related to the standardization process. GeoAPI reduces the technical debt by designing interfaces with each element in its proper place, regardless of the chronological order in which the standards were published. </p> <div class="example"><p><b>Example:</b> <abbr>ISO</abbr> 19115-2 standard is an extension of <abbr>ISO</abbr> 19115-1 standard, adding image metadata structures. These metadata were defined in a separate standard because they were not yet ready when the first part of the standard was published. As it was not possible for administrative reasons to add attributes to already-published classes, the new attributes were added in a sub-class bearing almost the same name. Thus, <abbr>ISO</abbr> 19115-2 defines the class <code>MI_Band</code>, which extends the class <code>MD_Band</code> from <abbr>ISO</abbr> 19115-1 by adding attributes that would have appeared directly in the parent class if there were ready on time. In GeoAPI, we have chosen to “repair” these anomalies by fusing these two classes into a single interface. </p></div> </li> </ul> <p> Deviations from the standards are documented in each affected class and method. Each mention of a deviation is also collected on a <a href="http://www.geoapi.org/3.0/javadoc/departures.html">single page</a> in order to provide an overview. Since these deviations blur the relationships between the standards and certain Java interfaces, the correspondence between these languages is explained by <code>@UML</code> annotations and property files described in the following section. </p> <h4 id="UML-annotation">Explicit mapping given by <code>@UML</code> annotations</h4> <p> For each class, method and constant defined by an <abbr>OGC</abbr> or <abbr>ISO</abbr> standard, GeoAPI indicates its provenance using annotations defined in the <code>org.opengis.annotation</code> package. In particular, the <code>@UML</code> annotations indicates the standard, the name of the element in that standard, and also its obligation. For example, in the following code snippet, the first <code>@UML</code> code indicates that the Java interface that follows (<code>ProjectedCRS</code>) is defined using the <code>SC_ProjectedCRS</code> type of <abbr>ISO</abbr> 19111 standard. The second <code>@UML</code> annotation, this time applied to the <code class="API">getCoordinateSystem()</code> method, indicates that this method is defined using the <code class="OGC">coordinateSystem</code> association of <abbr>ISO</abbr> 19111 standard, and that this association is mandatory — meaning, in Java, that the method is not allowed to return a <code>null</code> value. </p> <pre><code>package <code class="API">org.opengis.referencing.crs</code>; /** * A 2D coordinate reference system used to approximate the shape of the earth on a planar surface. */ @UML(specification=ISO_19111, identifier="<code class="OGC">SC_ProjectedCRS</code>") public interface ProjectedCRS extends GeneralDerivedCRS { /** * Returns the coordinate system, which must be Cartesian. */ @UML(obligation=MANDATORY, specification=ISO_19111, identifier="<code class="OGC">coordinateSystem</code>") CartesianCS <code class="API">getCoordinateSystem()</code>; }</code></pre> <p> Java reflection methods allow access to this information during the execution of an application. This is useful for displaying UML identifiers for users familiar with <abbr>OGC</abbr> standards, or for writing elements in an <abbr>XML</abbr> document. Class <code>org.apache.sis.util.iso.Types</code> provides static convenience methods like <code class="SIS">getStandardName(Class)</code> for such operations. For example the following code will display “Standard name of type <code>org.opengis.referencing.crs.ProjectedCRS</code> is <code>SC_ProjectedCRS</code>”: </p> <pre><code>Class&lt;?&gt; type = ProjectedCRS.class; System.out.println("Standard name of type " + type.getName() + " is " + Types.getStandardName(type));</code></pre> <p> The <code class="SIS">Types.forStandardName(String)</code> convenience method performs the reverse operation. Applications who want to perform those operations without SIS convenience methods can follow indications provided in a <a href="#UML-annotation-geoapi">separated chapter</a>. </p> <h4 id="MappingToJDK">Implicit mapping to standard <abbr>JDK</abbr></h4> <p> Some classes and methods have neither an <code>@UML</code> annotation, nor an entry in the <code class="API">class-index.properties</code> file. They are either extensions of GeoAPI, or else types defined in other libraries, such as standard <abbr title="Java Development Kit">JDK</abbr>. In this last case, the mapping to <abbr>ISO</abbr> standards is implicit. The following table describes this mapping for <abbr>ISO</abbr> 19103 types. Java’s primitive types are preferred when applicable, but where necessary their wrappers are used in order to authorize null values. </p> <table> <caption>Mapping between <abbr>ISO</abbr> 19103 and <abbr>JDK</abbr> types</caption> <tr> <th><abbr>ISO</abbr> type</th> <th><abbr>JDK</abbr> type</th> <th>Remarks</th> </tr> <tr> <td class="separator" colspan="2">Numbers</td> <td class="leftBorder"></td> </tr> <tr> <td><code class="OGC">Integer</code></td> <td><code>int</code></td> <td class="leftBorder">Sometimes <code>java.lang.Integer</code> for optional attributes.</td> </tr> <tr> <td><code class="OGC">Integer</code> (in some cases)</td> <td><code>long</code></td> <td class="leftBorder">Sometimes <code>java.lang.Long</code> for optional attributes.</td> </tr> <tr> <td><code class="OGC">Real</code></td> <td><code>double</code></td> <td class="leftBorder">Sometimes <code>java.lang.Double</code> for optional attributes.</td> </tr> <tr> <td><code class="OGC">Decimal</code></td> <td><code>java.math.BigDecimal</code></td> <td class="leftBorder"></td> </tr> <tr> <td><code class="OGC">Number</code></td> <td><code>java.lang.Number</code></td> <td class="leftBorder"></td> </tr> <tr> <td class="separator" colspan="2">Texts</td> <td class="leftBorder"></td> </tr> <tr> <td><code class="OGC">FreeText</code></td> <td>(no equivalent)</td> <td class="leftBorder">See <code class="API">org.opengis.util.InternationalString</code> below.</td> </tr> <tr> <td><code class="OGC">CharacterString</code></td> <td><code>java.lang.String</code></td> <td class="leftBorder">Often <code class="API">org.opengis.util.InternationalString</code> (see below).</td> </tr> <tr> <td><code class="OGC">LocalisedCharacterString</code></td> <td><code>java.lang.String</code></td> <td class="leftBorder"></td> </tr> <tr> <td><code class="OGC">Sequence&lt;Character&gt;</code></td> <td><code>java.lang.CharSequence</code></td> <td class="leftBorder"></td> </tr> <tr> <td><code class="OGC">Character</code></td> <td><code>char</code></td> <td class="leftBorder"></td> </tr> <tr> <td class="separator" colspan="2">Dates and hours</td> <td class="leftBorder"></td> </tr> <tr> <td><code class="OGC">Date</code></td> <td><code>java.util.Date</code></td> <td class="leftBorder"></td> </tr> <tr> <td><code class="OGC">Time</code></td> <td><code>java.util.Date</code></td> <td class="leftBorder"></td> </tr> <tr> <td><code class="OGC">DateTime</code></td> <td><code>java.util.Date</code></td> <td class="leftBorder"></td> </tr> <tr> <td class="separator" colspan="2">Collections</td> <td class="leftBorder"></td> </tr> <tr> <td><code class="OGC">Collection</code></td> <td><code>java.util.Collection</code></td> <td class="leftBorder"></td> </tr> <tr> <td><code class="OGC">Bag</code></td> <td><code>java.util.Collection</code></td> <td class="leftBorder">A <code class="OGC">Bag</code> is similar to a <code class="OGC">Set</code> without being restricted by uniqueness.</td> </tr> <tr> <td><code class="OGC">Set</code></td> <td><code>java.util.Set</code></td> <td class="leftBorder"></td> </tr> <tr> <td><code class="OGC">Sequence</code></td> <td><code>java.util.List</code></td> <td class="leftBorder"></td> </tr> <tr> <td><code class="OGC">Dictionary</code></td> <td><code>java.util.Map</code></td> <td class="leftBorder"></td> </tr> <tr> <td><code class="OGC">KeyValuePair</code></td> <td><code>java.util.Map.Entry</code></td> <td class="leftBorder"></td> </tr> <tr> <td class="separator" colspan="2">Enumerations</td> <td class="leftBorder"></td> </tr> <tr> <td><code class="OGC">Enumeration</code></td> <td><code>java.lang.Enum</code></td> <td class="leftBorder"></td> </tr> <tr> <td><code class="OGC">CodeList</code></td> <td>(no equivalent)</td> <td class="leftBorder">See <code>org.opengis.util.CodeList</code> below.</td> </tr> <tr> <td class="separator" colspan="2">Various</td> <td class="leftBorder"></td> </tr> <tr> <td><code class="OGC">Boolean</code></td> <td><code>boolean</code></td> <td class="leftBorder">Sometimes <code>java.lang.Boolean</code> for optional attributes.</td> </tr> <tr> <td><code class="OGC">Any</code></td> <td><code>java.lang.Object</code></td> <td class="leftBorder"></td> </tr> </table> <p> The nearest equivalent for <code>CharacterString</code> is the <code>String</code> class, but GeoAPI often uses the <code>InternationalString</code> interface, allowing the client to choose the language. For example, it is useful on a server that simultaneously provides pages in multiple languages. By returning translations when objects are used rather than at the time of their creation, we allow the <abbr>SIS</abbr> library to provide the same instances of <code>Metadata</code> or <code>Coverage</code> (for example) for the same data, regardless of the client’s language. Translations may be made on the fly with the help of the application’s <code>ResourceBundle</code>, or may be provided directly with the data (as in the case of <code>Metadata</code>). </p> <p> An <code>Enumeration</code> corresponds to an <code>Enum</code> in Java. Both define all authorized values, without allowing the user to add any. A <code class="OGC">CodeList</code> is similar to an enumeration, except that users may add their own items. Standard <abbr>JDK</abbr> does not offer this possibility. GeoAPI defines an abstract <code class="API">CodeList</code> class that reproduces some of the functionality of <code>Enum</code> while being extensible. Extensions are made available by the <code class="API">valueOf(String)</code> static method, which, in contrast to <code>Enum</code>, creates new instances if the name provided does not correspond to the name of an existing instance. </p> <pre><code>MediumName cdRom = MediumName.<code class="API">CD_ROM;</code> MediumName usbKey = MediumName.<code class="API">valueOf</code>("<code class="API">USB_KEY</code>"); // There is no constraint on this value. assert MediumName.<code class="API">valueOf</code>("<code class="API">CD_ROM</code>") == cdRom : "valueOf must return existing constants."; assert MediumName.<code class="API">valueOf</code>("<code class="API">USB_KEY</code>") == usbKey : "valueOf must cache the previously requested values.";</code></pre> </section> </body> </html>