You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2018/02/26 11:28:20 UTC

svn commit: r1825355 [14/15] - in /sis/trunk: ./ application/sis-console/src/test/java/org/apache/sis/console/ core/sis-build-helper/src/main/resources/org/apache/sis/internal/book/ core/sis-metadata/ core/sis-metadata/src/main/java/org/apache/sis/inte...

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/PooledUnmarshaller.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/PooledUnmarshaller.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/PooledUnmarshaller.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/PooledUnmarshaller.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -50,12 +50,12 @@ import org.apache.sis.internal.jaxb.Cont
  *       when the unmarshaller is recycled.</li>
  *   <li>Constructs a SIS {@link Context} object on unmarshalling, in order to give
  *       additional information to the SIS object being unmarshalled.</li>
- *   <li>Wraps the input stream in a {@link FilteredStreamReader} if the document GML version
+ *   <li>Wraps the input stream in a {@link TransformingReader} if the document GML version
  *       in not the SIS native GML version.</li>
  * </ul>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.4
+ * @version 1.0
  * @since   0.3
  * @module
  */
@@ -109,18 +109,17 @@ final class PooledUnmarshaller extends P
 
     /**
      * Unmarshals to the given input with on-the-fly substitution of namespaces.
-     * This method is invoked only when the user asked to marshal from a different GML version
-     * than the one supported natively by SIS, i.e. when {@link #getFilterVersion()} returns a
-     * non-null value.
+     * This method is invoked when we may marshal a different GML or metadata version than the one
+     * supported natively by SIS, i.e. when {@link #getTransformVersion()} returns a non-null value.
      *
      * @param  input    the reader created by SIS (<b>not</b> the reader given by the user).
      * @param  version  identify the namespace substitutions to perform.
      * @return the unmarshalled object.
      */
-    private Object unmarshal(XMLStreamReader input, final FilterVersion version)
+    private Object unmarshal(XMLEventReader input, final TransformVersion version)
             throws XMLStreamException, JAXBException
     {
-        input = new FilteredStreamReader(input, version);
+        input = new TransformingReader(input, version);
         final Context context = begin();
         final Object object;
         try {
@@ -133,13 +132,13 @@ final class PooledUnmarshaller extends P
     }
 
     /**
-     * Same as {@link #unmarshal(XMLStreamReader, FilterVersion)}, but delegating to the unmarshaller
+     * Same as {@link #unmarshal(XMLEventReader, TransformVersion)}, but delegating to the unmarshaller
      * methods returning a JAXB element instead than the one returning the object.
      */
-    private <T> JAXBElement<T> unmarshal(XMLStreamReader input, final FilterVersion version, final Class<T> declaredType)
+    private <T> JAXBElement<T> unmarshal(XMLEventReader input, final TransformVersion version, final Class<T> declaredType)
             throws XMLStreamException, JAXBException
     {
-        input = new FilteredStreamReader(input, version);
+        input = new TransformingReader(input, version);
         final Context context = begin();
         final JAXBElement<T> object;
         try {
@@ -156,9 +155,9 @@ final class PooledUnmarshaller extends P
      */
     @Override
     public Object unmarshal(final InputStream input) throws JAXBException {
-        final FilterVersion version = getFilterVersion();
+        final TransformVersion version = getTransformVersion();
         if (version != null) try {
-            return unmarshal(InputFactory.createXMLStreamReader(input), version);
+            return unmarshal(InputFactory.createXMLEventReader(input), version);
         } catch (XMLStreamException e) {
             throw new JAXBException(e);
         } else {
@@ -176,10 +175,10 @@ final class PooledUnmarshaller extends P
      */
     @Override
     public Object unmarshal(final URL input) throws JAXBException {
-        final FilterVersion version = getFilterVersion();
+        final TransformVersion version = getTransformVersion();
         if (version != null) try {
             try (InputStream s = input.openStream()) {
-                return unmarshal(InputFactory.createXMLStreamReader(s), version);
+                return unmarshal(InputFactory.createXMLEventReader(s), version);
             }
         } catch (IOException | XMLStreamException e) {
             throw new JAXBException(e);
@@ -198,10 +197,10 @@ final class PooledUnmarshaller extends P
      */
     @Override
     public Object unmarshal(final File input) throws JAXBException {
-        final FilterVersion version = getFilterVersion();
+        final TransformVersion version = getTransformVersion();
         if (version != null) try {
             try (InputStream s = new BufferedInputStream(new FileInputStream(input))) {
-                return unmarshal(InputFactory.createXMLStreamReader(s), version);
+                return unmarshal(InputFactory.createXMLEventReader(s), version);
             }
         } catch (IOException | XMLStreamException e) {
             throw new JAXBException(e);
@@ -220,9 +219,9 @@ final class PooledUnmarshaller extends P
      */
     @Override
     public Object unmarshal(final Reader input) throws JAXBException {
-        final FilterVersion version = getFilterVersion();
+        final TransformVersion version = getTransformVersion();
         if (version != null) try {
-            return unmarshal(InputFactory.createXMLStreamReader(input), version);
+            return unmarshal(InputFactory.createXMLEventReader(input), version);
         } catch (XMLStreamException e) {
             throw new JAXBException(e);
         } else {
@@ -240,9 +239,9 @@ final class PooledUnmarshaller extends P
      */
     @Override
     public Object unmarshal(final InputSource input) throws JAXBException {
-        final FilterVersion version = getFilterVersion();
+        final TransformVersion version = getTransformVersion();
         if (version != null) try {
-            return unmarshal(InputFactory.createXMLStreamReader(input), version);
+            return unmarshal(InputFactory.createXMLEventReader(input), version);
         } catch (XMLStreamException e) {
             throw new JAXBException(e);
         } else {
@@ -260,9 +259,9 @@ final class PooledUnmarshaller extends P
      */
     @Override
     public Object unmarshal(final Node input) throws JAXBException {
-        final FilterVersion version = getFilterVersion();
+        final TransformVersion version = getTransformVersion();
         if (version != null) try {
-            return unmarshal(InputFactory.createXMLStreamReader(input), version);
+            return unmarshal(InputFactory.createXMLEventReader(input), version);
         } catch (XMLStreamException e) {
             throw new JAXBException(e);
         } else {
@@ -280,9 +279,9 @@ final class PooledUnmarshaller extends P
      */
     @Override
     public <T> JAXBElement<T> unmarshal(final Node input, final Class<T> declaredType) throws JAXBException {
-        final FilterVersion version = getFilterVersion();
+        final TransformVersion version = getTransformVersion();
         if (version != null) try {
-            return unmarshal(InputFactory.createXMLStreamReader(input), version, declaredType);
+            return unmarshal(InputFactory.createXMLEventReader(input), version, declaredType);
         } catch (XMLStreamException e) {
             throw new JAXBException(e);
         } else {
@@ -300,9 +299,9 @@ final class PooledUnmarshaller extends P
      */
     @Override
     public Object unmarshal(final Source input) throws JAXBException {
-        final FilterVersion version = getFilterVersion();
+        final TransformVersion version = getTransformVersion();
         if (version != null) try {
-            return unmarshal(InputFactory.createXMLStreamReader(input), version);
+            return unmarshal(InputFactory.createXMLEventReader(input), version);
         } catch (XMLStreamException e) {
             throw new JAXBException(e);
         } else {
@@ -320,9 +319,9 @@ final class PooledUnmarshaller extends P
      */
     @Override
     public <T> JAXBElement<T> unmarshal(final Source input, final Class<T> declaredType) throws JAXBException {
-        final FilterVersion version = getFilterVersion();
+        final TransformVersion version = getTransformVersion();
         if (version != null) try {
-            return unmarshal(InputFactory.createXMLStreamReader(input), version, declaredType);
+            return unmarshal(InputFactory.createXMLEventReader(input), version, declaredType);
         } catch (XMLStreamException e) {
             throw new JAXBException(e);
         } else {
@@ -339,44 +338,10 @@ final class PooledUnmarshaller extends P
      * Delegates the unmarshalling to the wrapped unmarshaller.
      */
     @Override
-    public Object unmarshal(XMLStreamReader input) throws JAXBException {
-        final FilterVersion version = getFilterVersion();
-        if (version != null) {
-            input = new FilteredStreamReader(input, version);
-        }
-        final Context context = begin();
-        try {
-            return unmarshaller.unmarshal(input);
-        } finally {
-            context.finish();
-        }
-    }
-
-    /**
-     * Delegates the unmarshalling to the wrapped unmarshaller.
-     */
-    @Override
-    public <T> JAXBElement<T> unmarshal(XMLStreamReader input, final Class<T> declaredType) throws JAXBException {
-        final FilterVersion version = getFilterVersion();
-        if (version != null) {
-            input = new FilteredStreamReader(input, version);
-        }
-        final Context context = begin();
-        try {
-            return unmarshaller.unmarshal(input, declaredType);
-        } finally {
-            context.finish();
-        }
-    }
-
-    /**
-     * Delegates the unmarshalling to the wrapped unmarshaller.
-     */
-    @Override
-    public Object unmarshal(final XMLEventReader input) throws JAXBException {
-        final FilterVersion version = getFilterVersion();
+    public Object unmarshal(final XMLStreamReader input) throws JAXBException {
+        final TransformVersion version = getTransformVersion();
         if (version != null) try {
-            return unmarshal(InputFactory.createXMLStreamReader(input), version);
+            return unmarshal(InputFactory.createXMLEventReader(input), version);
         } catch (XMLStreamException e) {
             throw new JAXBException(e);
         } else {
@@ -393,10 +358,10 @@ final class PooledUnmarshaller extends P
      * Delegates the unmarshalling to the wrapped unmarshaller.
      */
     @Override
-    public <T> JAXBElement<T> unmarshal(final XMLEventReader input, final Class<T> declaredType) throws JAXBException {
-        final FilterVersion version = getFilterVersion();
+    public <T> JAXBElement<T> unmarshal(final XMLStreamReader input, final Class<T> declaredType) throws JAXBException {
+        final TransformVersion version = getTransformVersion();
         if (version != null) try {
-            return unmarshal(InputFactory.createXMLStreamReader(input), version, declaredType);
+            return unmarshal(InputFactory.createXMLEventReader(input), version, declaredType);
         } catch (XMLStreamException e) {
             throw new JAXBException(e);
         } else {
@@ -409,6 +374,40 @@ final class PooledUnmarshaller extends P
         }
     }
 
+    /**
+     * Delegates the unmarshalling to the wrapped unmarshaller.
+     */
+    @Override
+    public Object unmarshal(XMLEventReader input) throws JAXBException {
+        final TransformVersion version = getTransformVersion();
+        if (version != null) {
+            input = new TransformingReader(input, version);
+        }
+        final Context context = begin();
+        try {
+            return unmarshaller.unmarshal(input);
+        } finally {
+            context.finish();
+        }
+    }
+
+    /**
+     * Delegates the unmarshalling to the wrapped unmarshaller.
+     */
+    @Override
+    public <T> JAXBElement<T> unmarshal(XMLEventReader input, final Class<T> declaredType) throws JAXBException {
+        final TransformVersion version = getTransformVersion();
+        if (version != null) {
+            input = new TransformingReader(input, version);
+        }
+        final Context context = begin();
+        try {
+            return unmarshaller.unmarshal(input, declaredType);
+        } finally {
+            context.finish();
+        }
+    }
+
     /**
      * Delegates to the wrapped unmarshaller.
      */

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/ReferenceResolver.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/ReferenceResolver.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/ReferenceResolver.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/ReferenceResolver.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -100,7 +100,6 @@ public class ReferenceResolver {
      * @param  uuid     the {@code uuid} attributes.
      * @return an object of the given type for the given {@code uuid} attribute, or {@code null} if none.
      */
-    @SuppressWarnings("unchecked")
     public <T> T resolve(final MarshalContext context, final Class<T> type, final UUID uuid) {
         ensureNonNull("type", type);
         ensureNonNull("uuid", uuid);
@@ -243,8 +242,8 @@ public class ReferenceResolver {
 
     /**
      * Returns the {@code <gmx:Anchor>} to use for the given text, or {@code null} if none.
-     * Anchors can appear in ISO 19139 documents where we would normally expect a character
-     * sequence. For example:
+     * Anchors can appear in ISO 19115-3 documents where we would normally expect a character sequence.
+     * For example:
      *
      * <table class="sis">
      * <caption>XML representations of string</caption>

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/ValueConverter.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/ValueConverter.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/ValueConverter.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/ValueConverter.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -115,7 +115,7 @@ public class ValueConverter {
     }
 
     /**
-     * Converts the given locale to a language code. For better ISO 19139 compliance, the language code
+     * Converts the given locale to a language code. For better compliance with ISO standards, the language code
      * should be a 3-letters ISO 639-2 code (e.g. {@code "jpn"} for {@linkplain Locale#JAPANESE Japanese}).
      * However those codes may not be available for every locales.
      *
@@ -159,7 +159,7 @@ public class ValueConverter {
     }
 
     /**
-     * Converts the given locale to a country code. For better ISO 19139 compliance, the country code
+     * Converts the given locale to a country code. For better compliance with ISO standards, the country code
      * should be a 2-letters ISO 3166 code (e.g. {@code "JP"} for {@linkplain Locale#JAPAN Japan}).
      *
      * <p>The default implementation returns {@link Locale#getCountry()} if non-empty, or {@code null} otherwise.</p>
@@ -185,7 +185,7 @@ public class ValueConverter {
     /**
      * Converts the given character set to a code.
      *
-     * <p>The default implementation first invokes {@link Charset#name()}. Then if marshalling to ISO 19139:2007,
+     * <p>The default implementation first invokes {@link Charset#name()}. Then if marshalling to legacy ISO 19139:2007,
      * this method converts the <a href="http://www.iana.org/assignments/character-sets">IANA</a> name to a
      * ISO 19115:2003 {@code MD_CharacterSetCode} using the following equivalence table:</p>
      *

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/XML.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/XML.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/XML.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/XML.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -54,6 +54,17 @@ import static org.apache.sis.util.Argume
 
 /**
  * Provides convenience methods for marshalling and unmarshalling SIS objects.
+ * Marshalling operations use the standard versions listed below
+ * (for marshalling a document in a different version, see {@link PooledMarshaller}).
+ * Unmarshalling detects the version automatically.
+ *
+ * <table class="sis">
+ *   <caption>Versions of standards applied at marshalling time</caption>
+ *   <tr><th>Topic</th>       <th>SIS 0.3 to 0.8</th>  <th>SIS 1.0</th>          <td>Remarks</td></tr>
+ *   <tr><td>Metadata</td>    <td>ISO 19139:2007</td>  <td>ISO 19115-3:2016</td> <td></td></tr>
+ *   <tr><td>Referencing</td> <td>ISO 19136:2007</td>  <td>ISO 19136:2007</td>   <td>Same as GML 3.2</td></tr>
+ * </table>
+ *
  * This class defines also some property keys that can be given to the {@link Marshaller}
  * and {@link Unmarshaller} instances created by {@link PooledMarshaller}:
  *
@@ -64,7 +75,8 @@ import static org.apache.sis.util.Argume
  *   <tr><td>{@link #TIMEZONE}</td>           <td>{@link TimeZone}</td>          <td>for specifying the timezone to use for dates and times.</td></tr>
  *   <tr><td>{@link #SCHEMAS}</td>            <td>{@link Map}</td>               <td>for specifying the root URL of metadata schemas to use.</td></tr>
  *   <tr><td>{@link #DEFAULT_NAMESPACE}</td>  <td>{@link String}</td>            <td>for specifying the default namespace of the XML document to write.</td></tr>
- *   <tr><td>{@link #GML_VERSION}</td>        <td>{@link Version}</td>           <td>for specifying the GML version to the document be (un)marshalled.</td></tr>
+ *   <tr><td>{@link #GML_VERSION}</td>        <td>{@link Version}</td>           <td>for specifying the GML version of the document to be (un)marshalled.</td></tr>
+ *   <tr><td>{@link #METADATA_VERSION}</td>   <td>{@link Version}</td>           <td>for specifying the metadata version of the document to be (un)marshalled.</td></tr>
  *   <tr><td>{@link #RESOLVER}</td>           <td>{@link ReferenceResolver}</td> <td>for replacing {@code xlink} or {@code uuidref} attributes by the actual object to use.</td></tr>
  *   <tr><td>{@link #CONVERTER}</td>          <td>{@link ValueConverter}</td>    <td>for controlling the conversion of URL, UUID, Units or similar objects.</td></tr>
  *   <tr><td>{@link #STRING_SUBSTITUTES}</td> <td>{@code String[]}</td>          <td>for specifying which code lists to replace by simpler {@code <gco:CharacterString>} elements.</td></tr>
@@ -73,7 +85,8 @@ import static org.apache.sis.util.Argume
  *
  * @author  Cédric Briançon (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @author  Cullen Rombach (Image Matters)
+ * @version 1.0
  * @since   0.3
  * @module
  */
@@ -130,23 +143,31 @@ public final class XML extends Static {
      *
      * <ul>
      *   <li>The value of the {@code codeList} attribute when marshalling subclasses of
-     *       {@link org.opengis.util.CodeList} in ISO 19139 compliant XML document.</li>
-     *   <li>The value of the {@code uom} attribute when marshalling measures (for example
-     *       {@code <gco:Distance>}) in ISO 19139 compliant XML document.</li>
+     *       {@link org.opengis.util.CodeList}.</li>
+     *   <li>The value of the {@code uom} attribute when marshalling measures
+     *       (for example {@code <gco:Distance>}).</li>
      * </ul>
      *
-     * As of SIS 0.3, only one {@code Map} key is recognized: {@code "gmd"}, which stands
-     * for the ISO 19139 schemas. Additional keys, if any, are ignored. Future SIS versions
-     * may recognize more keys.
+     * Two {@code Map} keys are currently recognized: {@code "cat"} and {@code "gmd"},
+     * which stands for the new ISO 19115-3:2016 and the legacy ISO 19139:2007 schemas respectively.
+     * The key to be used depends on the {@linkplain #METADATA_VERSION metadata version} to be marshalled.
+     * Additional keys, if any, are ignored. Future SIS versions may recognize more keys.
      *
      * <div class="section">Valid values</div>
+     * The following table gives some typical URLs.
+     * The URL in bold character is the default one.
+     *
      * <table class="sis">
      *   <caption>Supported schemas</caption>
      *   <tr><th>Map key</th> <th>Typical values (choose only one)</th></tr>
+     *   <tr><td><b>cat</b></td><td>
+     *     <b>http://standards.iso.org/iso/19115/</b>
+     *   </td></tr>
      *   <tr><td><b>gmd</b></td><td>
-     *     http://schemas.opengis.net/iso/19139/20070417/<br>
-     *     http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/<br>
-     *     http://eden.ign.fr/xsd/fra/20060922/
+     *        http://www.isotc211.org/2005/<br>
+     *     <b>http://schemas.opengis.net/iso/19139/20070417/</b><br>
+     *        http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/<br>
+     *        http://eden.ign.fr/xsd/fra/20060922/
      *   </td></tr>
      * </table>
      */
@@ -160,19 +181,23 @@ public final class XML extends Static {
      * <div class="section">Current limitation</div>
      * In current SIS implementation, this property is honored only by the {@link MarshallerPool} constructors.
      * Specifying this property to {@link javax.xml.bind.Marshaller#setProperty(String, Object)} is too late.
+     *
+     * @deprecated Use {@link javax.xml.bind.annotation.XmlSchema} instead.
      */
+    @Deprecated
     public static final String DEFAULT_NAMESPACE = "org.apache.sis.xml.defaultNamespace";
 
     /**
      * Specifies the GML version of the document to be marshalled or unmarshalled.
      * The GML version may affect the set of XML elements to be marshalled and their namespaces.
+     * Note that GML 3.2 is identical to ISO 19136:2007.
      *
      * <div class="note"><b>Compatibility note:</b>
      * Newer versions typically have more elements, but not always. For example in {@code <gml:VerticalDatum>},
      * the {@code <gml:verticalDatumType>} property presents in GML 3.0 and 3.1 has been removed in GML 3.2.</div>
      *
-     * The value can be {@link String} or {@link Version} objects.
-     * If no version is specified, then the most recent GML version is assumed.
+     * The value can be {@link String} or {@link Version} object.
+     * If no version is specified, then the most recent supported GML version is assumed.
      *
      * <div class="section">Supported GML versions</div>
      * Apache SIS currently supports GML 3.2.1 by default. SIS can read and write GML 3.2
@@ -184,6 +209,26 @@ public final class XML extends Static {
     public static final String GML_VERSION = "org.apache.sis.gml.version";
 
     /**
+     * Specifies the metadata version of the document to be marshalled or unmarshalled.
+     * The metadata version may affect the set of XML elements to be marshalled and their namespaces.
+     * The value can be {@link String} or {@link Version} object.
+     * If no version is specified, then the most recent supported metadata version is assumed.
+     *
+     * <p>The metadata version may be ignored when the metadata to marshal is inside a GML element.
+     * For example the {@code <gml:domainOfValidity>} element inside a coordinate reference system
+     * is always marshalled using ISO 19139:2007 if the enclosing element uses GML 3.2 schema.</p>
+     *
+     * <div class="section">Supported metadata versions</div>
+     * Apache SIS currently supports ISO 19115-3:2016 by default. This version can be explicitly
+     * set with value "2014" or above (because the abstract model was defined in ISO 19115-1:2014).
+     * SIS can write legacy ISO 19139:2007 documents if this property is set to a value less than "2014".
+     * Both versions can be read without the need to specify this property.
+     *
+     * @since 1.0
+     */
+    public static final String METADATA_VERSION = "org.apache.sis.xml.version.metadata";
+
+    /**
      * Allows client code to replace {@code xlink} or {@code uuidref} attributes by the actual objects to use.
      * The value for this property shall be an instance of {@link ReferenceResolver}.
      *

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/package-info.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/package-info.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/package-info.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/package-info.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -17,8 +17,8 @@
 
 /**
  * Provides methods for marshalling and unmarshalling SIS objects in XML.
- * The XML format is compliant with ISO 19139 specification for metadata, and
- * compliant with GML for referencing objects.
+ * The XML format is compliant with ISO 19115-3 specification for metadata,
+ * and compliant with GML for referencing objects.
  *
  * <p>The main class in this package is {@link org.apache.sis.xml.XML}, which provides
  * property keys that can be used for configuring (un)marshallers and convenience
@@ -42,7 +42,7 @@
  * }
  *
  * <div class="section">Customizing the XML</div>
- * In order to parse and format ISO 19139 compliant documents, SIS needs its own
+ * In order to parse and format ISO 19115-3 compliant documents, SIS needs its own
  * {@link javax.xml.bind.Marshaller} and {@link javax.xml.bind.Unmarshaller} instances
  * (which are actually wrappers around standard instances). Those instances are created
  * and cached by {@link org.apache.sis.xml.MarshallerPool}, which is used internally by
@@ -58,7 +58,8 @@
  * @author  Cédric Briançon (Geomatys)
  * @author  Guilhem Legal (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.7
+ * @author  Cullen Rombach (Image Matters)
+ * @version 1.0
  * @since   0.3
  * @module
  */

Modified: sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gco/StringAdapterTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gco/StringAdapterTest.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gco/StringAdapterTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gco/StringAdapterTest.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -57,7 +57,7 @@ public final strictfp class StringAdapte
         i18n.add(Locale.ENGLISH,  "A word");
         i18n.add(Locale.FRENCH,   "Un mot");
         i18n.add(Locale.JAPANESE, "言葉");
-        final Context context = new Context(0, Locale.ENGLISH, null, null, null, null, null, null);
+        final Context context = new Context(0, Locale.ENGLISH, null, null, null, null, null, null, null);
         try {
             Context.push(Locale.JAPANESE);  assertEquals("言葉",    StringAdapter.toString(i18n));
             Context.push(Locale.FRENCH);    assertEquals("Un mot", StringAdapter.toString(i18n));

Modified: sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gmd/LanguageCodeTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gmd/LanguageCodeTest.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gmd/LanguageCodeTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gmd/LanguageCodeTest.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -25,12 +25,11 @@ import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBException;
 import org.opengis.metadata.Metadata;
 import org.apache.sis.xml.XML;
-import org.apache.sis.xml.Namespaces;
 import org.apache.sis.xml.MarshallerPool;
 import org.apache.sis.internal.jaxb.Schemas;
+import org.apache.sis.internal.jaxb.LegacyNamespaces;
 import org.apache.sis.test.XMLTestCase;
 import org.apache.sis.test.DependsOnMethod;
-import org.apache.sis.test.mock.MetadataMock;
 import org.junit.BeforeClass;
 import org.junit.AfterClass;
 import org.junit.Test;
@@ -41,9 +40,14 @@ import static org.apache.sis.internal.ut
 
 /**
  * Tests the XML marshaling of {@code Locale} when used for a language.
+ * The locale is marshalled as a character string. This format was used by ISO 19139:2007
+ * but is not used anymore in ISO 19115-3 (the newer version use {@code PT_Locale} instead).
+ *
+ * <p>This class also test indirectly the {@link org.apache.sis.xml} capability to map the legacy
+ * {@code "http://www.isotc211.org/2005/gmd"} namespace to {@code "http://standards.iso.org/…"}.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.4
+ * @version 1.0
  * @since   0.3
  * @module
  */
@@ -62,7 +66,7 @@ public final strictfp class LanguageCode
      * XML fragment using the {@code <gmd:LanguageCode>} construct with attributes.
      */
     private static final String LANGUAGE_CODE = "<gmd:LanguageCode" +
-            " codeList=\"" + Schemas.METADATA_ROOT + Schemas.CODELISTS_PATH + "#LanguageCode\"" +
+            " codeList=\"" + Schemas.METADATA_ROOT_LEGACY + Schemas.CODELISTS_PATH_LEGACY + "#LanguageCode\"" +
             " codeListValue=\"jpn\">Japanese</gmd:LanguageCode>";
 
     /**
@@ -74,6 +78,9 @@ public final strictfp class LanguageCode
      * Creates the XML (un)marshaller pool to be shared by all test methods.
      * The (un)marshallers locale and timezone will be set to fixed values.
      *
+     * <p>This test uses its own pool instead of {@link XMLTestCase#getMarshallerPool()} because it
+     * uses {@link MetadataMock} instead of {@link org.apache.sis.metadata.iso.DefaultMetadata}.</p>
+     *
      * @throws JAXBException if an error occurred while creating the pool.
      *
      * @see #disposeMarshallerPool()
@@ -111,8 +118,8 @@ public final strictfp class LanguageCode
      */
     private static String getMetadataXML(final String languageCode) {
         return "<gmd:MD_Metadata" +
-               " xmlns:gmd=\"" + Namespaces.GMD + '"' +
-               " xmlns:gco=\"" + Namespaces.GCO + "\">\n" +
+               " xmlns:gmd=\"" + LegacyNamespaces.GMD + '"' +
+               " xmlns:gco=\"" + LegacyNamespaces.GCO + "\">\n" +
                "  <gmd:language>\n" +
                "    " + languageCode + '\n' +
                "  </gmd:language>\n" +
@@ -121,17 +128,18 @@ public final strictfp class LanguageCode
 
     /**
      * Tests marshalling of {@code <gmd:LanguageCode>}.
-     * The result shall be as documented in {@link #testLanguageCode()}.
+     * The result shall be as documented in {@link #testMarshalLanguageCode()}.
      *
      * @throws JAXBException if an error occurs while marshalling the language.
      *
-     * @see #testMarshallCharacterString()
+     * @see #testMarshalCharacterString()
      */
     @Test
-    public void testMarshallLanguageCode() throws JAXBException {
+    public void testMarshalLanguageCode() throws JAXBException {
         final MetadataMock metadata = new MetadataMock(Locale.JAPANESE);
         final Marshaller marshaller = pool.acquireMarshaller();
         assertNull(marshaller.getProperty(XML.STRING_SUBSTITUTES));
+        marshaller.setProperty(XML.METADATA_VERSION, VERSION_2007);
         assertXmlEquals(getMetadataXML(LANGUAGE_CODE), marshal(marshaller, metadata), "xmlns:*");
         pool.recycle(marshaller);
     }
@@ -149,10 +157,10 @@ public final strictfp class LanguageCode
      *
      * @throws JAXBException if an error occurs while unmarshalling the language.
      *
-     * @see #testMarshallLanguageCode()
+     * @see #testMarshalLanguageCode()
      */
     @Test
-    public void testLanguageCode() throws JAXBException {
+    public void testUnmarshalLanguageCode() throws JAXBException {
         final Unmarshaller unmarshaller = pool.acquireUnmarshaller();
         final String xml = getMetadataXML(LANGUAGE_CODE);
         final Metadata metadata = (Metadata) unmarshal(unmarshaller, xml);
@@ -174,7 +182,7 @@ public final strictfp class LanguageCode
      * @throws JAXBException if an error occurs while unmarshalling the language.
      */
     @Test
-    @DependsOnMethod("testLanguageCode")
+    @DependsOnMethod("testMarshalLanguageCode")
     public void testLanguageCodeWithoutAttributes() throws JAXBException {
         final Unmarshaller unmarshaller = pool.acquireUnmarshaller();
         final String xml = getMetadataXML(LANGUAGE_CODE_WITHOUT_ATTRIBUTE);
@@ -185,16 +193,17 @@ public final strictfp class LanguageCode
 
     /**
      * Tests marshalling of {@code <gco:CharacterString>}, which require explicit marshaller configuration.
-     * The result shall be as documented in {@link #testCharacterString()}.
+     * The result shall be as documented in {@link #testUnmarshalCharacterString()}.
      *
      * @throws JAXBException if an error occurs while marshalling the language.
      *
-     * @see #testMarshallLanguageCode()
+     * @see #testMarshalLanguageCode()
      */
     @Test
-    public void testMarshallCharacterString() throws JAXBException {
+    public void testMarshalCharacterString() throws JAXBException {
         final MetadataMock metadata = new MetadataMock(Locale.JAPANESE);
         final Marshaller marshaller = pool.acquireMarshaller();
+        marshaller.setProperty(XML.METADATA_VERSION, VERSION_2007);
         marshaller.setProperty(XML.STRING_SUBSTITUTES, new String[] {"dummy","language","foo"});
         assertArrayEquals(new String[] {"language"}, (String[]) marshaller.getProperty(XML.STRING_SUBSTITUTES));
         assertXmlEquals(getMetadataXML(CHARACTER_STRING), marshal(marshaller, metadata), "xmlns:*");
@@ -216,7 +225,7 @@ public final strictfp class LanguageCode
      * @throws JAXBException if an error occurs while unmarshalling the language.
      */
     @Test
-    public void testCharacterString() throws JAXBException {
+    public void testUnmarshalCharacterString() throws JAXBException {
         final Unmarshaller unmarshaller = pool.acquireUnmarshaller();
         final String xml = getMetadataXML(CHARACTER_STRING);
         final Metadata metadata = (Metadata) unmarshal(unmarshaller, xml);

Modified: sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gml/MeasureTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gml/MeasureTest.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gml/MeasureTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gml/MeasureTest.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -61,7 +61,7 @@ public final strictfp class MeasureTest
         assertEquals(Units.METRE, measure.unit);
         assertEquals("urn:ogc:def:uom:EPSG::9001", measure.getUOM());
         measure.asXPointer = true;
-        assertEquals(Schemas.METADATA_ROOT + Schemas.UOM_PATH + "#xpointer(//*[@gml:id='m'])", measure.getUOM());
+        assertEquals(Schemas.METADATA_ROOT_LEGACY + Schemas.UOM_PATH + "#xpointer(//*[@gml:id='m'])", measure.getUOM());
 
         measure.unit = null;
         measure.asXPointer = false;
@@ -69,12 +69,12 @@ public final strictfp class MeasureTest
         assertEquals(Units.DEGREE, measure.unit);
         assertEquals("urn:ogc:def:uom:EPSG::9102", measure.getUOM());
         measure.asXPointer = true;
-        assertEquals(Schemas.METADATA_ROOT + Schemas.UOM_PATH + "#xpointer(//*[@gml:id='deg'])", measure.getUOM());
+        assertEquals(Schemas.METADATA_ROOT_LEGACY + Schemas.UOM_PATH + "#xpointer(//*[@gml:id='deg'])", measure.getUOM());
 
         measure.unit = null;
         measure.asXPointer = true;
         measure.setUOM("gmxUom.xml#kg");                        // Not really an existing unit in 'gmxUom'.
         assertEquals(Units.KILOGRAM, measure.unit);
-        assertEquals(Schemas.METADATA_ROOT + Schemas.UOM_PATH + "#xpointer(//*[@gml:id='kg'])", measure.getUOM());
+        assertEquals(Schemas.METADATA_ROOT_LEGACY + Schemas.UOM_PATH + "#xpointer(//*[@gml:id='kg'])", measure.getUOM());
     }
 }

Modified: sis/trunk/core/sis-utility/src/test/java/org/apache/sis/test/XMLComparator.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/test/java/org/apache/sis/test/XMLComparator.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/test/java/org/apache/sis/test/XMLComparator.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/test/java/org/apache/sis/test/XMLComparator.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -43,6 +43,7 @@ import org.w3c.dom.Text;
 import org.xml.sax.SAXException;
 import org.apache.sis.xml.Namespaces;
 import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.internal.jaxb.LegacyNamespaces;
 
 import static java.lang.StrictMath.*;
 import static org.opengis.test.Assert.*;
@@ -70,7 +71,7 @@ import static org.apache.sis.util.CharSe
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Guilhem Legal (Geomatys)
- * @version 0.4
+ * @version 1.0
  *
  * @see XMLTestCase
  * @see Assert#assertXmlEquals(Object, Object, String[])
@@ -91,11 +92,13 @@ public strictfp class XMLComparator {
         map.put("xmlns", "http://www.w3.org/2000/xmlns");           // No trailing slash.
         map.put("xlink", Namespaces.XLINK);
         map.put("xsi",   Namespaces.XSI);
-        map.put("gml",   Namespaces.GML);
-        map.put("gmd",   Namespaces.GMD);
-        map.put("gmx",   Namespaces.GMX);
-        map.put("gmi",   Namespaces.GMI);
         map.put("gco",   Namespaces.GCO);
+        map.put("mdb",   Namespaces.MDB);
+        map.put("srv",   Namespaces.SRV);
+        map.put("gml",   Namespaces.GML);
+        map.put("gmd",   LegacyNamespaces.GMD);
+        map.put("gmx",   LegacyNamespaces.GMX);
+        map.put("gmi",   LegacyNamespaces.GMI);
     }
 
     /**
@@ -316,7 +319,7 @@ public strictfp class XMLComparator {
             compareAttributes(expected, actual);
         }
         /*
-         * Check child nodes recursivly if it's not an attribut.
+         * Check child nodes recursivly if it's not an attribute.
          */
         if (expected.getNodeType() != Node.ATTRIBUTE_NODE) {
             compareChildren(expected, actual);
@@ -758,7 +761,7 @@ public strictfp class XMLComparator {
          */
         final String ns = node.getNamespaceURI();
         if (ns != null) {
-            buffer.append(ns).append(':');
+            buffer.append('{').append(ns).append('}');
         }
         buffer.append(node.getNodeName());
         boolean hasText = appendTextContent(buffer, node);

Modified: sis/trunk/core/sis-utility/src/test/java/org/apache/sis/test/XMLTestCase.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/test/java/org/apache/sis/test/XMLTestCase.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/test/java/org/apache/sis/test/XMLTestCase.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/test/java/org/apache/sis/test/XMLTestCase.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -31,7 +31,11 @@ import javax.xml.bind.Marshaller;
 import javax.xml.bind.Unmarshaller;
 import javax.xml.bind.JAXBException;
 import org.apache.sis.internal.jaxb.Context;
+import org.apache.sis.internal.jaxb.LegacyNamespaces;
+import org.apache.sis.internal.jaxb.Schemas;
 import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.Version;
+import org.apache.sis.xml.Namespaces;
 import org.apache.sis.xml.MarshallerPool;
 import org.apache.sis.xml.XML;
 import org.junit.After;
@@ -52,7 +56,8 @@ import static org.apache.sis.test.Assert
  * after each test for clearing the SIS internal {@link ThreadLocal} which was holding that context.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.7
+ * @author  Cullen Rombach (Image Matters)
+ * @version 1.0
  *
  * @see XMLComparator
  *
@@ -61,6 +66,12 @@ import static org.apache.sis.test.Assert
  */
 public abstract strictfp class XMLTestCase extends TestCase {
     /**
+     * Miscellaneous version constants used for ISO standards.
+     */
+    protected static final Version VERSION_2007 = LegacyNamespaces.VERSION_2007,
+                                   VERSION_2014 = LegacyNamespaces.VERSION_2014;
+
+    /**
      * The timezone used for the tests. We intentionally use a timezone different than UTC in order
      * to have an error of one or two hours if a code fails to take timezone offset in account.
      */
@@ -143,7 +154,7 @@ public abstract strictfp class XMLTestCa
      */
     protected final void createContext(final boolean marshal, final Locale locale, final String timezone) {
         context = new Context(marshal ? Context.MARSHALLING : 0, locale,
-                (timezone != null) ? TimeZone.getTimeZone(timezone) : null, null, null, null, null, null);
+                (timezone != null) ? TimeZone.getTimeZone(timezone) : null, null, null, null, null, null, null);
     }
 
     /**
@@ -198,11 +209,30 @@ public abstract strictfp class XMLTestCa
     }
 
     /**
+     * Marshals the given object and ensure that the result is equals to the content of the given file.
+     *
+     * @param  filename           the name of the XML file in the package of the final subclass of {@code this}.
+     * @param  object             the object to marshal.
+     * @param  metadataVersion    whether to marshal legacy 19139:2007 or newer ISO 19115-3 document. Can be {@code null}.
+     * @param  ignoredAttributes  the fully-qualified names of attributes to ignore
+     *                            (typically {@code "xmlns:*"} and {@code "xsi:schemaLocation"}).
+     * @throws JAXBException if an error occurred during marshalling.
+     *
+     * @since 1.0
+     */
+    protected final void assertMarshalEqualsFile(final String filename, final Object object,
+            final Version metadataVersion, final String... ignoredAttributes) throws JAXBException
+    {
+        assertXmlEquals(getResource(filename), marshal(object, metadataVersion), ignoredAttributes);
+    }
+
+    /**
      * Marshals the given object and ensure that the result is equals to the content of the given file,
      * within a tolerance threshold for numerical values.
      *
      * @param  filename           the name of the XML file in the package of the final subclass of {@code this}.
      * @param  object             the object to marshal.
+     * @param  metadataVersion    whether to marshal legacy 19139:2007 or newer ISO 19115-3 document. Can be {@code null}.
      * @param  tolerance          the tolerance threshold for comparison of numerical values.
      * @param  ignoredNodes       the fully-qualified names of the nodes to ignore, or {@code null} if none.
      * @param  ignoredAttributes  the fully-qualified names of attributes to ignore
@@ -211,16 +241,17 @@ public abstract strictfp class XMLTestCa
      *
      * @see #unmarshalFile(Class, String)
      *
-     * @since 0.7
+     * @since 1.0
      */
-    protected final void assertMarshalEqualsFile(final String filename, final Object object,
+    protected final void assertMarshalEqualsFile(final String filename, final Object object, final Version metadataVersion,
             final double tolerance, final String[] ignoredNodes, final String[] ignoredAttributes) throws JAXBException
     {
-        assertXmlEquals(getResource(filename), marshal(object), tolerance, ignoredNodes, ignoredAttributes);
+        assertXmlEquals(getResource(filename), marshal(object, metadataVersion), tolerance, ignoredNodes, ignoredAttributes);
     }
 
     /**
      * Marshals the given object using the {@linkplain #getMarshallerPool() test marshaller pool}.
+     * The default XML schema is used (usually the most recent one).
      *
      * @param  object  the object to marshal.
      * @return the marshalled object.
@@ -237,6 +268,26 @@ public abstract strictfp class XMLTestCa
     }
 
     /**
+     * Marshals the given object using the {@linkplain #getMarshallerPool() test marshaller pool}.
+     * The XML schema identified by the given version is used.
+     *
+     * @param  object           the object to marshal.
+     * @param  metadataVersion  whether to marshal legacy 19139:2007 or newer ISO 19115-3 document. Can be {@code null}.
+     * @return the marshalled object.
+     * @throws JAXBException if an error occurred while marshalling the object.
+     *
+     * @since 1.0
+     */
+    protected final String marshal(final Object object, final Version metadataVersion) throws JAXBException {
+        final MarshallerPool pool = getMarshallerPool();
+        final Marshaller marshaller = pool.acquireMarshaller();
+        marshaller.setProperty(XML.METADATA_VERSION, metadataVersion);
+        final String xml = marshal(marshaller, object);
+        pool.recycle(marshaller);
+        return xml;
+    }
+
+    /**
      * Marshals the given object using the given marshaler.
      *
      * @param  marshaller  the marshaller to use.
@@ -300,7 +351,7 @@ public abstract strictfp class XMLTestCa
     }
 
     /**
-     * Unmarshals the given XML using the given unmarshaler.
+     * Unmarshals the given XML using the given unmarshaller.
      *
      * @param  unmarshaller  the unmarshaller to use.
      * @param  xml           the XML representation of the object to unmarshal.
@@ -332,4 +383,56 @@ public abstract strictfp class XMLTestCa
             throw new AssertionError(e);
         }
     }
+
+    /**
+     * The string substitutions to perform for downgrading an ISO 19115-3 document to ISO 19139:2007.
+     * Values at even indices are strings to search, and values at odd indices are replacements.
+     */
+    private static final String[] TO_LEGACY_XML = {
+        Namespaces.CIT, LegacyNamespaces.GMD, "cit",  "gmd",
+        Namespaces.MCC, LegacyNamespaces.GMD, "mcc",  "gmd",
+        Namespaces.MRI, LegacyNamespaces.GMD, "mri",  "gmd",
+        Namespaces.GCO, LegacyNamespaces.GCO,      // "gco"
+        Namespaces.GCX, LegacyNamespaces.GMX, "gcx",  "gmx",
+        Schemas.METADATA_ROOT,  Schemas.METADATA_ROOT_LEGACY,           // For code lists
+        Schemas.CODELISTS_PATH, Schemas.CODELISTS_PATH_LEGACY
+    };
+
+    /**
+     * Performs a simple ISO 19115-3 to ISO 19139:2007 translations using only search-and-replaces.
+     * For example this method replaces {@code "cit"} prefix by {@code "gmd"} and the corresponding
+     * {@value Namespaces#CIT} namespace by {@value LegacyNamespaces#GMD}. However this method does
+     * not perform any more complex translations like attributes refactored in other classes.  If a
+     * more complex translation is required, the test case should provide the legacy XML verbatim
+     * in a separated string.
+     *
+     * @param  xml  an XML compliant with ISO 19115-3.
+     * @return an XML compliant with ISO 19139:2007.
+     *
+     * @since 1.0
+     */
+    protected static String toLegacyXML(final String xml) {
+        final StringBuilder buffer = new StringBuilder(xml);
+        for (int c=0; c < TO_LEGACY_XML.length;) {
+            final String toSearch  = TO_LEGACY_XML[c++];
+            final String replaceBy = TO_LEGACY_XML[c++];
+            final int length = toSearch.length();
+            int i = buffer.length();
+            while ((i = buffer.lastIndexOf(toSearch, i)) >= 0) {
+                /*
+                 * Following may throw a StringIndexOutOfBoundsException if 'toSearch' is located at the
+                 * beginning (i == 0) or end (end == buffer.length()) of the buffer. However those cases
+                 * should never happen in Apache SIS test cases since it would be invalid XML.
+                 */
+                if (!Character.isUnicodeIdentifierPart(buffer.codePointBefore(i))) {
+                    final int end = i + length;
+                    if (!Character.isUnicodeIdentifierPart(buffer.codePointAt(end))) {
+                        buffer.replace(i, end, replaceBy);
+                    }
+                }
+                i -= length;
+            }
+        }
+        return buffer.toString();
+    }
 }

Modified: sis/trunk/core/sis-utility/src/test/java/org/apache/sis/test/mock/package-info.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/test/java/org/apache/sis/test/mock/package-info.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/test/java/org/apache/sis/test/mock/package-info.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/test/java/org/apache/sis/test/mock/package-info.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -33,7 +33,6 @@
  */
 @XmlSchema(elementFormDefault = XmlNsForm.QUALIFIED, namespace = Namespaces.GML, xmlns = {
     @XmlNs(prefix = "gml", namespaceURI = Namespaces.GML),
-    @XmlNs(prefix = "gmd", namespaceURI = Namespaces.GMD),
     @XmlNs(prefix = "gco", namespaceURI = Namespaces.GCO)
 })
 @XmlAccessorType(XmlAccessType.NONE)

Modified: sis/trunk/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -150,6 +150,7 @@ import org.junit.BeforeClass;
     org.apache.sis.xml.ValueConverterTest.class,
     org.apache.sis.xml.OGCNamespacePrefixMapperTest.class,
     org.apache.sis.xml.MarshallerPoolTest.class,
+    org.apache.sis.xml.TransformingNamespacesTest.class,
     org.apache.sis.internal.jaxb.XmlUtilitiesTest.class,
     org.apache.sis.internal.jaxb.IdentifierMapAdapterTest.class,
     org.apache.sis.internal.jaxb.ModifiableIdentifierMapTest.class,

Modified: sis/trunk/core/sis-utility/src/test/java/org/apache/sis/util/iso/NameMarshallingTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/test/java/org/apache/sis/util/iso/NameMarshallingTest.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/test/java/org/apache/sis/util/iso/NameMarshallingTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/test/java/org/apache/sis/util/iso/NameMarshallingTest.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -25,9 +25,11 @@ import org.opengis.util.LocalName;
 import org.opengis.util.GenericName;
 import org.opengis.util.NameFactory;
 import org.opengis.util.NameSpace;
-import org.apache.sis.internal.system.DefaultFactories;
+import org.apache.sis.xml.XML;
 import org.apache.sis.xml.Namespaces;
 import org.apache.sis.xml.MarshallerPool;
+import org.apache.sis.internal.jaxb.LegacyNamespaces;
+import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.test.mock.IdentifiedObjectMock;
 import org.apache.sis.test.XMLTestCase;
 import org.apache.sis.test.DependsOn;
@@ -42,7 +44,8 @@ import static org.apache.sis.test.Assert
  * Tests the XML marshalling of generic names.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.5
+ * @author  Cullen Rombach (Image Matters)
+ * @version 1.0
  * @since   0.3
  * @module
  */
@@ -64,6 +67,7 @@ public final strictfp class NameMarshall
             pool = new MarshallerPool(JAXBContext.newInstance(IdentifiedObjectMock.class), null);
         }
         final Marshaller marshaller = pool.acquireMarshaller();
+        marshaller.setProperty(XML.METADATA_VERSION, VERSION_2007);
         final String xml = marshal(marshaller, new IdentifiedObjectMock(null, name));
         pool.recycle(marshaller);
         return xml;
@@ -72,7 +76,7 @@ public final strictfp class NameMarshall
     /**
      * Converse of {@link #marshal(GenericName)}.
      */
-    private GenericName unmarshall(final String xml) throws JAXBException {
+    private GenericName unmarshal(final String xml) throws JAXBException {
         final Unmarshaller unmarshaller = pool.acquireUnmarshaller();
         final Object value = unmarshal(unmarshaller, xml);
         pool.recycle(unmarshaller);
@@ -91,14 +95,14 @@ public final strictfp class NameMarshall
         assertEquals("An ordinary local name", name.toString());
         final String expected =
                 "<gml:IO_IdentifiedObject xmlns:gml=\"" + Namespaces.GML + '"' +
-                                        " xmlns:gco=\"" + Namespaces.GCO + "\">\n" +
+                                        " xmlns:gco=\"" + LegacyNamespaces.GCO + "\">\n" +
                 "  <gml:alias>\n" +
                 "    <gco:LocalName>An ordinary local name</gco:LocalName>\n" +
                 "  </gml:alias>\n" +
                 "</gml:IO_IdentifiedObject>\n";
         final String actual = marshal(name);
         assertXmlEquals(expected, actual, "xmlns:*");
-        assertEquals(name, unmarshall(expected));
+        assertEquals(name, unmarshal(expected));
     }
 
     /**
@@ -114,14 +118,14 @@ public final strictfp class NameMarshall
         assertEquals("A name with & and > and <.", name.toString());
         final String expected =
                 "<gml:IO_IdentifiedObject xmlns:gml=\"" + Namespaces.GML + '"' +
-                                        " xmlns:gco=\"" + Namespaces.GCO + "\">\n" +
+                                        " xmlns:gco=\"" + LegacyNamespaces.GCO + "\">\n" +
                 "  <gml:alias>\n" +
                 "    <gco:LocalName>A name with &amp; and &gt; and &lt;.</gco:LocalName>\n" +
                 "  </gml:alias>\n" +
                 "</gml:IO_IdentifiedObject>\n";
         final String actual = marshal(name);
         assertXmlEquals(expected, actual, "xmlns:*");
-        assertEquals(name, unmarshall(expected));
+        assertEquals(name, unmarshal(expected));
     }
 
     /**
@@ -138,14 +142,14 @@ public final strictfp class NameMarshall
         assertEquals("A name in a scope", name.toString());
         final String expected =
                 "<gml:IO_IdentifiedObject xmlns:gml=\"" + Namespaces.GML + '"' +
-                                        " xmlns:gco=\"" + Namespaces.GCO + "\">\n" +
+                                        " xmlns:gco=\"" + LegacyNamespaces.GCO + "\">\n" +
                 "  <gml:alias>\n" +
                 "    <gco:LocalName codeSpace=\"A code space\">A name in a scope</gco:LocalName>\n" +
                 "  </gml:alias>\n" +
                 "</gml:IO_IdentifiedObject>\n";
         final String actual = marshal(name);
         assertXmlEquals(expected, actual, "xmlns:*");
-        assertEquals(name, unmarshall(expected));
+        assertEquals(name, unmarshal(expected));
     }
 
     /**
@@ -160,7 +164,7 @@ public final strictfp class NameMarshall
         assertEquals("An other local name", name.toString());
         final String expected =
                 "<gml:IO_IdentifiedObject xmlns:gml=\"" + Namespaces.GML + '"' +
-                                        " xmlns:gco=\"" + Namespaces.GCO + "\">\n" +
+                                        " xmlns:gco=\"" + LegacyNamespaces.GCO + "\">\n" +
                 "  <gml:alias>\n" +
                 "    <gco:TypeName>\n" +
                 "      <gco:aName>\n" +
@@ -171,7 +175,7 @@ public final strictfp class NameMarshall
                 "</gml:IO_IdentifiedObject>\n";
         final String actual = marshal(name);
         assertXmlEquals(expected, actual, "xmlns:*");
-        assertEquals(name, unmarshall(expected));
+        assertEquals(name, unmarshal(expected));
     }
 
     /**
@@ -186,14 +190,14 @@ public final strictfp class NameMarshall
         assertEquals("myScope:myName", name.toString());
         final String expected =
                 "<gml:IO_IdentifiedObject xmlns:gml=\"" + Namespaces.GML + '"' +
-                                        " xmlns:gco=\"" + Namespaces.GCO + "\">\n" +
+                                        " xmlns:gco=\"" + LegacyNamespaces.GCO + "\">\n" +
                 "  <gml:alias>\n" +
                 "    <gco:ScopedName>myScope:myName</gco:ScopedName>\n" +
                 "  </gml:alias>\n" +
                 "</gml:IO_IdentifiedObject>\n";
         final String actual = marshal(name);
         assertXmlEquals(expected, actual, "xmlns:*");
-        assertEquals(name, unmarshall(expected));
+        assertEquals(name, unmarshal(expected));
     }
 
     /**

Modified: sis/trunk/core/sis-utility/src/test/java/org/apache/sis/xml/NamespacesTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/test/java/org/apache/sis/xml/NamespacesTest.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/test/java/org/apache/sis/xml/NamespacesTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/test/java/org/apache/sis/xml/NamespacesTest.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -26,7 +26,7 @@ import static org.junit.Assert.*;
  * Tests the {@link Namespaces} class.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.0
  * @since   0.8
  * @module
  */
@@ -36,6 +36,24 @@ public final strictfp class NamespacesTe
      */
     @Test
     public void testGetPreferredPrefix() {
-        assertEquals("gml", Namespaces.getPreferredPrefix("http://www.opengis.net/gml/3.2", null));
+        assertEquals("gml",  Namespaces.getPreferredPrefix("http://www.opengis.net/gml/3.2", null));
+        assertEquals("mdb",  Namespaces.getPreferredPrefix("http://standards.iso.org/iso/19115/-3/mdb/1.0", null));
+        assertEquals("gmi",  Namespaces.getPreferredPrefix("http://standards.iso.org/iso/19115/-2/gmi/1.0", null));
+        assertEquals("srv",  Namespaces.getPreferredPrefix("http://standards.iso.org/iso/19115/-3/srv/2.0", null));
+        assertEquals("srv1", Namespaces.getPreferredPrefix("http://www.isotc211.org/2005/srv", null));
+    }
+
+    /**
+     * Tests {@link Namespaces#guessForType(String)}. This method uses {@code assertSame(…)} instead than
+     * {@code assertEquals(…)} for verifying that {@link TransformingReader} invoked {@link String#intern()}.
+     */
+    @Test
+    public void testGuessForType() {
+        assertSame("CI_Citation",           Namespaces.CIT, Namespaces.guessForType("CI_Citation"));
+        assertSame("EX_Extent",             Namespaces.GEX, Namespaces.guessForType("EX_Extent"));
+        assertSame("MD_Metadata",           Namespaces.MDB, Namespaces.guessForType("MD_Metadata"));
+        assertSame("MD_DataIdentification", Namespaces.MRI, Namespaces.guessForType("MD_DataIdentification"));
+        assertSame("DS_InitiativeTypeCode", Namespaces.MRI, Namespaces.guessForType("DS_InitiativeTypeCode"));
+        assertSame("DCPList",               Namespaces.SRV, Namespaces.guessForType("DCPList"));
     }
 }

Modified: sis/trunk/core/sis-utility/src/test/java/org/apache/sis/xml/OGCNamespacePrefixMapperTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/test/java/org/apache/sis/xml/OGCNamespacePrefixMapperTest.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/test/java/org/apache/sis/xml/OGCNamespacePrefixMapperTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/test/java/org/apache/sis/xml/OGCNamespacePrefixMapperTest.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -34,7 +34,7 @@ import static org.junit.Assume.assumeTru
  *   <li>Invoke every public methods from the {@code NamespacePrefixMapper} class.
  *       If we failed to override an abstract method, we will get an {@link AbstractMethodError}.</li>
  *   <li>For specific methods like {@link OGCNamespacePrefixMapper#getPreferredPrefix(String, String,
- *       boolean)}, use some value which will prove us that the overriden method has been invoked.</li>
+ *       boolean)}, use some value which will prove us that the overridden method has been invoked.</li>
  * </ul>
  *
  * @author  Martin Desruisseaux (Geomatys)

Modified: sis/trunk/core/sis-utility/src/test/java/org/apache/sis/xml/ReferenceResolverMock.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/test/java/org/apache/sis/xml/ReferenceResolverMock.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/test/java/org/apache/sis/xml/ReferenceResolverMock.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/test/java/org/apache/sis/xml/ReferenceResolverMock.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -58,7 +58,7 @@ public final strictfp class ReferenceRes
      */
     public static Context begin(final boolean marshalling) {
         return new Context(marshalling ? Context.MARSHALLING : 0, null, null, null, null,
-                new ReferenceResolverMock(), null, null);
+                null, new ReferenceResolverMock(), null, null);
     }
 
     /**

Modified: sis/trunk/ide-project/NetBeans/build.xml
URL: http://svn.apache.org/viewvc/sis/trunk/ide-project/NetBeans/build.xml?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/ide-project/NetBeans/build.xml (original)
+++ sis/trunk/ide-project/NetBeans/build.xml Mon Feb 26 11:28:17 2018
@@ -71,6 +71,7 @@
       <!-- Other resources (properties files, SQL scripts, native libraries). -->
       <fileset dir="${project.root}/core/sis-utility/src/main/resources">
         <include name="**/*.properties"/>
+        <include name="**/*.lst"/>
       </fileset>
       <fileset dir="${project.root}/core/sis-metadata/src/main/resources">
         <include name="**/*.sql"/>

Modified: sis/trunk/pom.xml
URL: http://svn.apache.org/viewvc/sis/trunk/pom.xml?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/pom.xml (original)
+++ sis/trunk/pom.xml Mon Feb 26 11:28:17 2018
@@ -50,7 +50,7 @@ Apache SIS is a free software, Java lang
  SIS provides data structures for geographic data and associated metadata along with methods
  to manipulate those data structures. The SIS metadata module forms the base of the library
  and enables the creation of metadata objects which comply with the ISO 19115 metadata model
- and which can be read from or written to ISO 19139 compliant XML documents.
+ and which can be read from or written to ISO 19115-3 compliant XML documents.
  The SIS referencing module will enable the construction of geodetic data structures for
  geospatial referencing based on the ISO 19111 model such as axis, projection and coordinate
  reference system definitions, along with the associated operations which enable the mathematical
@@ -326,6 +326,15 @@ Apache SIS is a free software, Java lang
       </roles>
     </contributor>
     <contributor>
+      <name>Cullen Rombach</name>
+      <organization>Image Matters</organization>
+      <organizationUrl>http://www.imagemattersllc.com</organizationUrl>
+      <timezone>-5</timezone>
+      <roles>
+        <role>developer</role>
+      </roles>
+    </contributor>
+    <contributor>
       <name>Guilhem Legal</name>
       <email>guilhem.legal@geomatys.com</email>
       <organization>Geomatys</organization>

Modified: sis/trunk/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/DataIdentification.java
URL: http://svn.apache.org/viewvc/sis/trunk/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/DataIdentification.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/DataIdentification.java [UTF-8] (original)
+++ sis/trunk/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/DataIdentification.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -51,7 +51,7 @@ import org.apache.sis.metadata.iso.ident
  */
 @SuppressWarnings("CloneableClassWithoutClone")                 // ModifiableMetadata needs shallow clones.
 @XmlType(name = "FRA_DataIdentification_Type")
-@XmlRootElement(name ="FRA_DataIdentification")
+@XmlRootElement(name = "FRA_DataIdentification")
 public class DataIdentification extends DefaultDataIdentification {
     /**
      * For serialization purpose.

Modified: sis/trunk/profiles/sis-french-profile/src/test/java/org/apache/sis/internal/profile/fra/DataIdentificationTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/profiles/sis-french-profile/src/test/java/org/apache/sis/internal/profile/fra/DataIdentificationTest.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/profiles/sis-french-profile/src/test/java/org/apache/sis/internal/profile/fra/DataIdentificationTest.java [UTF-8] (original)
+++ sis/trunk/profiles/sis-french-profile/src/test/java/org/apache/sis/internal/profile/fra/DataIdentificationTest.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -17,8 +17,8 @@
 package org.apache.sis.internal.profile.fra;
 
 import javax.xml.bind.JAXBException;
-import org.apache.sis.xml.XML;
-import org.apache.sis.test.TestCase;
+import org.apache.sis.test.XMLTestCase;
+import org.junit.Ignore;
 import org.junit.Test;
 
 import static org.apache.sis.test.MetadataAssert.*;
@@ -29,17 +29,20 @@ import static org.apache.sis.test.TestUt
  * Tests (un)marshalling of French profile of data identification.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.4
+ * @version 1.0
  * @since   0.4
  * @module
  */
-public final strictfp class DataIdentificationTest extends TestCase {
+public final strictfp class DataIdentificationTest extends XMLTestCase {
     /**
      * Tests marshalling and unmarshalling of a XML fragment.
      *
      * @throws JAXBException if an error occurred during (un)marshalling.
+     *
+     * @see <a href="https://issues.apache.org/jira/browse/SIS-404">SIS-404</a>
      */
     @Test
+    @Ignore("Verify if we should discontinue this profile.")
     public void testMarshalling() throws JAXBException {
         final String xml =
                 "<fra:FRA_DataIdentification xmlns:gmd=\"http://www.isotc211.org/2005/gmd\"" +
@@ -61,12 +64,11 @@ public final strictfp class DataIdentifi
                 "  </fra:relatedCitation>\n" +
                 "</fra:FRA_DataIdentification>";
 
-        final Object id = XML.unmarshal(xml);
-        assertInstanceOf("Expected an AFNOR instance.", DataIdentification.class, id);
-        assertTitleEquals("citation", "Main documentation.", ((DataIdentification) id).getCitation());
-        assertTitleEquals("relatedCitations", "Related documentation.", getSingleton(((DataIdentification) id).getRelatedCitations()));
+        final DataIdentification id = unmarshal(DataIdentification.class, xml);
+        assertTitleEquals("citation", "Main documentation.", id.getCitation());
+        assertTitleEquals("relatedCitations", "Related documentation.", getSingleton(id.getRelatedCitations()));
 
-        final String actual = XML.marshal(id);
+        final String actual = marshal(id, VERSION_2007);
         assertXmlEquals(xml, actual, "xmlns:*");
     }
 }

Modified: sis/trunk/profiles/sis-french-profile/src/test/java/org/apache/sis/internal/profile/fra/DirectReferenceSystemTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/profiles/sis-french-profile/src/test/java/org/apache/sis/internal/profile/fra/DirectReferenceSystemTest.java?rev=1825355&r1=1825354&r2=1825355&view=diff
==============================================================================
--- sis/trunk/profiles/sis-french-profile/src/test/java/org/apache/sis/internal/profile/fra/DirectReferenceSystemTest.java [UTF-8] (original)
+++ sis/trunk/profiles/sis-french-profile/src/test/java/org/apache/sis/internal/profile/fra/DirectReferenceSystemTest.java [UTF-8] Mon Feb 26 11:28:17 2018
@@ -38,7 +38,7 @@ import static org.apache.sis.test.Assert
  *
  * @author  Cédric Briançon (Geomatys)
  * @author  Guilhem Legal (Geomatys)
- * @version 0.4
+ * @version 1.0
  * @since   0.5
  * @module
  */
@@ -76,7 +76,7 @@ public final strictfp class DirectRefere
      */
     @Test
     public void marshallingTest() throws JAXBException {
-        assertMarshalEqualsFile(XML_FILE, createMetadata(false), "xmlns:*", "xsi:schemaLocation");
+        assertMarshalEqualsFile(XML_FILE, createMetadata(false), VERSION_2007, "xmlns:*", "xsi:schemaLocation");
     }
 
     /**