sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1683756 [2/6] - in /sis/branches/JDK7: ./ application/sis-console/src/test/java/org/apache/sis/console/ core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ core/sis-metadata/src/main/java/org/apache/sis/io/wkt/ core/sis-metad...
Date Fri, 05 Jun 2015 13:53:59 GMT
Modified: sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/Citations.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/Citations.java?rev=1683756&r1=1683755&r2=1683756&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/Citations.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/Citations.java [UTF-8] Fri Jun  5 13:53:58 2015
@@ -16,27 +16,57 @@
  */
 package org.apache.sis.metadata.iso.citation;
 
+import java.util.List;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.referencing.IdentifiedObject;        // For javadoc
 import org.apache.sis.util.Static;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.xml.IdentifierSpace;
 import org.apache.sis.internal.util.Constants;
+import org.apache.sis.internal.util.UnmodifiableArrayList;
 import org.apache.sis.internal.simple.SimpleCitation;
+import org.apache.sis.internal.simple.CitationConstant;
+import org.apache.sis.internal.jaxb.NonMarshalledAuthority;
+import org.apache.sis.internal.system.Modules;
+import org.apache.sis.internal.system.SystemListener;
 import org.apache.sis.metadata.iso.DefaultIdentifier;   // For javadoc
 
+import static org.apache.sis.internal.util.Citations.equalsFiltered;
+
 
 /**
  * A set of pre-defined constants and static methods working on {@linkplain Citation citations}.
- * The citation constants declared in this class are for:
+ * This class provides two kinds of {@code Citation} constants:
  *
  * <ul>
- *   <li><cite>Organizations</cite> (e.g. {@linkplain #OGC})</li>
- *   <li><cite>Specifications</cite> (e.g. {@linkplain #WMS})</li>
- *   <li><cite>Authorities</cite> that maintain definitions of codes (e.g. {@linkplain #EPSG})</li>
+ *   <li>Instances of {@link Citation} are references mostly for human reading.</li>
+ *   <li>Instances of {@link IdentifierSpace} provide the code spaces for identifiers
+ *       (most often {@linkplain org.apache.sis.referencing.crs.AbstractCRS Coordinate Reference System} identifiers)
+ *       together with information about who maintains those identifiers.</li>
  * </ul>
  *
- * In the later case, the citations are actually of kind {@link IdentifierSpace}.
+ * <div class="note"><b>Example:</b> {@code "EPSG:4326"} is a widely-used identifier
+ * for the <cite>“World Geodetic System (WGS) 1984”</cite> Coordinate Reference System (CRS).
+ * The {@code "4326"} part is the identifier {@linkplain DefaultIdentifier#getCode() code} and
+ * the {@code "EPSG"} part is the identifier {@linkplain DefaultIdentifier#getCodeSpace() code space}.
+ * The meaning of codes in that code space is controlled by an {@linkplain DefaultIdentifier#getAuthority() authority},
+ * the <cite>“EPSG Geodetic Parameter Dataset”</cite>. The {@linkplain DefaultCitation#getCitedResponsibleParties() cited
+ * responsible party} for the EPSG dataset is the <cite>“International Association of Oil &amp; Gas producers”</cite> (IOGP).
+ * </div>
+ *
+ * The constants defined in this class are typically values returned by:
+ * <ul>
+ *   <li>{@link DefaultCitation#getIdentifiers()} for the {@link #ISBN} and {@link #ISSN} constants.</li>
+ *   <li>{@link org.apache.sis.metadata.iso.ImmutableIdentifier#getAuthority()} for other {@code IdentifierSpace} constants.</li>
+ *   <li>{@link org.apache.sis.metadata.iso.DefaultMetadata#getMetadataStandards()} for other {@code Citation} constants.</li>
+ * </ul>
+ *
+ * The static methods defined in this class are for:
+ * <ul>
+ *   <li>Inferring an identifier from a citation (this is useful mostly with {@code IdentifierSpace} instances).</li>
+ *   <li>Determining if two instances can be considered the same {@code Citation} by comparing their titles or
+ *       their identifiers.</li>
+ * </ul>
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3
@@ -44,168 +74,368 @@ import org.apache.sis.metadata.iso.Defau
  * @module
  */
 public final class Citations extends Static {
-    /*
-     * NOTE: other constants are defined in org.apache.sis.internal.metadata.Standards.
-     */
-
     /**
      * The <a href="http://www.iso.org/">International Organization for Standardization</a>.
      *
-     * @category Organization
+     * @deprecated No replacement since ISO is an {@linkplain DefaultOrganisation organisation} rather than a citation.
      */
+    @Deprecated
     public static final Citation ISO = new SimpleCitation("ISO");
 
     /**
-     * The <a href="http://www.opengeospatial.org">Open Geospatial Consortium</a> organization.
-     * "Open Geospatial Consortium" is the new name for "OpenGIS consortium".
+     * The <cite>Geographic Information — Metadata</cite> standards defined by ISO 19115.
+     * This list contains two standards published by the
+     * <a href="http://www.iso.org/">International Organization for Standardization</a>:
+     *
+     * <ul>
+     *   <li>ISO 19115-1 Geographic Information — Metadata Part 1: Fundamentals</li>
+     *   <li>ISO 19115-2 Geographic Information — Metadata Part 2: Extensions for imagery and gridded data</li>
+     * </ul>
+     *
+     * Apache SIS always uses those standards together (actually the SIS's API is a merge of those two standards,
+     * providing for example a unified view of {@code MI_Band} and {@code MD_Band}). This is why those standards
+     * are defined in a collection rather than as separated constants.
+     *
+     * <div class="section">Content and future evolution</div>
+     * The content of this list may vary in future Apache SIS versions depending on the evolution of standards
+     * and in the way that SIS support them. The current content is:
+     *
+     * <ul>
+     *   <li>{@linkplain org.opengis.annotation.Specification#ISO_19115   ISO 19115-1:2014(E)} at index 0.</li>
+     *   <li>{@linkplain org.opengis.annotation.Specification#ISO_19115_2 ISO 19115-2:2009(E)} at index 1.</li>
+     * </ul>
      *
-     * @category Organization
+     * <div class="section">Main usage</div>
+     * This value can be returned by:
+     * <ul>
+     *   <li>{@link org.apache.sis.metadata.iso.DefaultMetadata#getMetadataStandards()}</li>
+     * </ul>
+     *
+     * @since 0.6
      */
-    public static final Citation OGC = new SimpleCitation(Constants.OGC);
+    public static final List<Citation> ISO_19115 = UnmodifiableArrayList.<Citation>wrap(new CitationConstant[] {
+        new CitationConstant("ISO 19115-1"),
+        new CitationConstant("ISO 19115-2")
+    });
 
     /**
      * The <a href="http://www.ogp.org.uk">International Association of Oil &amp; Gas Producers</a> organization.
      * This organization is responsible for maintainance of {@link #EPSG} database.
      *
-     * @see #EPSG
-     * @category Organization
-     *
      * @since 0.4
      *
      * @deprecated The OGP organization is now known as IOGP. This citation will be removed in SIS 0.7
      *             because of this name change and for avoiding confusion with {@link #EPSG} citation.
      */
     @Deprecated
-    public static final Citation OGP = new SimpleCitation("OGP"); // TODO: after removal, forName("OGP") should map to EPSG.
+    public static final Citation OGP = new SimpleCitation("OGP");
 
     /**
-     * The <a href="http://www.epsg.org">EPSG</a> dataset. This citation is used as an authority for
-     * {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem coordinate reference system}
-     * identifiers.
+     * The authority for identifiers of objects defined by the
+     * <a href="http://www.epsg.org">EPSG Geodetic Parameter Dataset</a>.
+     * EPSG is not an organization by itself, but is the <em>identifier space</em> managed by the
+     * <a href="http://www.iogp.org">International Association of Oil &amp; Gas producers</a> (IOGP) organization
+     * for {@linkplain org.apache.sis.referencing.crs.AbstractCRS Coordinate Reference System} identifiers.
+     * EPSG is the default namespace of map projection method and parameter names in Apache SIS.
      *
      * <div class="note"><b>Historical note:</b>
-     * The EPSG acronym meaning was <cite>European Petroleum Survey Group</cite>.
+     * The EPSG acronym meaning was <cite>“European Petroleum Survey Group”</cite>.
      * But this meaning does not apply anymore since the European and American associations merged into
-     * the <a href="http://www.iogp.org">International Association of Oil &amp; Gas producers</a> (IOGP).
+     * the <cite>“Association of Oil &amp; Gas producers”</cite> (OGP), later renamed as IOGP.
      * The legacy acronym now applies only to the database Coordinate Reference System definitions,
-     * known as <cite>EPSG dataset</cite>.</div>
+     * known as <cite>“EPSG Geodetic Parameter Dataset”</cite>.</div>
+     *
+     * The citation {@linkplain DefaultCitation#getCitedResponsibleParties() responsible party} is
+     * the IOGP organization, but the {@linkplain IdentifierSpace#getName() namespace} is {@code "EPSG"}.
+     *
+     * <div class="section">When to use "EPSG" and "IOGP"</div>
+     * For all usages except GML, the {@code "EPSG"} namespace shall be used for identifying
+     * {@linkplain org.apache.sis.referencing.crs.AbstractCRS Coordinate Reference System} objects.
+     * But in the particular case of GML, both {@code "EPSG"} and {@code "IOGP"} appear in different locations.
+     * For example:
+     *
+     * {@preformat xml
+     *   <gml:identifier codeSpace="IOGP">urn:ogc:def:crs:EPSG::4326</gml:identifier>
+     * }
+     *
+     * Guidelines:
+     * <ul>
+     *   <li>The {@code "EPSG"} name shall be used in URN. This part of the URN is called "the authority" and
+     *       is returned by both {@code Identifier.getAuthority()} and {@code Identifier.getCodeSpace()}.</li>
+     *   <li>The {@code "IOGP"} name appears in the GML {@code codeSpace} attribute, but despite the attribute name this
+     *       is <strong>not</strong> the {@code Identifier.getCodeSpace()} value of the {@code "EPSG:4326"} identifier.
+     *       Instead, Apache SIS considers {@code "IOGP"} as the codespace of the {@code "IOGP:EPSG"} identifier,
+     *       which is the {@linkplain DefaultCitation#getIdentifiers() identifier of this citation}.</li>
+     * </ul>
      *
-     * The citation {@linkplain DefaultCitation#getTitle() title} and contact information reference
-     * the IOGP organization, but the {@link IdentifierSpace#getName() namespace} is {@code "EPSG"}.
-     * Note that both the new "IOGP" and the legacy "OGP" abbreviations may be used as a code space
-     * in GML files.
-     *
-     * @see #AUTO
-     * @see #AUTO2
-     * @see #CRS
-     * @category Code space
+     * In other words, Apache SIS considers "IOGP" as the codespace of the "EPSG" codespace, but there is usually
+     * no need to go to such depth in identifier hierarchy except when handling GML documents. For this reason,
+     * the {@code "IOGP:EPSG"} identifier is handled in a special way by {@link #getIdentifier(Citation)},
+     * which return only {@code "EPSG"}.
+     *
+     * <div class="section">Main usage</div>
+     * This value can be returned by:
+     * <ul>
+     *   <li>{@link org.apache.sis.metadata.iso.ImmutableIdentifier#getAuthority()}</li>
+     * </ul>
      *
      * @since 0.4
      */
-    public static final IdentifierSpace<Integer> EPSG = new Authority<>(Constants.IOGP, Constants.EPSG);
+    public static final IdentifierSpace<Integer> EPSG = new CitationConstant.Authority<>(Constants.EPSG);
 
     /**
-     * The <a href="http://sis.apache.org">Apache SIS</a> project.
+     * The authority for identifiers found in specifications from the
+     * <a href="http://www.opengeospatial.org">Open Geospatial Consortium</a>.
+     * The {@linkplain IdentifierSpace#getName() name} of this identifier space is fixed to {@code "OGC"}.
+     * Apache SIS uses this authority mostly for map projection methods and parameters as they were defined in older
+     * OGC specifications (in more recent specifications, {@linkplain #EPSG} identifiers tend to be more widely used).
+     *
+     * <div class="note"><b>Example</b>
+     * the Mercator projection can be defined by an operation method having the {@code "OGC:Mercator_1SP"} identifier
+     * and the following parameters:
+     *
+     * <table class="sis">
+     * <caption>Example of identifiers in OGC name space</caption>
+     * <tr><th>Name in OGC namespace</th>           <th>Name in default namespace (EPSG)</th></tr>
+     * <tr><td>{@code "OGC:semi_major"}</td>        <td></td></tr>
+     * <tr><td>{@code "OGC:semi_minor"}</td>        <td></td></tr>
+     * <tr><td>{@code "OGC:latitude_of_origin"}</td><td>Latitude of natural origin</td></tr>
+     * <tr><td>{@code "OGC:central_meridian"}</td>  <td>Longitude of natural origin</td></tr>
+     * <tr><td>{@code "OGC:scale_factor"}</td>      <td>Scale factor at natural origin</td></tr>
+     * <tr><td>{@code "OGC:false_easting"}</td>     <td>False easting</td></tr>
+     * <tr><td>{@code "OGC:false_northing"}</td>    <td>False northing</td></tr>
+     * </table></div>
+     *
+     * <div class="section">Specifications referenced</div>
+     * The specification actually referenced by this citation is implementation dependent
+     * and may change in future SIS version. Some of the specifications used are:
      *
-     * @since 0.4
+     * <ul>
+     *   <li><a href="http://www.opengeospatial.org/standards/ct">Coordinate Transformation Service</a></li>
+     *   <li><a href="http://www.opengeospatial.org/standards/wms">Web Map Service</a></li>
+     *   <li>Definition identifier URNs in OGC namespace</li>
+     * </ul>
+     *
+     * We do not commit to a particular OGC specification in order to keep the flexibility to change the
+     * {@linkplain DefaultCitation#getTitle() title} or URL according newer OGC publications.
+     *
+     * <div class="section">Main usage</div>
+     * This value can be returned by:
+     * <ul>
+     *   <li>{@link org.apache.sis.metadata.iso.ImmutableIdentifier#getAuthority()}</li>
+     * </ul>
+     *
+     * @see #EPSG
+     * @see #ESRI
      */
-    public static final Citation SIS = new SimpleCitation(Constants.SIS);
+    public static final IdentifierSpace<String> OGC = new CitationConstant.Authority<>(Constants.OGC);
 
     /**
-     * The <a href="http://www.esri.com">ESRI</a> organization.
-     * This company defines many Coordinate Reference Systems in addition to the {@linkplain #EPSG} ones.
+     * The authority for identifiers of objects defined by <a href="http://www.esri.com">ESRI</a>.
+     * The {@linkplain IdentifierSpace#getName() name} of this identifier space is fixed to {@code "ESRI"}.
+     * This citation is used as the authority for many map projection method and parameter names
+     * other than the {@linkplain #EPSG} ones.
+     *
+     * <div class="note"><b>Note</b>
+     * many parameter names defined by {@linkplain #OGC} are very similar to the ESRI ones,
+     * except for the case. Examples:
+     *
+     * <table class="sis">
+     * <caption>Example of identifiers in ESRI name space</caption>
+     * <tr><th>Name in ESRI namespace</th>           <th>Name in OGC namespace</th></tr>
+     * <tr><td>{@code "ESRI:Semi_Major"}</td>        <td>{@code "OGC:semi_major"}</td></tr>
+     * <tr><td>{@code "ESRI:Semi_Minor"}</td>        <td>{@code "OGC:semi_minor"}</td></tr>
+     * <tr><td>{@code "ESRI:Latitude_Of_Origin"}</td><td>{@code "OGC:latitude_of_origin"}</td></tr>
+     * <tr><td>{@code "ESRI:Central_Meridian"}</td>  <td>{@code "OGC:central_meridian"}</td></tr>
+     * <tr><td>{@code "ESRI:Scale_Factor"}</td>      <td>{@code "OGC:scale_factor"}</td></tr>
+     * <tr><td>{@code "ESRI:False_Easting"}</td>     <td>{@code "OGC:false_easting"}</td></tr>
+     * <tr><td>{@code "ESRI:False_Northing"}</td>    <td>{@code "OGC:false_northing"}</td></tr>
+     * </table></div>
      *
-     * @category Organization
+     * <div class="section">Main usage</div>
+     * This value can be returned by:
+     * <ul>
+     *   <li>{@link org.apache.sis.metadata.iso.ImmutableIdentifier#getAuthority()}</li>
+     * </ul>
      *
      * @since 0.4
+     *
+     * @see #OGC
+     * @see #EPSG
      */
-    public static final Citation ESRI = new SimpleCitation("ESRI");
+    public static final IdentifierSpace<String> ESRI = new CitationConstant.Authority<>("ESRI");
 
     /**
      * The <a href="http://www.oracle.com">Oracle</a> organization.
      *
-     * @category Organization
+     * @deprecated No replacement since Oracle is an {@linkplain DefaultOrganisation organisation} rather
+     *             than a citation, and we do not have Oracle-specific objects.
      *
      * @since 0.4
      */
-    public static final Citation ORACLE = new SimpleCitation("Oracle");
+    @Deprecated
+    public static final Citation ORACLE = new CitationConstant("Oracle");
 
     /**
-     * The <a href="http://www.unidata.ucar.edu/software/netcdf-java">NetCDF</a> specification.
+     * The authority for identifiers of objects defined by the
+     * <a href="http://www.unidata.ucar.edu/software/netcdf-java">NetCDF</a> specification.
+     * The {@linkplain IdentifierSpace#getName() name} of this identifier space is fixed to {@code "NetCDF"}.
+     * This citation is used as the authority for some map projection method and parameter names
+     * as used in NetCDF files.
+     *
+     * <div class="note"><b>Example</b>
+     * the Mercator projection can be defined in a NetCDF file with the following parameters:
+     *
+     * <table class="sis">
+     * <caption>Example of identifiers in NetCDF name space</caption>
+     * <tr><th>Name in NetCDF namespace</th>                           <th>Name in default namespace (EPSG)</th></tr>
+     * <tr><td>{@code "NetCDF:semi_major_axis"}</td>                   <td></td></tr>
+     * <tr><td>{@code "NetCDF:semi_minor_axis"}</td>                   <td></td></tr>
+     * <tr><td>{@code "NetCDF:latitude_of_projection_origin"}</td>     <td>Latitude of natural origin</td></tr>
+     * <tr><td>{@code "NetCDF:longitude_of_projection_origin"}</td>    <td>Longitude of natural origin</td></tr>
+     * <tr><td>{@code "NetCDF:scale_factor_at_projection_origin"}</td> <td>Scale factor at natural origin</td></tr>
+     * <tr><td>{@code "NetCDF:false_easting"}</td>                     <td>False easting</td></tr>
+     * <tr><td>{@code "NetCDF:false_northing"}</td>                    <td>False northing</td></tr>
+     * </table></div>
      *
-     * @category Specification
+     * <div class="section">Main usage</div>
+     * This value can be returned by:
+     * <ul>
+     *   <li>{@link org.apache.sis.metadata.iso.ImmutableIdentifier#getAuthority()}</li>
+     * </ul>
      *
      * @since 0.4
      */
-    public static final Citation NETCDF = new SimpleCitation("NetCDF");
+    public static final IdentifierSpace<String> NETCDF = new CitationConstant.Authority<>("NetCDF");
 
     /**
-     * The <a href="http://www.remotesensing.org/geotiff/geotiff.html">GeoTIFF</a> specification.
+     * The authority for identifiers of objects defined by the
+     * the <a href="http://trac.osgeo.org/geotiff/">GeoTIFF</a> specification.
      * This specification identifies some map projections by their own numerical codes.
      *
-     * @category Code space
+     * <div class="section">Main usage</div>
+     * This value can be returned by:
+     * <ul>
+     *   <li>{@link org.apache.sis.metadata.iso.ImmutableIdentifier#getAuthority()}</li>
+     * </ul>
      *
      * @since 0.4
      */
-    public static final IdentifierSpace<Integer> GEOTIFF = new Authority<>("GeoTIFF", "GeoTIFF");
+    public static final IdentifierSpace<Integer> GEOTIFF = new CitationConstant.Authority<>("GeoTIFF");
 
     /**
-     * The <a href="http://trac.osgeo.org/proj/">Proj.4</a> project.
+     * The authority for identifiers of objects defined by the <a href="http://trac.osgeo.org/proj/">Proj.4</a> project.
      *
-     * @category Code space
+     * <div class="section">Main usage</div>
+     * This value can be returned by:
+     * <ul>
+     *   <li>{@link org.apache.sis.metadata.iso.ImmutableIdentifier#getAuthority()}</li>
+     * </ul>
      *
      * @since 0.4
      */
-    public static final IdentifierSpace<String> PROJ4 = new Authority<>("Proj.4", "Proj4");
+    public static final IdentifierSpace<String> PROJ4 = new CitationConstant.Authority<>("Proj4");
 
     /**
-     * The MapInfo software. This software defines its own projection codes.
+     * The authority for identifiers of objects defined by MapInfo.
      *
-     * @category Code space
+     * <div class="section">Main usage</div>
+     * This value can be returned by:
+     * <ul>
+     *   <li>{@link org.apache.sis.metadata.iso.ImmutableIdentifier#getAuthority()}</li>
+     * </ul>
      *
      * @since 0.6
      */
-    public static final IdentifierSpace<Integer> MAP_INFO = new Authority<>("MapInfo", "MapInfo");
+    public static final IdentifierSpace<Integer> MAP_INFO = new CitationConstant.Authority<>("MapInfo");
 
     /**
      * The <a href="http://www.iho.int/iho_pubs/standard/S-57Ed3.1/31Main.pdf">IHO transfer standard
      * for digital hydrographic data</a> specification.
      *
-     * @category Code space
+     * <div class="section">Main usage</div>
+     * This value can be returned by:
+     * <ul>
+     *   <li>{@link org.apache.sis.metadata.iso.ImmutableIdentifier#getAuthority()}</li>
+     * </ul>
      *
      * @since 0.6
      */
-    public static final IdentifierSpace<Integer> S57 = new Authority<>("S-57", "S57");
+    public static final IdentifierSpace<Integer> S57 = new CitationConstant.Authority<>("S57");
 
     /**
-     * <cite>International Standard Book Number</cite> (ISBN) defined by ISO-2108.
+     * The <cite>International Standard Book Number</cite> (ISBN) defined by ISO-2108.
      * The ISO-19115 metadata standard defines a specific attribute for this information,
      * but the SIS library handles it like any other identifier.
      *
-     * @see DefaultCitation#getISBN()
+     * <div class="section">Main usage</div>
+     * This value can be returned by:
+     * <ul>
+     *   <li>{@link DefaultCitation#getIdentifiers()}</li>
+     * </ul>
      *
-     * @category Code space
+     * @see DefaultCitation#getISBN()
      */
-    public static final IdentifierSpace<String> ISBN = DefaultCitation.ISBN;
+    public static final IdentifierSpace<String> ISBN = new NonMarshalledAuthority<>("ISBN", NonMarshalledAuthority.ISBN);
 
     /**
-     * <cite>International Standard Serial Number</cite> (ISSN) defined by ISO-3297.
+     * The <cite>International Standard Serial Number</cite> (ISSN) defined by ISO-3297.
      * The ISO-19115 metadata standard defines a specific attribute for this information,
      * but the SIS library handles it like any other identifier.
      *
+     * <div class="section">Main usage</div>
+     * This value can be returned by:
+     * <ul>
+     *   <li>{@link DefaultCitation#getIdentifiers()}</li>
+     * </ul>
+     *
      * @see DefaultCitation#getISSN()
+     */
+    public static final IdentifierSpace<String> ISSN = new NonMarshalledAuthority<>("ISSN", NonMarshalledAuthority.ISSN);
+
+    /**
+     * The codespace of objects that are specific to the <a href="http://sis.apache.org">Apache SIS</a> project.
+     *
+     * <div class="section">Main usage</div>
+     * This value can be returned by:
+     * <ul>
+     *   <li>{@link org.apache.sis.metadata.iso.quality.DefaultConformanceResult#getSpecification()}</li>
+     * </ul>
      *
-     * @category Code space
+     * @since 0.4
      */
-    public static final IdentifierSpace<String> ISSN = DefaultCitation.ISSN;
+    public static final Citation SIS = new CitationConstant(Constants.SIS);
 
     /**
      * List of citations declared in this class.
+     * Most frequently used citations (at least in SIS) should be first.
      */
-    private static final Citation[] CITATIONS = {
-        ISO, OGC, OGP, EPSG, SIS, ESRI, ORACLE, NETCDF, GEOTIFF, PROJ4, MAP_INFO, S57, ISBN, ISSN
+    private static final SimpleCitation[] CITATIONS = {
+        (SimpleCitation) EPSG,
+        (SimpleCitation) OGC,
+        (SimpleCitation) ESRI,
+        (SimpleCitation) NETCDF,
+        (SimpleCitation) GEOTIFF,
+        (SimpleCitation) PROJ4,
+        (SimpleCitation) MAP_INFO,
+        (SimpleCitation) S57,
+        (SimpleCitation) ISBN,
+        (SimpleCitation) ISSN,
+        (SimpleCitation) SIS,
+        (SimpleCitation) ISO_19115.get(0),
+        (SimpleCitation) ISO_19115.get(1),
+        (SimpleCitation) OGP,
+        (SimpleCitation) ISO,
+        (SimpleCitation) ORACLE
     };
 
+    static {  // Must be after CITATIONS array construction.
+        SystemListener.add(new SystemListener(Modules.METADATA) {
+            @Override protected void classpathChanged() {refresh();}
+            @Override protected void databaseChanged()  {refresh();}
+        });
+    }
+
     /**
      * Do not allows instantiation of this class.
      */
@@ -213,37 +443,51 @@ public final class Citations extends Sta
     }
 
     /**
-     * Returns a citation of the given name. The method makes the following choice:
+     * Invoked when the content of the citation constants (title, responsible party, URL, <i>etc.</i>)
+     * may have changed. This method notifies all citations that they will need to refresh their content.
+     */
+    static void refresh() {
+        for (final SimpleCitation citation : CITATIONS) {
+            if (citation instanceof CitationConstant) {
+                ((CitationConstant) citation).refresh();
+            }
+        }
+    }
+
+    /**
+     * Returns a citation of the given identifier. The method makes the following choice:
      *
      * <ul>
      *   <li>If the given title is {@code null} or empty (ignoring spaces), then this method returns {@code null}.</li>
-     *   <li>Otherwise if the given name matches a {@linkplain DefaultCitation#getTitle() title} or an
-     *       {@linkplain DefaultCitation#getAlternateTitles() alternate titles} of one of the pre-defined
-     *       constants ({@link #EPSG}, {@link #GEOTIFF}, <i>etc.</i>), then that constant is returned.</li>
+     *   <li>Otherwise if the given string matches an {@linkplain DefaultCitation#getIdentifiers() identifier} of one of
+     *       the pre-defined constants ({@link #EPSG}, {@link #GEOTIFF}, <i>etc.</i>), then that constant is returned.</li>
      *   <li>Otherwise, a new citation is created with the specified name as the title.</li>
      * </ul>
      *
-     * @param  title The citation title (or alternate title), or {@code null}.
+     * @param  identifier The citation title (or alternate title), or {@code null}.
      * @return A citation using the specified name, or {@code null} if the given title is null or empty.
      */
-    public static Citation fromName(String title) {
-        if (title == null || ((title = CharSequences.trimWhitespaces(title)).isEmpty())) {
+    public static Citation fromName(String identifier) {
+        if (identifier == null || ((identifier = CharSequences.trimWhitespaces(identifier)).isEmpty())) {
             return null;
         }
-        /*
-         * We perform a special check because it is our only IdentifierSpace having an namespace ("EPSG")
-         * that can not be inferred from the authority abbreviation ("IOGP"). We test this special case
-         * first because it is usually to be the most frequently used citation.
-         */
-        if (title.equalsIgnoreCase(Constants.EPSG)) {
-            return EPSG;
-        }
-        for (final Citation citation : CITATIONS) {
-            if (titleMatches(citation, title)) {
+        for (final SimpleCitation citation : CITATIONS) {
+            if (equalsFiltered(identifier, citation.title)) {
                 return citation;
             }
         }
-        return new SimpleCitation(title);
+        /*
+         * Temporary check to be removed after we deleted the deprecated citation.
+         */
+        if (equalsFiltered(identifier, Constants.IOGP)) {
+            return OGP;
+        }
+        /*
+         * If we found no match, org.apache.sis.internal.metadata.ServicesForUtility expects the default citation
+         * to be of this exact class: SimpleCitation (not a subclass). If the type of citation created below is
+         * modified, then we need to review ServicesForUtility.getCitationConstant(String) method body.
+         */
+        return new SimpleCitation(identifier);
     }
 
     /**
@@ -305,8 +549,10 @@ public final class Citations extends Sta
      *
      * <p>If (and <em>only</em> if) the citation does not contain any identifier, then this method
      * fallback on titles comparison using the {@link #titleMatches(Citation,String) titleMatches}
-     * method. This fallback exists for compatibility with client codes using citation
-     * {@linkplain DefaultCitation#getTitle() title} without identifiers.</p>
+     * method. This fallback exists for compatibility with citations using
+     * {@linkplain DefaultCitation#getTitle() title} and
+     * {@linkplain DefaultCitation#getAlternateTitles() alternate titles} (often abbreviations)
+     * without identifiers.</p>
      *
      * @param  citation The citation to check for, or {@code null}.
      * @param  identifier The identifier to compare, or {@code null}.
@@ -318,31 +564,40 @@ public final class Citations extends Sta
 
     /**
      * Infers an identifier from the given citation, or returns {@code null} if no identifier has been found.
-     * This method is useful for extracting the namespace from an authority (e.g. {@code "EPSG"})
+     * This method is useful for extracting a short designation of an authority (e.g. {@code "EPSG"})
      * for display purpose. This method performs the following choices:
      *
      * <ul>
      *   <li>If the given citation is {@code null}, then this method returns {@code null}.</li>
-     *   <li>Otherwise if the citation contains at least one {@linkplain DefaultCitation#getIdentifiers() identifier}, then:
+     *   <li>Otherwise if the collection of {@linkplain DefaultCitation#getIdentifiers() citation identifiers}
+     *       contains at least one non-{@linkplain org.apache.sis.util.Deprecable#isDeprecated() deprecated}
+     *       identifier, then:
      *     <ul>
-     *       <li>If at least one identifier is a {@linkplain org.apache.sis.util.CharSequences#isUnicodeIdentifier
-     *           unicode identifier}, then the shortest of those identifiers is returned.</li>
-     *       <li>Otherwise the shortest identifier is returned, despite not being a Unicode identifier.</li>
-     *     </ul></li>
-     *   <li>Otherwise if the citation contains at least one {@linkplain DefaultCitation#getTitle() title} or
-     *       {@linkplain DefaultCitation#getAlternateTitles() alternate title}, then:
+     *       <li>If the code and codespace of at least one non-deprecated identifier are
+     *           {@linkplain org.apache.sis.util.CharSequences#isUnicodeIdentifier unicode identifiers}, then
+     *           the <strong>first</strong> of those identifiers is returned in a {@code "[codespace:]code"} format.
+     *           Only the first character of the resulting string needs to be an
+     *           {@linkplain Character#isUnicodeIdentifierStart(int) identifier start character}.</li>
+     *       <li>Otherwise the first non-empty and non-deprecated identifier is returned in a
+     *           {@code "[codespace:]code"} format, despite not being a valid Unicode identifier.</li>
+     *     </ul>
+     *   </li>
+     *   <li>Otherwise if the citation contains at least one non-deprecated {@linkplain DefaultCitation#getTitle() title}
+     *       or {@linkplain DefaultCitation#getAlternateTitles() alternate title}, then:
      *     <ul>
-     *       <li>If at least one title is a {@linkplain org.apache.sis.util.CharSequences#isUnicodeIdentifier
-     *           unicode identifier}, then the shortest of those titles is returned.</li>
-     *       <li>Otherwise the shortest title is returned, despite not being a Unicode identifier.</li>
-     *     </ul></li>
+     *       <li>If at least one non-deprecated title is a {@linkplain org.apache.sis.util.CharSequences#isUnicodeIdentifier
+     *           unicode identifier}, then the <strong>first</strong> of those titles is returned.</li>
+     *       <li>Otherwise the first non-empty and non-deprecated title is returned,
+     *           despite not being a valid Unicode identifier.</li>
+     *     </ul>
+     *   </li>
      *   <li>Otherwise this method returns {@code null}.</li>
      * </ul>
      *
      * <div class="note"><b>Note:</b>
      * This method searches in alternate titles as a fallback because ISO specification said
      * that those titles are often used for abbreviations. However titles are never searched
-     * if the given citation contains at least one identifier.</div>
+     * if the given citation contains at least one non-empty and non-deprecated identifier.</div>
      *
      * This method ignores leading and trailing {@linkplain Character#isWhitespace(int) whitespaces}
      * in every character sequences. Null or empty trimmed character sequences are ignored.
@@ -361,11 +616,13 @@ public final class Citations extends Sta
 
     /**
      * Infers a valid Unicode identifier from the given citation, or returns {@code null} if none.
-     * This method is useful for extracting the namespace from an authority (e.g. {@code "EPSG"})
+     * This method is useful for extracting a short designation of an authority (e.g. {@code "EPSG"})
      * for processing purpose. This method performs the following actions:
      *
      * <ul>
-     *   <li>First, invoke {@link #getIdentifier(Citation)}.</li>
+     *   <li>First, performs the same work than {@link #getIdentifier(Citation)} except that {@code '_'}
+     *       is used instead of {@link org.apache.sis.util.iso.DefaultNameSpace#DEFAULT_SEPARATOR ':'}
+     *       as the separator between the codespace and the code.</li>
      *   <li>If the result of above method call is {@code null} or is not a
      *       {@linkplain org.apache.sis.util.CharSequences#isUnicodeIdentifier valid Unicode identifier},
      *       then return {@code null}.</li>
@@ -378,8 +635,17 @@ public final class Citations extends Sta
      * Those characters are illegal in XML identifiers, and should therfore be removed if the Unicode identifier
      * may also be used as XML identifier.</div>
      *
-     * If non-null, the result is suitable for use as a XML identifier except for a few uncommon characters
-     * ({@code µ}, {@code ª} (feminine ordinal indicator), {@code º} (masculine ordinal indicator) and {@code ⁔}).
+     * If non-null, the result is suitable for use as a XML identifier except for a few uncommon characters.
+     *
+     * <div class="note"><b>Note:</b>
+     * the following characters are invalid in XML identifiers. However since they are valid in Unicode identifiers,
+     * they could be included in the string returned by this method:
+     * <ul>
+     *   <li>{@code µ}</li>
+     *   <li>{@code ª} (feminine ordinal indicator)</li>
+     *   <li>{@code º} (masculine ordinal indicator)</li>
+     *   <li>{@code ⁔}</li>
+     * </ul></div>
      *
      * @param  citation The citation for which to get the Unicode identifier, or {@code null}.
      * @return A non-empty Unicode identifier for the given citation without leading or trailing whitespaces,

Modified: sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultCitation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultCitation.java?rev=1683756&r1=1683755&r2=1683756&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultCitation.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultCitation.java [UTF-8] Fri Jun  5 13:53:58 2015
@@ -91,26 +91,6 @@ public class DefaultCitation extends ISO
     private static final long serialVersionUID = -7343644724857519090L;
 
     /**
-     * The authority for International Standard Book Number.
-     *
-     * <div class="note"><b>Implementation note:</b> This field is read by reflection in
-     * {@link org.apache.sis.internal.jaxb.NonMarshalledAuthority#getCitation(String)}.
-     * If this field is renamed or moved, then {@code NonMarshalledAuthority} needs
-     * to be updated.</div>
-     */
-    static final IdentifierSpace<String> ISBN = new NonMarshalledAuthority<>("ISBN", NonMarshalledAuthority.ISBN);
-
-    /**
-     * The authority for International Standard Serial Number.
-     *
-     * <div class="note"><b>Implementation note:</b> This field is read by reflection in
-     * {@link org.apache.sis.internal.jaxb.NonMarshalledAuthority#getCitation(String)}.
-     * If this field is renamed or moved, then {@code NonMarshalledAuthority} needs
-     * to be updated.</div>
-     */
-    static final IdentifierSpace<String> ISSN = new NonMarshalledAuthority<>("ISSN", NonMarshalledAuthority.ISSN);
-
-    /**
      * Name by which the cited resource is known.
      */
     private InternationalString title;
@@ -256,8 +236,8 @@ public class DefaultCitation extends ISO
             final String id2        = object.getISSN();
             if (id1 != null || id2 != null) {
                 final IdentifierMap map = super.getIdentifierMap();
-                if (id1 != null) map.putSpecialized(ISBN, id1);
-                if (id2 != null) map.putSpecialized(ISSN, id2);
+                if (id1 != null) map.putSpecialized(Citations.ISBN, id1);
+                if (id2 != null) map.putSpecialized(Citations.ISSN, id2);
             }
         }
     }
@@ -568,7 +548,7 @@ public class DefaultCitation extends ISO
     @Override
     @XmlElement(name = "ISBN")
     public String getISBN() {
-        return isNullOrEmpty(identifiers) ? null : getIdentifierMap().get(ISBN);
+        return isNullOrEmpty(identifiers) ? null : getIdentifierMap().get(Citations.ISBN);
     }
 
     /**
@@ -587,7 +567,7 @@ public class DefaultCitation extends ISO
     public void setISBN(final String newValue) {
         checkWritePermission();
         if (newValue != null || !isNullOrEmpty(identifiers)) {
-            getIdentifierMap().putSpecialized(ISBN, newValue);
+            getIdentifierMap().putSpecialized(Citations.ISBN, newValue);
         }
     }
 
@@ -607,7 +587,7 @@ public class DefaultCitation extends ISO
     @Override
     @XmlElement(name = "ISSN")
     public String getISSN() {
-        return isNullOrEmpty(identifiers) ? null : getIdentifierMap().get(ISSN);
+        return isNullOrEmpty(identifiers) ? null : getIdentifierMap().get(Citations.ISSN);
     }
 
     /**
@@ -626,7 +606,7 @@ public class DefaultCitation extends ISO
     public void setISSN(final String newValue) {
         checkWritePermission();
         if (newValue != null || !isNullOrEmpty(identifiers)) {
-            getIdentifierMap().putSpecialized(ISSN, newValue);
+            getIdentifierMap().putSpecialized(Citations.ISSN, newValue);
         }
     }
 

Modified: sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataStandardTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataStandardTest.java?rev=1683756&r1=1683755&r2=1683756&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataStandardTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataStandardTest.java [UTF-8] Fri Jun  5 13:53:58 2015
@@ -172,13 +172,13 @@ public final strictfp class MetadataStan
 
         // Self equality test
         DefaultCitation instance = HardCodedCitations.EPSG;
-        assertFalse(std.equals(instance, HardCodedCitations.GEOTIFF, ComparisonMode.STRICT));
-        assertTrue (std.equals(instance, HardCodedCitations.EPSG,    ComparisonMode.STRICT));
+        assertFalse(std.equals(instance, HardCodedCitations.SIS,  ComparisonMode.STRICT));
+        assertTrue (std.equals(instance, HardCodedCitations.EPSG, ComparisonMode.STRICT));
 
         // Test comparison with a copy
         instance = new DefaultCitation(HardCodedCitations.EPSG);
-        assertFalse(std.equals(instance, HardCodedCitations.GEOTIFF, ComparisonMode.STRICT));
-        assertTrue (std.equals(instance, HardCodedCitations.EPSG,    ComparisonMode.STRICT));
+        assertFalse(std.equals(instance, HardCodedCitations.SIS,  ComparisonMode.STRICT));
+        assertTrue (std.equals(instance, HardCodedCitations.EPSG, ComparisonMode.STRICT));
 
         // test comparison with a modified copy
         instance.setTitle(new SimpleInternationalString("A dummy title"));
@@ -227,7 +227,7 @@ public final strictfp class MetadataStan
         final Map<String,Object> map = MetadataStandard.ISO_19115.asValueMap(instance,
                 KeyNamePolicy.JAVABEANS_PROPERTY, ValueExistencePolicy.NON_EMPTY);
         assertFalse("The properties map shall not be empty.", map.isEmpty());
-        assertEquals("Unexpected number of properties.", 5, map.size());
+        assertEquals("Unexpected number of properties.", 4, map.size());
         /*
          * Verify the set of keys in the ValueMap.
          *
@@ -236,7 +236,7 @@ public final strictfp class MetadataStan
          * PropertyAccessorTest.testConstructor().
          */
         final Set<String> keys = map.keySet();
-        assertEquals("[title, alternateTitles, identifiers, citedResponsibleParties, presentationForms]", keys.toString());
+        assertEquals("[title, identifiers, citedResponsibleParties, presentationForms]", keys.toString());
         assertTrue  ("Shall exist and be defined.",   keys.contains("title"));
         assertTrue  ("Shall exist and be defined.",   keys.contains("getTitle"));
         assertTrue  ("Shall exist and be defined.",   keys.contains("identifier"));
@@ -249,8 +249,8 @@ public final strictfp class MetadataStan
         /*
          * Verifies values.
          */
-        assertEquals("title", "European Petroleum Survey Group", map.get("title").toString());
-        assertEquals("title", "European Petroleum Survey Group", map.get("getTitle").toString());
+        assertEquals("title", "EPSG Geodetic Parameter Dataset", map.get("title").toString());
+        assertEquals("title", "EPSG Geodetic Parameter Dataset", map.get("getTitle").toString());
         final Object identifiers = map.get("identifiers");
         assertInstanceOf("identifiers", Collection.class, identifiers);
         assertContainsIdentifierCode("EPSG", (Collection<?>) identifiers);

Modified: sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyAccessorTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyAccessorTest.java?rev=1683756&r1=1683755&r2=1683756&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyAccessorTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyAccessorTest.java [UTF-8] Fri Jun  5 13:53:58 2015
@@ -238,7 +238,7 @@ public final strictfp class PropertyAcce
     @DependsOnMethod("testConstructorWithInheritance")
     public void testConstructorWithCovariantReturnType() {
         final Class<?> type = GeographicCRS.class;
-        assertMappingEquals(new PropertyAccessor(HardCodedCitations.ISO, type, type),
+        assertMappingEquals(new PropertyAccessor(HardCodedCitations.ISO_19111, type, type),
         //……Declaring type……………………………Method……………………………………………JavaBeans……………………………UML identifier………………Sentence…………………………………Type…………………………………………………………
             GeographicCRS.class,    "getCoordinateSystem", "coordinateSystem", "coordinateSystem", "Coordinate system",  EllipsoidalCS.class,       // Covariant return type
             GeodeticCRS.class,      "getDatum",            "datum",            "datum",            "Datum",              GeodeticDatum.class,       // Covariant return type
@@ -269,32 +269,33 @@ public final strictfp class PropertyAcce
      * {@preformat text
      *   DefaultCitation
      *     ├─Title…………………………………… International Organization for Standardization
-     *     ├─Alternate title………… ISO
+     *     ├─Alternate title………… ISO 19111
      *     ├─Identifier
-     *     │   └─Code…………………………… ISO
+     *     │   ├─Code…………………………… 19111
+     *     │   └─Code space…………… ISO
      *     └─Presentation form…… Document digital
      * }
      */
     @Test
     @DependsOnMethod("testConstructor")
     public void testGet() {
-        final DefaultCitation  instance = HardCodedCitations.ISO;
+        final DefaultCitation  instance = HardCodedCitations.ISO_19111;
         final PropertyAccessor accessor = createPropertyAccessor();
 
         // Singleton value (not a collection)
         final Object title = accessor.get(accessor.indexOf("title", true), instance);
         assertInstanceOf("title", InternationalString.class, title);
-        assertEquals("title", "International Organization for Standardization", title.toString());
+        assertEquals("title", "Spatial referencing by coordinates", title.toString());
 
         // Collection of InternationalStrings
         final Object alternateTitles = accessor.get(accessor.indexOf("alternateTitles", true), instance);
         assertInstanceOf("alternateTitles", Collection.class, alternateTitles);
-        assertEquals("alternateTitles", "ISO", getSingleton((Collection<?>) alternateTitles).toString());
+        assertEquals("alternateTitles", "ISO 19111", getSingleton((Collection<?>) alternateTitles).toString());
 
         // Collection of Identifiers
         final Object identifiers = accessor.get(accessor.indexOf("identifiers", true), instance);
         assertInstanceOf("identifiers", Collection.class, identifiers);
-        assertContainsIdentifierCode("ISO", (Collection<?>) identifiers);
+        assertContainsIdentifierCode("19111", (Collection<?>) identifiers);
     }
 
     /**
@@ -592,13 +593,13 @@ public final strictfp class PropertyAcce
     public void testEquals() {
         DefaultCitation citation = HardCodedCitations.EPSG;
         final PropertyAccessor accessor = createPropertyAccessor();
-        assertFalse(accessor.equals(citation, HardCodedCitations.GEOTIFF, ComparisonMode.STRICT));
-        assertTrue (accessor.equals(citation, HardCodedCitations.EPSG,    ComparisonMode.STRICT));
+        assertFalse(accessor.equals(citation, HardCodedCitations.SIS,  ComparisonMode.STRICT));
+        assertTrue (accessor.equals(citation, HardCodedCitations.EPSG, ComparisonMode.STRICT));
 
         // Same test than above, but on a copy of the EPSG constant.
         citation = new DefaultCitation(HardCodedCitations.EPSG);
-        assertFalse(accessor.equals(citation, HardCodedCitations.GEOTIFF, ComparisonMode.STRICT));
-        assertTrue (accessor.equals(citation, HardCodedCitations.EPSG,    ComparisonMode.STRICT));
+        assertFalse(accessor.equals(citation, HardCodedCitations.SIS,  ComparisonMode.STRICT));
+        assertTrue (accessor.equals(citation, HardCodedCitations.EPSG, ComparisonMode.STRICT));
 
         // Identifiers shall be stored in different collection instances with equal content.
         final int    index  = accessor.indexOf("identifiers", true);

Modified: sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/PrunerTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/PrunerTest.java?rev=1683756&r1=1683755&r2=1683756&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/PrunerTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/PrunerTest.java [UTF-8] Fri Jun  5 13:53:58 2015
@@ -114,7 +114,7 @@ public final strictfp class PrunerTest e
         /*
          * Set a non-empty metadata info.
          */
-        metadata.setMetadataIdentifier(new SimpleIdentifier(null, "A file identifiers"));
+        metadata.setMetadataIdentifier(new SimpleIdentifier(null, "A file identifiers", false));
         assertTrue ("GeographicBoundingBox", bbox.isEmpty());
         assertTrue ("Extent",                extent.isEmpty());
         assertTrue ("Scale",                 scale.isEmpty());
@@ -142,7 +142,7 @@ public final strictfp class PrunerTest e
          * Set an empty string in an element.
          */
         scale.setScale(Double.NaN);
-        metadata.setMetadataIdentifier(new SimpleIdentifier(null, "   "));
+        metadata.setMetadataIdentifier(new SimpleIdentifier(null, "   ", false));
         assertTrue("Scale",                 scale.isEmpty());
         assertTrue("DataIdentification",    identification.isEmpty());
         assertTrue("Metadata",              metadata.isEmpty());
@@ -176,7 +176,7 @@ public final strictfp class PrunerTest e
     @Test
     @DependsOnMethod("testIsEmpty")
     public void testPrune() {
-        metadata.setMetadataIdentifier(new SimpleIdentifier(null, "A file identifiers"));
+        metadata.setMetadataIdentifier(new SimpleIdentifier(null, "A file identifiers", false));
         identification.setCitation(new DefaultCitation("A citation title"));
         assertFalse(isNullOrEmpty(metadata.getMetadataIdentifier()));
         assertFalse(isNullOrEmpty(identification.getCitation()));
@@ -193,7 +193,7 @@ public final strictfp class PrunerTest e
         assertEquals(0, extent.getGeographicElements().size());
         assertFalse(metadata.isEmpty());
 
-        metadata.setMetadataIdentifier(new SimpleIdentifier(null, " "));
+        metadata.setMetadataIdentifier(new SimpleIdentifier(null, " ", false));
         identification.setCitation(new DefaultCitation(" "));
         assertNotNull(metadata.getMetadataIdentifier());
         metadata.prune();

Modified: sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableFormatTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableFormatTest.java?rev=1683756&r1=1683755&r2=1683756&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableFormatTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/TreeTableFormatTest.java [UTF-8] Fri Jun  5 13:53:58 2015
@@ -110,7 +110,8 @@ public final strictfp class TreeTableFor
             "  ├─Identifier\n" +
             "  │   ├─Code……………………………………………………………… 9782505004509\n" +
             "  │   ├─Authority\n" +
-            "  │   │   └─Title………………………………………………… ISBN\n" +
+            "  │   │   ├─Title………………………………………………… International Standard Book Number\n" +
+            "  │   │   └─Alternate title……………………… ISBN\n" +
             "  │   └─Code space……………………………………………… ISBN\n"+
             "  ├─Cited responsible party (1 of 2)\n" +
             "  │   ├─Party\n" +

Modified: sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/ImmutableIdentifierTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/ImmutableIdentifierTest.java?rev=1683756&r1=1683755&r2=1683756&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/ImmutableIdentifierTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/ImmutableIdentifierTest.java [UTF-8] Fri Jun  5 13:53:58 2015
@@ -22,8 +22,8 @@ import java.util.Locale;
 import javax.xml.bind.JAXBException;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.metadata.iso.citation.DefaultCitation;
-import org.apache.sis.metadata.iso.citation.HardCodedCitations;
 import org.apache.sis.util.iso.SimpleInternationalString;
+import org.apache.sis.internal.simple.SimpleCitation;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.io.wkt.Convention;
 import org.apache.sis.test.DependsOnMethod;
@@ -179,7 +179,14 @@ public final strictfp class ImmutableIde
      */
     @Test
     public void testWKT() {
-        final ImmutableIdentifier id = new ImmutableIdentifier(HardCodedCitations.IOGP, "EPSG", "4326", "8.2", null);
+        ImmutableIdentifier id = new ImmutableIdentifier(Citations.EPSG, "EPSG", "4326", "8.2", null);
+        assertWktEquals(Convention.WKT2, "Id[“EPSG”, 4326, “8.2”]", id);
+        assertWktEquals(Convention.WKT1, "AUTHORITY[“EPSG”, “4326”]", id);
+        /*
+         * Same identifier, but with an authority different than the EPSG one.
+         * The Citation element should then be visible in WKT 2.
+         */
+        id = new ImmutableIdentifier(new SimpleCitation("IOGP"), "EPSG", "4326", "8.2", null);
         assertWktEquals(Convention.WKT2, "Id[“EPSG”, 4326, “8.2”, Citation[“IOGP”]]", id);
         assertWktEquals(Convention.WKT1, "AUTHORITY[“EPSG”, “4326”]", id);
     }

Modified: sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/CitationsTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/CitationsTest.java?rev=1683756&r1=1683755&r2=1683756&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/CitationsTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/CitationsTest.java [UTF-8] Fri Jun  5 13:53:58 2015
@@ -16,12 +16,19 @@
  */
 package org.apache.sis.metadata.iso.citation;
 
+import java.util.Locale;
+import java.lang.reflect.Field;
+import org.opengis.metadata.Identifier;
+import org.opengis.metadata.citation.Citation;
+import org.apache.sis.internal.simple.CitationConstant;
 import org.apache.sis.internal.util.Constants;
+import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
 import static org.apache.sis.metadata.iso.citation.Citations.*;
-import static org.junit.Assert.assertSame;
+import static org.apache.sis.test.TestUtilities.getSingleton;
+import static org.apache.sis.test.Assert.*;
 
 
 /**
@@ -35,24 +42,182 @@ import static org.junit.Assert.assertSam
 public final strictfp class CitationsTest extends TestCase {
     /**
      * Tests {@link Citations#fromName(String)}.
+     *
+     * @throws IllegalAccessException should never happen since we asked only for public fields.
      */
     @Test
-    public void testFromName() {
-        assertSame(ISO,      fromName("ISO"));
-        assertSame(OGC,      fromName(Constants.OGC));
-        assertSame(EPSG,     fromName(Constants.EPSG));  // This one is important.
-        assertSame(EPSG,     fromName(Constants.IOGP));  // This one is not really needed (and maybe not strictly correct).
-        assertSame(SIS,      fromName(Constants.SIS));
-        assertSame(ESRI,     fromName("ESRI"));
-        assertSame(ORACLE,   fromName("Oracle"));
-        assertSame(NETCDF,   fromName("NetCDF"));
-        assertSame(GEOTIFF,  fromName("GeoTIFF"));
-        assertSame(PROJ4,    fromName("Proj.4"));
-        assertSame(PROJ4,    fromName("Proj4"));
-        assertSame(MAP_INFO, fromName("MapInfo"));
-        assertSame(S57,      fromName("S-57"));
-        assertSame(S57,      fromName("S57"));
-        assertSame(ISBN,     fromName("ISBN"));
-        assertSame(ISSN,     fromName("ISSN"));
+    public void testFromName() throws IllegalAccessException {
+        assertSame(SIS,              fromName(Constants.SIS));
+        assertSame(OGC,              fromName(Constants.OGC));   // Success of this test is important for remaining of SIS.
+        assertSame(EPSG,             fromName(Constants.EPSG));  // Success of this test is important for remaining of SIS.
+        assertSame(OGP,              fromName(Constants.IOGP));  // TODO: return EPSG after we removed deprecated constant.
+        assertSame(OGP,              fromName("OGP"));           // TODO: return EPSG after we removed deprecated constant.
+        assertSame(ESRI,             fromName("ESRI"));          // Handled in a way very similar to "OGC".
+        assertSame(ORACLE,           fromName("Oracle"));
+        assertSame(NETCDF,           fromName("NetCDF"));
+        assertSame(GEOTIFF,          fromName("GeoTIFF"));
+        assertSame(PROJ4,            fromName("Proj.4"));
+        assertSame(PROJ4,            fromName("Proj4"));
+        assertSame(MAP_INFO,         fromName("MapInfo"));
+        assertSame(S57,              fromName("S-57"));
+        assertSame(S57,              fromName("S57"));
+        assertSame(ISBN,             fromName("ISBN"));
+        assertSame(ISSN,             fromName("ISSN"));
+        assertSame(ISO,              fromName("ISO"));
+        assertSame(ISO_19115.get(0), fromName("ISO 19115-1"));
+        assertSame(ISO_19115.get(1), fromName("ISO 19115-2"));
+        /*
+         * Verify again, but using reflection for making sure that the field names
+         * are consistent and that we did not forgot any citation constant.
+         */
+        for (final Field field : Citations.class.getFields()) {
+            if (Citation.class.isAssignableFrom(field.getType())) {
+                final String name = field.getName();
+                assertSame(name, field.get(null), Citations.fromName(name));
+            }
+        }
+    }
+
+    /**
+     * Tests {@link Citations#getIdentifier(Citation)} on the constants declared in the {@link Citations} class.
+     * The values do not need to be valid Unicode identifiers.
+     */
+    @Test
+    public void testGetIdentifier() {
+        assertEquals("SIS",         getIdentifier(SIS));
+        assertEquals("OGC",         getIdentifier(OGC));
+        assertEquals("EPSG",        getIdentifier(EPSG));
+        assertEquals("OGP",         getIdentifier(OGP));
+        assertEquals("ESRI",        getIdentifier(ESRI));
+        assertEquals("Oracle",      getIdentifier(ORACLE));
+        assertEquals("NetCDF",      getIdentifier(NETCDF));
+        assertEquals("GeoTIFF",     getIdentifier(GEOTIFF));
+        assertEquals("MapInfo",     getIdentifier(MAP_INFO));
+        assertEquals("ISBN",        getIdentifier(ISBN));
+        assertEquals("ISSN",        getIdentifier(ISSN));
+        assertEquals("Proj.4",      getIdentifier(PROJ4));  // Not a valid Unicode identifier.
+        assertEquals("S-57",        getIdentifier(S57));    // Not a valid Unicode identifier.
+        assertEquals("ISO",         getIdentifier(ISO));
+        assertEquals("ISO:19115-1", getIdentifier(ISO_19115.get(0)));  // The ':' separator is not usual in ISO references
+        assertEquals("ISO:19115-2", getIdentifier(ISO_19115.get(1)));  // and could be changed in future SIS versions.
+    }
+
+    /**
+     * Tests {@link Citations#getUnicodeIdentifier(Citation)} on the constants declared in the {@link Citations} class.
+     * All values shall be valid Unicode identifiers or {@code null}.
+     */
+    @Test
+    @DependsOnMethod("testGetIdentifier")
+    public void testGetUnicodeIdentifier() {
+        assertEquals("SIS",         getUnicodeIdentifier(SIS));
+        assertEquals("OGC",         getUnicodeIdentifier(OGC));
+        assertEquals("EPSG",        getUnicodeIdentifier(EPSG));
+        assertEquals("OGP",         getUnicodeIdentifier(OGP));
+        assertEquals("ESRI",        getUnicodeIdentifier(ESRI));
+        assertEquals("Oracle",      getUnicodeIdentifier(ORACLE));
+        assertEquals("NetCDF",      getUnicodeIdentifier(NETCDF));
+        assertEquals("GeoTIFF",     getUnicodeIdentifier(GEOTIFF));
+        assertEquals("MapInfo",     getUnicodeIdentifier(MAP_INFO));
+        assertEquals("ISBN",        getUnicodeIdentifier(ISBN));
+        assertEquals("ISSN",        getUnicodeIdentifier(ISSN));
+        assertNull  ("Proj4",       getUnicodeIdentifier(PROJ4));      // Not yet publicly declared as an identifier.
+        assertNull  ("S57",         getUnicodeIdentifier(S57));        // Not yet publicly declared as an identifier.
+        assertEquals("ISO",         getUnicodeIdentifier(ISO));
+        assertNull  ("ISO_19115-1", getUnicodeIdentifier(ISO_19115.get(0)));  // Not a valid Unicode identifier.
+        assertNull  ("ISO_19115-2", getUnicodeIdentifier(ISO_19115.get(1)));
+    }
+
+    /**
+     * Tests {@link org.apache.sis.internal.util.Citations#getCodeSpace(Citation)} on the constants
+     * declared in the {@link Citations} class.
+     */
+    @Test
+    @DependsOnMethod("testGetUnicodeIdentifier")
+    public void testGetCodeSpace() {
+        assertEquals("SIS",         org.apache.sis.internal.util.Citations.getCodeSpace(SIS));
+        assertEquals("OGC",         org.apache.sis.internal.util.Citations.getCodeSpace(OGC));
+        assertEquals("EPSG",        org.apache.sis.internal.util.Citations.getCodeSpace(EPSG));
+        assertEquals("OGP",         org.apache.sis.internal.util.Citations.getCodeSpace(OGP));
+        assertEquals("ESRI",        org.apache.sis.internal.util.Citations.getCodeSpace(ESRI));
+        assertEquals("Oracle",      org.apache.sis.internal.util.Citations.getCodeSpace(ORACLE));
+        assertEquals("NetCDF",      org.apache.sis.internal.util.Citations.getCodeSpace(NETCDF));
+        assertEquals("GeoTIFF",     org.apache.sis.internal.util.Citations.getCodeSpace(GEOTIFF));
+        assertEquals("MapInfo",     org.apache.sis.internal.util.Citations.getCodeSpace(MAP_INFO));
+        assertEquals("ISBN",        org.apache.sis.internal.util.Citations.getCodeSpace(ISBN));
+        assertEquals("ISSN",        org.apache.sis.internal.util.Citations.getCodeSpace(ISSN));
+        assertEquals("Proj4",       org.apache.sis.internal.util.Citations.getCodeSpace(PROJ4));
+        assertEquals("S57",         org.apache.sis.internal.util.Citations.getCodeSpace(S57));
+        assertEquals("ISO",         org.apache.sis.internal.util.Citations.getCodeSpace(ISO));
+        assertNull  ("ISO_19115-1", org.apache.sis.internal.util.Citations.getCodeSpace(ISO_19115.get(0)));
+        assertNull  ("ISO_19115-2", org.apache.sis.internal.util.Citations.getCodeSpace(ISO_19115.get(1)));
+    }
+
+    /**
+     * Tests {@code getTitle()} on some {@code Citation} constants.
+     */
+    @Test
+    public void testGetTitles() {
+        assertEquals("Apache Spatial Information System",    SIS    .getTitle().toString(Locale.US));
+        assertEquals("Identifier in OGC namespace",          OGC    .getTitle().toString(Locale.US));
+        assertEquals("EPSG Geodetic Parameter Dataset",      EPSG   .getTitle().toString(Locale.US));
+        assertEquals("International Standard Book Number",   ISBN   .getTitle().toString(Locale.US));
+        assertEquals("International Standard Serial Number", ISSN   .getTitle().toString(Locale.US));
+        assertEquals("GeoTIFF",                              GEOTIFF.getTitle().toString(Locale.US));
+        assertEquals("NetCDF",                               NETCDF .getTitle().toString(Locale.US));
+        assertEquals("Proj.4",                               PROJ4  .getTitle().toString(Locale.US));
+        assertEquals("S-57",                                 S57    .getTitle().toString(Locale.US));
+        assertEquals("Geographic Information — Metadata Part 1: Fundamentals",
+                ISO_19115.get(0).getTitle().toString(Locale.US));
+        assertEquals("Geographic Information — Metadata Part 2: Extensions for imagery and gridded data",
+                ISO_19115.get(1).getTitle().toString(Locale.US));
+    }
+
+    /**
+     * Tests {@code getCitedResponsibleParties()} on some {@code Citation} constants.
+     */
+    @Test
+    public void testGetCitedResponsibleParty() {
+        assertEquals("Open Geospatial Consortium",                       getCitedResponsibleParty(OGC));
+        assertEquals("International Organization for Standardization",   getCitedResponsibleParty(ISO_19115.get(0)));
+        assertEquals("International Organization for Standardization",   getCitedResponsibleParty(ISO_19115.get(1)));
+        assertEquals("International Association of Oil & Gas producers", getCitedResponsibleParty(EPSG));
+    }
+
+    /**
+     * Returns the responsible party for the given constant.
+     */
+    private static String getCitedResponsibleParty(final Citation citation) {
+        return getSingleton(getSingleton(citation.getCitedResponsibleParties()).getParties()).getName().toString(Locale.US);
+    }
+
+    /**
+     * Special tests dedicated to the {@link Citations#EPSG} constant. This is maybe the most important
+     * citation declared in the {@link Citations} class, since it is declared as the authority of almost
+     * all Coordinate Reference System (CRS) objects typically used by SIS.
+     *
+     * <p>Apache SIS identifies the EPSG authority with {@link Identifier} {@code "IOGP:EPSG"}.</p>
+     */
+    @Test
+    public void testEPSG() {
+        final Identifier identifier = getSingleton(EPSG.getIdentifiers());
+        assertEquals("EPSG", getUnicodeIdentifier(EPSG));
+        assertEquals("IOGP", identifier.getCodeSpace());
+        assertEquals("EPSG", identifier.getCode());
+    }
+
+    /**
+     * Test serialization.
+     *
+     * @throws IllegalAccessException should never happen since we asked only for public fields.
+     */
+    @Test
+    @DependsOnMethod("testFromName")
+    public void testSerialization() throws IllegalAccessException {
+        for (final Field field : Citations.class.getFields()) {
+            if (CitationConstant.class.isAssignableFrom(field.getType())) {
+                final Object c = field.get(null);
+                assertSame(field.getName(), c, assertSerializedEquals(c));
+            }
+        }
     }
 }

Modified: sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/DefaultCitationTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/DefaultCitationTest.java?rev=1683756&r1=1683755&r2=1683756&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/DefaultCitationTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/DefaultCitationTest.java [UTF-8] Fri Jun  5 13:53:58 2015
@@ -59,13 +59,13 @@ public final strictfp class DefaultCitat
          */
         assertNull("ISSN shall be initially null.", citation.getISSN());
         citation.setIdentifiers(Arrays.asList(
-                new DefaultIdentifier(HardCodedCitations.OGC,  "MyOGC"),
-                new DefaultIdentifier(HardCodedCitations.EPSG, "MyEPSG"),
-                new DefaultIdentifier(Citations.ISBN, "MyIgnored"),
-                new DefaultIdentifier(Citations.ISSN, "MyISSN")));
+                new DefaultIdentifier(Citations.NETCDF, "MyNetCDF"),
+                new DefaultIdentifier(Citations.EPSG,   "MyEPSG"),
+                new DefaultIdentifier(Citations.ISBN,   "MyIgnored"),
+                new DefaultIdentifier(Citations.ISSN,   "MyISSN")));
 
         assertEquals("The ISBN value shall not have been overwritten.",    "MyISBN", citation.getISBN());
         assertEquals("The ISSN value shall have been added, because new.", "MyISSN", citation.getISSN());
-        assertEquals("{OGC=“MyOGC”, EPSG=“MyEPSG”, ISSN=“MyISSN”, ISBN=“MyISBN”}", identifierMap.toString());
+        assertEquals("{NetCDF=“MyNetCDF”, EPSG=“MyEPSG”, ISSN=“MyISSN”, ISBN=“MyISBN”}", identifierMap.toString());
     }
 }

Modified: sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/HardCodedCitations.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/HardCodedCitations.java?rev=1683756&r1=1683755&r2=1683756&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/HardCodedCitations.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/HardCodedCitations.java [UTF-8] Fri Jun  5 13:53:58 2015
@@ -22,12 +22,11 @@ import org.opengis.metadata.citation.Cit
 import org.opengis.metadata.citation.OnLineFunction;
 import org.opengis.metadata.citation.PresentationForm;
 import org.apache.sis.metadata.iso.DefaultIdentifier;
+import org.apache.sis.metadata.iso.ImmutableIdentifier;
 import org.apache.sis.util.iso.SimpleInternationalString;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.util.Static;
 
-import static java.util.Collections.singleton;
-
 
 /**
  * Hard-coded citation constants used for testing purpose only.
@@ -38,39 +37,21 @@ import static java.util.Collections.sing
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.5
+ * @version 0.6
  * @module
  */
 public final strictfp class HardCodedCitations extends Static {
     /**
-     * The <a href="http://www.opengeospatial.org">Open Geospatial consortium</a> organization.
-     * "Open Geospatial consortium" is the new name for "OpenGIS consortium".
-     * An {@linkplain Citation#getAlternateTitles() alternate title} for this citation is "OGC"
-     * (according ISO 19115, alternate titles often contain abbreviations).
-     */
-    public static final DefaultCitation OGC;
-    static {
-        final DefaultCitation c = new DefaultCitation("Open Geospatial consortium");
-        c.setAlternateTitles(singleton(new SimpleInternationalString(Constants.OGC)));
-        c.setPresentationForms(singleton(PresentationForm.DOCUMENT_DIGITAL));
-        c.setIdentifiers(singleton(new DefaultIdentifier(Constants.OGC)));
-        c.freeze();
-        OGC = c;
-    }
-
-    /**
-     * The <a href="http://www.iso.org/">International Organization for Standardization</a>
-     * organization. An {@linkplain Citation#getAlternateTitles() alternate title} for this
-     * citation is "ISO" (according ISO 19115, alternate titles often contain abbreviations).
+     * The ISO 19111 standard.
      */
-    public static final DefaultCitation ISO;
+    public static final DefaultCitation ISO_19111;
     static {
-        final DefaultCitation c = new DefaultCitation("International Organization for Standardization");
-        c.setAlternateTitles(singleton(new SimpleInternationalString("ISO")));
-        c.setPresentationForms(singleton(PresentationForm.DOCUMENT_DIGITAL));
-        c.setIdentifiers(singleton(new DefaultIdentifier("ISO")));
+        final DefaultCitation c = new DefaultCitation("Spatial referencing by coordinates");
+        c.getAlternateTitles().add(new SimpleInternationalString("ISO 19111"));
+        c.getIdentifiers().add(new ImmutableIdentifier(null, "ISO", "19111"));
+        c.getPresentationForms().add(PresentationForm.DOCUMENT_DIGITAL);
         c.freeze();
-        ISO = c;
+        ISO_19111 = c;
     }
 
     /**
@@ -79,38 +60,20 @@ public final strictfp class HardCodedCit
     public static final DefaultCitation ISO_19115;
     static {
         final DefaultCitation c = new DefaultCitation("ISO 19115");
-        c.setPresentationForms(singleton(PresentationForm.DOCUMENT_DIGITAL));
+        c.getPresentationForms().add(PresentationForm.DOCUMENT_DIGITAL);
         c.freeze();
         ISO_19115 = c;
     }
 
     /**
-     * The <a href="http://www.iogp.org">International Association of Oil &amp; Gas Producers</a> organization.
-     * This organization is responsible for maintainance of {@link #EPSG} database.
-     * An {@linkplain Citation#getAlternateTitles() alternate title} for this citation is "IOGP"
-     * (according ISO 19115, alternate titles often contain abbreviations).
-     */
-    public static final DefaultCitation IOGP;
-    static {
-        final DefaultCitation c = new DefaultCitation("International Association of Oil & Gas Producers");
-        c.setAlternateTitles(singleton(new SimpleInternationalString(Constants.IOGP)));
-        c.setIdentifiers(singleton(new DefaultIdentifier(Constants.IOGP)));
-        c.freeze();
-        IOGP = c;
-    }
-
-    /**
-     * The <a href="http://www.epsg.org">European Petroleum Survey Group</a> authority.
-     * An {@linkplain Citation#getAlternateTitles() alternate title} for this citation is "EPSG"
-     * (according ISO 19115, alternate titles often contain abbreviations). In addition,
-     * this citation contains the "EPSG" {@linkplain Citation#getIdentifiers() identifier}.
+     * The <a href="http://www.epsg.org">EPSG Geodetic Parameter Dataset</a> authority.
+     * This citation contains the "EPSG" {@linkplain Citation#getIdentifiers() identifier}.
      *
      * <p>String representation:</p>
      *
      * {@preformat text
      *   Citation
-     *     ├─Title………………………………………………………… European Petroleum Survey Group
-     *     ├─Alternate title……………………………… EPSG
+     *     ├─Title………………………………………………………… EPSG Geodetic Parameter Dataset
      *     ├─Identifier
      *     │   └─Code………………………………………………… EPSG
      *     ├─Cited responsible party
@@ -130,30 +93,18 @@ public final strictfp class HardCodedCit
         r.setFunction(OnLineFunction.INFORMATION);
 
         final DefaultResponsibility p = new DefaultResponsibility(Role.PRINCIPAL_INVESTIGATOR, null,
-                new DefaultOrganisation(IOGP.getTitle(), null, null, new DefaultContact(r)));
+                new DefaultOrganisation("International Association of Oil & Gas Producers", null, null, new DefaultContact(r)));
 
-        final DefaultCitation c = new DefaultCitation("European Petroleum Survey Group");
-        c.setAlternateTitles(singleton(new SimpleInternationalString("EPSG")));
-        c.setPresentationForms(singleton(PresentationForm.TABLE_DIGITAL));
-        c.setIdentifiers(singleton(new DefaultIdentifier(Constants.EPSG)));
-        c.setCitedResponsibleParties(singleton(p));
+        final DefaultCitation c = new DefaultCitation("EPSG Geodetic Parameter Dataset");
+        c.getPresentationForms().add(PresentationForm.TABLE_DIGITAL);
+        c.getIdentifiers().add(new DefaultIdentifier(Constants.EPSG));
+        c.getCitedResponsibleParties().add(p);
         c.freeze();
         EPSG = c;
     }
 
     /**
-     * The <a href="http://www.remotesensing.org/geotiff/geotiff.html">GeoTIFF</a> specification.
-     */
-    public static final DefaultCitation GEOTIFF;
-    static {
-        final DefaultCitation c = new DefaultCitation("GeoTIFF");
-        c.setPresentationForms(singleton(PresentationForm.DOCUMENT_DIGITAL));
-        c.freeze();
-        GEOTIFF = c;
-    }
-
-    /**
-     * The <a href="http://sis.apache.org">Apache SIS</a> project.
+     * Codespace for objects specific to <a href="http://sis.apache.org">Apache SIS</a>.
      */
     public static final DefaultCitation SIS;
     static {

Modified: sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java?rev=1683756&r1=1683755&r2=1683756&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java [UTF-8] Fri Jun  5 13:53:58 2015
@@ -33,6 +33,7 @@ import org.junit.BeforeClass;
     org.apache.sis.internal.metadata.WKTKeywordsTest.class,
     org.apache.sis.internal.metadata.NameMeaningTest.class,
     org.apache.sis.internal.metadata.MetadataUtilitiesTest.class,
+    org.apache.sis.internal.metadata.VerticalDatumTypesTest.class,
     org.apache.sis.internal.metadata.OtherLocalesTest.class,
 
     // Classes using Java reflection.

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/Code.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/Code.java?rev=1683756&r1=1683755&r2=1683756&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/Code.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/Code.java [UTF-8] Fri Jun  5 13:53:58 2015
@@ -21,12 +21,13 @@ import javax.xml.bind.annotation.XmlValu
 import javax.xml.bind.annotation.XmlAttribute;
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
+import org.apache.sis.internal.util.Constants;
 import org.apache.sis.internal.util.DefinitionURI;
 import org.apache.sis.internal.metadata.NameMeaning;
 import org.apache.sis.referencing.NamedIdentifier;
 import org.apache.sis.metadata.iso.citation.Citations;
 
-import static org.apache.sis.internal.util.Citations.getUnicodeIdentifier;
+import static org.apache.sis.internal.util.Citations.getCodeSpace;
 
 
 /**
@@ -36,7 +37,7 @@ import static org.apache.sis.internal.ut
  * @author  Cédric Briançon (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.5
+ * @version 0.6
  * @module
  */
 @XmlType(name = "CodeType")
@@ -103,11 +104,41 @@ public final class Code {
         String version = null, cs = codeSpace;
         final DefinitionURI parsed = DefinitionURI.parse(c);
         if (parsed != null) {
-            authority = Citations.fromName(cs); // May be null.
-            cs        = parsed.authority;
-            version   = parsed.version;
-            c         = parsed.code;
+            /*
+             * Case where the URN has been successfully parsed. The OGC's URN contains an "authority" component,
+             * which we take as the Identifier.codeSpace value (not Identifier.authority despite what the names
+             * would suggest).
+             *
+             * The GML document may also provide a 'codeSpace' attribute separated from the URN, which we take
+             * as the authority.  This is the opposite of what the names would suggest, but we can not map the
+             * 'codeSpace' attribute to Identifier.codeSpace  because the 'codeSpace' attribute value found in
+             * practice is often "IOGP" while the 'Identifier.description' example provided in ISO 19115-1 for
+             * an EPSG code has the "EPSG" codespace. Example:
+             *
+             *    - XML: <gml:identifier codeSpace="IOGP">urn:ogc:def:crs:EPSG::4326</gml:identifier>
+             *    - ISO: For "EPSG::4326", Identifier.codeSpace = "EPSG" and Identifier.code = "4326".
+             *
+             * Apache SIS attempts to organize this apparent contradiction by considering IOGP as the codespace of
+             * the EPSG codespace, but this interpretation is not likely to be widely used by libraries other than
+             * SIS. For now, a special handling is hard-coded below: if codeSpace = "IOGP" and authority = "EPSG",
+             * then we take the authority as the Citations.EPSG constant, which has a "IOGP:EPSG" identifier.
+             *
+             * A symmetrical special handling for EPSG is done in the 'forIdentifiedObject(…)' method of this class.
+             */
+            if (org.apache.sis.internal.util.Citations.isEPSG(cs, parsed.authority)) {
+                authority = Citations.EPSG;
+            } else {
+                authority = Citations.fromName(cs);     // May be null.
+            }
+            cs      = parsed.authority;
+            version = parsed.version;
+            c       = parsed.code;
         } else if (cs != null) {
+            /*
+             * Case where the URN can not be parsed but a 'codeSpace' attribute exists. We take this 'codeSpace'
+             * as both the code space and the authority. As a special case, if there is a semi-colon, we take all
+             * text after that semi-color as the version number.
+             */
             final int s = cs.lastIndexOf(DefinitionURI.SEPARATOR);
             if (s >= 0) {
                 version = cs.substring(s+1);
@@ -124,7 +155,8 @@ public final class Code {
      * <ul>
      *   <li>The first identifier having a code that begin with {@code "urn:"}.</li>
      *   <li>The first identifier having a code that begin with {@code "http:"}.</li>
-     *   <li>The first identifier, converted to the {@code "urn:} syntax if possible.</li>
+     *   <li>The first identifier in the {@code "EPSG"} codespace, converted to the {@code "urn:} syntax.</li>
+     *   <li>The first identifier in other codespace, converted to the {@code "urn:} syntax if possible.</li>
      * </ul>
      *
      * @param  type The type of the identified object.
@@ -134,6 +166,7 @@ public final class Code {
     public static Code forIdentifiedObject(final Class<?> type, final Iterable<? extends Identifier> identifiers) {
         if (identifiers != null) {
             boolean isHTTP = false;
+            boolean isEPSG = false;
             Identifier fallback = null;
             for (final Identifier identifier : identifiers) {
                 final String code = identifier.getCode();
@@ -143,13 +176,18 @@ public final class Code {
                 }
                 if (!isHTTP) {
                     isHTTP = code.regionMatches(true, 0, "http:", 0, 5);
-                    if (isHTTP || fallback == null) {
+                    if (isHTTP) {
                         fallback = identifier;
+                    } else if (!isEPSG) {
+                        isEPSG = Constants.EPSG.equalsIgnoreCase(identifier.getCodeSpace());
+                        if (isEPSG || fallback == null) {
+                            fallback = identifier;
+                        }
                     }
                 }
             }
             /*
-             * If no "urn:" or "http:" form has been found, try to create a "urn:" form the first identifier.
+             * If no "urn:" or "http:" form has been found, try to create a "urn:" form from the first identifier.
              * For example "EPSG:4326" may be converted to "urn:ogc:def:crs:EPSG:8.2:4326". If the first identifier
              * can not be converted to a "urn:" form, then it will be returned as-is.
              */
@@ -159,15 +197,50 @@ public final class Code {
                     if (urn != null) {
                         final Code code = new Code();
                         /*
-                         * Really getUnicodeIdentifier(…) below, not getCodeSpace(…). The reason is that the
-                         * code space already appears in the URN string, and common usage found in GML files
-                         * is to use the "codeSpace" attribute for the authority ("OGP" or "IOGP" for objects
-                         * from the EPSG database). Consequently in the common case where the authority is our
-                         * Citations.EPSG constant, we really want the "IOGP" string rather than "EPSG".
+                         * Rational for EPSG special case below:
+                         * -------------------------------------
+                         * Apache SIS already formats the Identifier.getCodeSpace() value in the URN.
+                         * This value is "EPSG" for IdentifiedObject instances from the EPSG database.
+                         * But GML additionally have a "codeSpace" attribute, and common usage seems to
+                         * give the "OGP" or "IOGP" value to that attribute as in the following example:
+                         *
+                         *     <gml:identifier codeSpace="IOGP">urn:ogc:def:crs:EPSG::4326</gml:identifier>
+                         *
+                         * A discussion can be found in the comments of https://issues.apache.org/jira/browse/SIS-196
+                         *
+                         * Where to take this "IOGP" value from? It is not the Identifier.getCodeSpace() String value
+                         * since ISO 19115-1 clearly uses the "EPSG" value in their example.  We could consider using
+                         * the Identifier.getAuthority() value, which is a Citation. But the "EPSG" part in above URN
+                         * is named "the authority" in URN specification, which suggest that Identifier.getAuthority()
+                         * should return a citation for the "EPSG Geodetic Parameter Dataset" rather than for the IOGP
+                         * organisation.
+                         *
+                         * Apache SIS declares IOGP as the codespace of the EPSG codespace, i.e. the identifier of the
+                         * EPSG authority is "IOGP:EPSG". So the code below searches for the "IOGP" part of the above.
+                         * However there is no indication at this time that objects from other sources than SIS would
+                         * follow such convention, so we also keep a hard-coded "IOGP" default value for now.
+                         *
+                         * A symmetrical special handling for EPSG is done in the 'getIdentifier()' method of this class.
                          *
-                         * See https://issues.apache.org/jira/browse/SIS-196
+                         * See https://issues.apache.org/jira/browse/SIS-199
                          */
-                        code.codeSpace = getUnicodeIdentifier(fallback.getAuthority());
+                        final Citation authority = fallback.getAuthority();
+                        if (isEPSG) {
+                            code.codeSpace = Constants.IOGP;    // Default value if we do not find a codespace below.
+                            if (authority != null) {
+                                for (final Identifier id : authority.getIdentifiers()) {
+                                    if (Constants.EPSG.equalsIgnoreCase(id.getCode())) {
+                                        final String cs = id.getCodeSpace();
+                                        if (cs != null) {
+                                            code.codeSpace = cs;
+                                            break;
+                                        }
+                                    }
+                                }
+                            }
+                        } else {
+                            code.codeSpace = getCodeSpace(authority);
+                        }
                         code.code = urn;
                         return code;
                     }



Mime
View raw message