sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1733385 [3/4] - in /sis/trunk: ./ application/sis-console/src/main/artifact/bin/ application/sis-console/src/main/artifact/conf/ application/sis-console/src/main/artifact/data/ application/sis-console/src/main/artifact/lib/ application/sis...
Date Wed, 02 Mar 2016 22:31:04 GMT
Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -16,6 +16,9 @@
  */
 package org.apache.sis.referencing.factory.sql;
 
+import java.util.Set;
+import java.util.Locale;
+import java.util.Collections;
 import java.sql.Connection;
 import java.io.BufferedReader;
 import java.io.LineNumberReader;
@@ -24,11 +27,12 @@ import java.io.InputStreamReader;
 import java.io.IOException;
 import java.io.FileNotFoundException;
 import java.nio.charset.Charset;
-import org.opengis.util.InternationalString;
-import org.apache.sis.internal.util.Constants;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.setup.InstallationResources;
 import org.apache.sis.internal.system.DataDirectory;
+import org.apache.sis.internal.util.CollectionsExt;
+import org.apache.sis.internal.util.Constants;
 
 // Branch-dependent imports
 import org.apache.sis.internal.jdk7.StandardCharsets;
@@ -37,28 +41,24 @@ import org.apache.sis.internal.jdk7.Path
 
 
 /**
- * Provides SQL scripts needed for creating a copy of the EPSG dataset. This interface allows Apache SIS
- * users to bundle the EPSG dataset in their own product for automatic installation when first needed.
- * That dataset is not included directly in Apache SIS for
- * <a href="https://issues.apache.org/jira/browse/LEGAL-183">licensing reasons</a>.
- *
- * <p>Implementations of this interface can be declared in the following file for automatic discovery
- * by {@link EPSGFactory} (see {@link java.util.ServiceLoader} for more information):</p>
+ * Provides SQL scripts needed for creating a local copy of a dataset. This class allows Apache SIS users
+ * to bundle the EPSG or other datasets in their own product for automatic installation when first needed.
+ * Implementations of this class can be declared in the following file for automatic discovery by {@link EPSGFactory}:
  *
  * {@preformat text
- *     META-INF/services/org.apache.sis.referencing.factory.sql.InstallationScriptProvider
+ *     META-INF/services/org.apache.sis.setup.InstallationResources
  * }
  *
- * <div class="section">How this interface is used</div>
- * The first time that an {@link EPSGDataAccess} needs to be instantiated, {@link EPSGFactory} verifies
- * if the EPSG database exists. If it does not, then:
+ * <div class="section">How this class is used</div>
+ * The first time that an {@link EPSGDataAccess} needs to be instantiated,
+ * {@link EPSGFactory} verifies if the EPSG database exists. If it does not, then:
  * <ol>
- *   <li>{@link EPSGFactory#install(Connection)} searches for the first {@code InstallationScriptProvider} instance
- *       for which {@link #getAuthority()} returns {@code "EPSG"}.</li>
+ *   <li>{@link EPSGFactory#install(Connection)} searches for the first instance of {@link InstallationResources}
+ *       (the parent of this class) for which the {@linkplain #getAuthorities() set of authorities} contains {@code "EPSG"}.</li>
  *   <li>The {@linkplain #getLicense license} may be shown to the user if the application allows that
  *       (for example when running as a {@linkplain org.apache.sis.console console application}).</li>
  *   <li>If the installation process is allowed to continue, it will iterate over all readers provided by
- *       {@link #getScriptContent(int)} and execute the SQL statements (not necessarily verbatim;
+ *       {@link #openScript(String, int)} and execute the SQL statements (not necessarily verbatim;
  *       the installation process may adapt to the target database).</li>
  * </ol>
  *
@@ -67,9 +67,9 @@ import org.apache.sis.internal.jdk7.Path
  * @version 0.7
  * @module
  */
-public abstract class InstallationScriptProvider {
+public abstract class InstallationScriptProvider extends InstallationResources {
     /**
-     * A sentinel value for the content of the script to execute before the official EPSG scripts.
+     * A sentinel value for the content of the script to execute before the SQL scripts provided by the authority.
      * This is an Apache SIS build-in script for constraining the values of some {@code VARCHAR} columns
      * to enumerations of values recognized by {@link EPSGDataAccess}. Those enumerations are not required
      * for proper working of {@link EPSGFactory}, but can improve data integrity.
@@ -77,73 +77,96 @@ public abstract class InstallationScript
     protected static final String PREPARE = "Prepare";
 
     /**
-     * A sentinel value for the content of the script to execute after the official EPSG scripts.
-     * This is an Apache SIS build-in script for creating indexes or performing any other manipulation
-     * that help SIS to use the EPSG dataset. Those indexes are not required for proper working of
-     * {@link EPSGFactory}, but can significantly improve performances.
+     * A sentinel value for the content of the script to execute after the SQL scripts provided by the authority.
+     * This is an Apache SIS build-in script for creating indexes or performing any other manipulation that help
+     * SIS to use the dataset. Those indexes are not required for proper working of {@link EPSGFactory},
+     * but can significantly improve performances.
      */
     protected static final String FINISH = "Finish";
 
     /**
+     * The authorities to be returned by {@link #getAuthorities()}.
+     */
+    private final Set<String> authorities;
+
+    /**
      * The names of the SQL scripts to read.
      */
-    private final String[] names;
+    private final String[] resources;
 
     /**
      * Creates a new provider which will read script files of the given names in that order.
      * The given names are often filenames, but not necessarily
      * (it is okay to use those names only as labels).
      *
-     * <p>For the EPSG dataset, the {@code names} argument is usually
-     * (potentially completed with EPSG dataset version and database software name):</p>
+     * <table class="sis">
+     *   <caption>Typical argument values</caption>
+     *   <tr>
+     *     <th>Authority</th>
+     *     <th class="sep">Argument values</th>
+     *   </tr><tr>
+     *     <td>{@code EPSG}</td>
+     *     <td class="sep"><code>
+     *       {{@linkplain #PREPARE}, "EPSG_Tables.sql", "EPSG_Data.sql", "EPSG_FKeys.sql", {@linkplain #FINISH}}
+     *     </code></td>
+     *   </tr>
+     * </table>
      *
-     * <blockquote><code>
-     *   {@linkplain #PREPARE}, "EPSG_Tables.sql", "EPSG_Data.sql", "EPSG_FKeys.sql", {@linkplain #FINISH}
-     * </code></blockquote>
+     * @param authority The authority (typically {@code "EPSG"}), or {@code null} if not available.
+     * @param resources Names of the SQL scripts to read.
      *
-     * @param names Names of the SQL scripts to read.
-     *
-     * @see #getScriptNames()
-     * @see #open(String)
+     * @see #getResourceNames(String)
+     * @see #openStream(String)
      */
-    protected InstallationScriptProvider(final String... names) {
-        ArgumentChecks.ensureNonNull("filenames", names);
-        this.names = names;
+    protected InstallationScriptProvider(final String authority, final String... resources) {
+        ArgumentChecks.ensureNonNull("resources", resources);
+        authorities = CollectionsExt.singletonOrEmpty(authority);
+        this.resources = resources;
     }
 
     /**
-     * Returns the identifier of the dataset installed by the SQL scripts, or {@code "unavailable"}
-     * if the SQL scripts are not available.
+     * Returns the identifiers of the dataset installed by the SQL scripts.
+     * The values currently recognized by SIS are:
+     *
+     * <ul>
+     *   <li>{@code "EPSG"} for the EPSG geodetic dataset.</li>
+     * </ul>
      *
-     * <p>Currently, the only allowed return values are {@code "EPSG"} and {@code "unavailable"}.
-     * This list may be expanded in future SIS versions if more authorities are supported.</p>
+     * The default implementation returns the authority given at construction time, or an empty set
+     * if that authority was {@code null}. An empty set means that the provider does not have all
+     * needed resources or does not have permission to distribute the installation scripts.
      *
-     * @return {@code "EPSG"} if the SQL scripts for installing the EPSG dataset are available,
-     *         or {@code "unavailable"} otherwise.
+     * @return Identifiers of SQL scripts that this instance can distribute.
      */
-    public abstract String getAuthority();
+    @Override
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
+    public Set<String> getAuthorities() {
+        return authorities;
+    }
 
     /**
-     * Returns the terms of use of the dataset, or {@code null} if presumed already accepted.
-     * The terms of use can be returned in either plain text or HTML.
-     *
-     * <p>For the EPSG dataset, this method should return the content of the
-     * <a href="http://www.epsg.org/TermsOfUse">http://www.epsg.org/TermsOfUse</a> page.</p>
-     *
-     * @param  mimeType Either {@code "text/plain"} or {@code "text/html"}.
-     * @return The terms of use in plain text or HTML, or {@code null} if the license is presumed already accepted.
-     * @throws IOException if an error occurred while reading the license file.
+     * Verifies that the given authority is one of the expected values.
      */
-    public abstract InternationalString getLicense(String mimeType) throws IOException;
+    private void verifyAuthority(final String authority) {
+        if (!authorities.contains(authority)) {
+            throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentValue_2, "authority", authority));
+        }
+    }
 
     /**
      * Returns the names of all SQL scripts to execute.
+     * This is a copy of the array of names given to the constructor.
      * Those names are often filenames, but not necessarily (they may be just labels).
      *
+     * @param  authority The value given at construction time (e.g. {@code "EPSG"}).
      * @return The names of all SQL scripts to execute.
+     * @throws IllegalArgumentException if the given {@code authority} argument is not the expected value.
+     * @throws IOException if fetching the script names required an I/O operation and that operation failed.
      */
-    public String[] getScriptNames() {
-        return names.clone();
+    @Override
+    public String[] getResourceNames(String authority) throws IOException {
+        verifyAuthority(authority);
+        return resources.clone();
     }
 
     /**
@@ -154,34 +177,40 @@ public abstract class InstallationScript
      * <div class="section">EPSG case</div>
      * In the EPSG dataset case, the iterator should return {@code BufferedReader} instances for the following files
      * (replace {@code <version>} by the EPSG version number and {@code <product>} by the target database) in same order.
-     * The first 3 files can be downloaded from <a href="http://www.epsg.org/">http://www.epsg.org/</a>.
-     * The fourth file is provided by Apache SIS.
+     * The first and last files are provided by Apache SIS.
+     * All other files can be downloaded from <a href="http://www.epsg.org/">http://www.epsg.org/</a>.
      *
      * <ol>
+     *   <li>Content of {@link #PREPARE}, an optional data definition script that define the enumerations expected by {@link EPSGDataAccess}.</li>
      *   <li>Content of {@code "EPSG_<version>.mdb_Tables_<product>.sql"}, a data definition script that create empty tables.</li>
      *   <li>Content of {@code "EPSG_<version>.mdb_Data_<product>.sql"}, a data manipulation script that populate the tables.</li>
      *   <li>Content of {@code "EPSG_<version>.mdb_FKeys_<product>.sql"}, a data definition script that create foreigner key constraints.</li>
-     *   <li>Content of {@link #POST_CREATE}, a data definition and data control script that create indexes and set permissions.</li>
+     *   <li>Content of {@link #FINISH}, an optional data definition and data control script that create indexes and set permissions.</li>
      * </ol>
      *
      * Implementors are free to return a different set of scripts with equivalent content.
      *
      * <div class="section">Default implementation</div>
-     * The default implementation invokes {@link #open(String)} – except for {@link #POST_CREATE} in which case
-     * an Apache SIS build-in script is used – and wrap the result in a {@link LineNumberReader}.
+     * The default implementation invokes {@link #openStream(String)} – except for {@link #PREPARE} and {@link #FINISH}
+     * in which case an Apache SIS build-in script is used – and wrap the result in a {@link LineNumberReader}.
+     * The file encoding is ISO LATIN-1 (the encoding used in the scripts distributed by EPSG).
      *
-     * @param  index Index of the SQL script to read, from 0 inclusive to
+     * @param  authority The value given at construction time (e.g. {@code "EPSG"}).
+     * @param  resource Index of the SQL script to read, from 0 inclusive to
      *         <code>{@linkplain #getScriptNames()}.length</code> exclusive.
      * @return A reader for the content of SQL script to execute.
+     * @throws IllegalArgumentException if the given {@code authority} argument is not the expected value.
+     * @throws IndexOutOfBoundsException if the given {@code resource} argument is out of bounds.
      * @throws IOException if an error occurred while creating the reader.
      */
-    public BufferedReader getScriptContent(final int index) throws IOException {
-        ArgumentChecks.ensureValidIndex(names.length, index);
-        final String authority = getAuthority();
+    @Override
+    public BufferedReader openScript(final String authority, final int resource) throws IOException {
+        verifyAuthority(authority);
+        ArgumentChecks.ensureValidIndex(resources.length, resource);
         if (!Constants.EPSG.equals(authority)) {
             throw new IllegalStateException(Errors.format(Errors.Keys.UnknownAuthority_1, authority));
         }
-        String name = names[index];
+        String name = resources[resource];
         final Charset charset;
         final InputStream in;
         if (PREPARE.equals(name) || FINISH.equals(name)) {
@@ -189,7 +218,7 @@ public abstract class InstallationScript
             in = InstallationScriptProvider.class.getResourceAsStream(name);
             charset = StandardCharsets.UTF_8;
         } else {
-            in = open(name);
+            in = openStream(name);
             charset = StandardCharsets.ISO_8859_1;
         }
         if (in == null) {
@@ -200,35 +229,37 @@ public abstract class InstallationScript
 
     /**
      * Opens the input stream for the SQL script of the given name.
-     * This method is invoked by the default implementation of {@link #getScriptContent(int)}
+     * This method is invoked by the default implementation of {@link #openScript(String, int)}
      * for all scripts except {@link #PREPARE} and {@link #FINISH}.
      *
-     * <div class="note"><b>Examples:</b>
-     * If this {@code InstallationScriptProvider} instance gets the SQL scripts from files in a well-known directory
+     * <div class="note"><b>Example 1:</b>
+     * if this {@code InstallationScriptProvider} instance gets the SQL scripts from files in a well-known directory
      * and if the names given at {@linkplain #InstallationScriptProvider(String...) construction time} are the
      * filenames in that directory, then this method can be implemented as below:
      *
      * {@preformat java
-     *    protected InputStream open(String name) throws IOException {
+     *    protected InputStream openStream(String name) throws IOException {
      *        return Files.newInputStream(directory.resolve(name));
      *    }
      * }
+     * </div>
      *
-     * If this {@code InstallationScriptProvider} instance rather gets the SQL scripts from resources bundled
+     * <div class="note"><b>Example 2:</b>
+     * if this {@code InstallationScriptProvider} instance rather gets the SQL scripts from resources bundled
      * in the same JAR files than and in the same package, then this method can be implemented as below:
      *
      * {@preformat java
-     *    protected InputStream open(String name) {
+     *    protected InputStream openStream(String name) {
      *        return MyClass.getResourceAsStream(name);
      *    }
      * }
      * </div>
      *
-     * @param  name Name of the script file to open.
+     * @param  name Name of the script file to open. Can be {@code null} if the resource is not found.
      * @return An input stream opened of the given script file.
      * @throws IOException if an error occurred while opening the file.
      */
-    protected abstract InputStream open(final String name) throws IOException;
+    protected abstract InputStream openStream(final String name) throws IOException;
 
 
 
@@ -257,12 +288,13 @@ public abstract class InstallationScript
         /**
          * Creates a default provider.
          */
-        public Default() {
-            super(PREPARE,
-                  "EPSG_Tables.sql",
-                  "EPSG_Data.sql",
-                  "EPSG_FKeys.sql",
-                  FINISH);
+        Default() {
+            super(Constants.EPSG,
+                    PREPARE,
+                    "EPSG_Tables.sql",
+                    "EPSG_Data.sql",
+                    "EPSG_FKeys.sql",
+                    FINISH);
 
             Path dir = DataDirectory.DATABASES.getDirectory();
             if (dir != null) {
@@ -282,8 +314,8 @@ public abstract class InstallationScript
          *         or {@code "unavailable"} otherwise.
          */
         @Override
-        public String getAuthority() {
-            return (directory != null) ? Constants.EPSG : "unavailable";
+        public Set<String> getAuthorities() {
+            return (directory != null) ? super.getAuthorities() : Collections.<String>emptySet();
         }
 
         /**
@@ -292,7 +324,7 @@ public abstract class InstallationScript
          * @return The terms of use in plain text or HTML, or {@code null} if the license is presumed already accepted.
          */
         @Override
-        public InternationalString getLicense(String mimeType) {
+        public String getLicense(String authority, Locale locale, String mimeType) {
             return null;
         }
 
@@ -304,7 +336,7 @@ public abstract class InstallationScript
          * @throws IOException if an error occurred while opening the file.
          */
         @Override
-        protected InputStream open(final String name) throws IOException {
+        protected InputStream openStream(final String name) throws IOException {
             return Files.newInputStream(directory.resolve(name));
         }
     }

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/package-info.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/package-info.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/package-info.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/package-info.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -17,20 +17,23 @@
 
 /**
  * Factories for geodetic objects defined in a SQL database, typically the EPSG dataset.
+ * This package provides support for all codes prefixed by {@code "EPSG:"} in the Apache SIS's
+ * <a href="http://sis.apache.org/book/tables/CoordinateReferenceSystems.html">list of authority codes</a>.
  * The main class in this package is {@link org.apache.sis.referencing.factory.sql.EPSGFactory},
  * which requires a {@link javax.sql.DataSource} providing connections to an EPSG database.
  *
  *
  * <div class="section">Connection to the database</div>
- * By default Apache SIS used Apache Derby (a.k.a. JavaDB), but the database can also be PostgreSQL or MS-Access.
- * The connection is obtained by the first of the following data sources which is found:
+ * By default Apache SIS uses Apache Derby (a.k.a. JavaDB in Oracle JDK),
+ * but the database can also be PostgreSQL or MS-Access.
+ * The database connection is obtained by the first of the following data sources which is found:
  *
- * <ol class="verbose">
+ * <ol>
  *   <li>If a {@linkplain javax.naming.InitialContext JNDI context} exists,
  *       the {@link javax.sql.DataSource} registered under the {@code "java:comp/env/jdbc/SpatialMetadata"} name.</li>
- *   <li>If the {@code SIS_DATA} {@linkplain System#getenv(String) environment variable} is defined,
+ *   <li>If the {@code SIS_DATA} {@linkplain java.lang.System#getenv(String) environment variable} is defined,
  *       a JDBC connection for the {@code "jdbc:derby:$SIS_DATA/Databases/SpatialMetadata"} URL.</li>
- *   <li>If the {@code "derby.system.home"} {@linkplain System#getProperty(String) property} is defined,
+ *   <li>If the {@code "derby.system.home"} {@linkplain java.lang.System#getProperty(String) property} is defined,
  *       a JDBC connection for the {@code "jdbc:derby:SpatialMetadata"} URL.</li>
  * </ol>
  *
@@ -64,10 +67,10 @@
  *
  * <ul>
  *   <li>Deprecated objects are not listed in the collection returned by the
- *       {@link org.apache.sis.referencing.factory.sql.EPSGDataAccess#getAuthorityCodes getAuthorityCodes(…)} method.</li>
+ *       {@link org.apache.sis.referencing.factory.sql.EPSGDataAccess#getAuthorityCodes EPSGDataAccess.getAuthorityCodes(…)} method.</li>
  *   <li>All method expecting an EPSG code in argument accept also the codes of deprecated objects.</li>
- *   <li>If a deprecated object is created by a call to {@code createFoo(…)}, a warning will be logged
- *       with a message proposing a replacement.</li>
+ *   <li>If a deprecated object is created by a call to {@code EPSGDataAccess.createFoo(…)},
+ *       a warning will be logged with a message proposing a replacement.</li>
  * </ul>
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -28,6 +28,7 @@ import org.opengis.util.InternationalStr
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.extent.Extent;
 import org.opengis.metadata.quality.PositionalAccuracy;
+import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.crs.GeneralDerivedCRS;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.operation.CoordinateOperation;
@@ -54,6 +55,7 @@ import org.apache.sis.internal.referenci
 import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.internal.referencing.WKTUtilities;
 import org.apache.sis.internal.metadata.WKTKeywords;
+import org.apache.sis.internal.metadata.MetadataUtilities;
 import org.apache.sis.internal.util.CollectionsExt;
 import org.apache.sis.internal.util.UnmodifiableArrayList;
 import org.apache.sis.internal.system.Semaphores;
@@ -795,10 +797,13 @@ check:      for (int isTarget=0; ; isTar
                         MathTransform tr1 = this.getMathTransform();
                         MathTransform tr2 = that.getMathTransform();
                         if (mode == ComparisonMode.ALLOW_VARIANT) try {
-                            final MathTransform swap = MathTransforms.linear(
+                            final MathTransform before = MathTransforms.linear(
                                     CoordinateSystems.swapAndScaleAxes(crs1.getCoordinateSystem(),
                                                                        crs2.getCoordinateSystem()));
-                            tr2 = MathTransforms.concatenate(swap, tr2);
+                            final MathTransform after = MathTransforms.linear(
+                                    CoordinateSystems.swapAndScaleAxes(that.getTargetCRS().getCoordinateSystem(),
+                                                                       this.getTargetCRS().getCoordinateSystem()));
+                            tr2 = MathTransforms.concatenate(before, tr2, after);
                         } catch (Exception e) {    // (ConversionException | RuntimeException) on the JDK7 branch.
                             Logging.recoverableException(Logging.getLogger(Loggers.COORDINATE_OPERATION),
                                     AbstractCoordinateOperation.class, "equals", e);
@@ -842,7 +847,14 @@ check:      for (int isTarget=0; ; isTar
         append(formatter, getSourceCRS(), WKTKeywords.SourceCRS);
         append(formatter, getTargetCRS(), WKTKeywords.TargetCRS);
         formatter.append(DefaultOperationMethod.castOrCopy(getMethod()));
-        final ParameterValueGroup parameters = getParameterValues();
+        ParameterValueGroup parameters;
+        try {
+            parameters = getParameterValues();
+        } catch (UnsupportedOperationException e) {
+            final IdentifiedObject c = getParameterDescriptors();
+            formatter.setInvalidWKT(c != null ? c : this, e);
+            parameters = null;
+        }
         if (parameters != null) {
             formatter.newLine();
             for (final GeneralParameterValue param : parameters.values()) {
@@ -923,7 +935,7 @@ check:      for (int isTarget=0; ; isTar
         if (sourceCRS == null) {
             sourceCRS = crs;
         } else {
-            ReferencingUtilities.propertyAlreadySet(AbstractCoordinateOperation.class, "setSource", "sourceCRS");
+            MetadataUtilities.propertyAlreadySet(AbstractCoordinateOperation.class, "setSource", "sourceCRS");
         }
     }
 
@@ -942,7 +954,7 @@ check:      for (int isTarget=0; ; isTar
         if (targetCRS == null) {
             targetCRS = crs;
         } else {
-            ReferencingUtilities.propertyAlreadySet(AbstractCoordinateOperation.class, "setTarget", "targetCRS");
+            MetadataUtilities.propertyAlreadySet(AbstractCoordinateOperation.class, "setTarget", "targetCRS");
         }
     }
 
@@ -963,7 +975,7 @@ check:      for (int isTarget=0; ; isTar
         if (coordinateOperationAccuracy == null) {
             coordinateOperationAccuracy = UnmodifiableArrayList.wrap(values);
         } else {
-            ReferencingUtilities.propertyAlreadySet(AbstractCoordinateOperation.class, "setAccuracy", "coordinateOperationAccuracy");
+            MetadataUtilities.propertyAlreadySet(AbstractCoordinateOperation.class, "setAccuracy", "coordinateOperationAccuracy");
         }
     }
 
@@ -976,7 +988,7 @@ check:      for (int isTarget=0; ; isTar
         if (operationVersion == null) {
             operationVersion = value;
         } else {
-            ReferencingUtilities.propertyAlreadySet(AbstractCoordinateOperation.class, "setOperationVersion", "operationVersion");
+            MetadataUtilities.propertyAlreadySet(AbstractCoordinateOperation.class, "setOperationVersion", "operationVersion");
         }
     }
 
@@ -989,7 +1001,7 @@ check:      for (int isTarget=0; ; isTar
         if (domainOfValidity == null) {
             domainOfValidity = value;
         } else {
-            ReferencingUtilities.propertyAlreadySet(AbstractCoordinateOperation.class, "setDomainOfValidity", "domainOfValidity");
+            MetadataUtilities.propertyAlreadySet(AbstractCoordinateOperation.class, "setDomainOfValidity", "domainOfValidity");
         }
     }
 
@@ -1002,7 +1014,7 @@ check:      for (int isTarget=0; ; isTar
         if (scope == null) {
             scope = value;
         } else {
-            ReferencingUtilities.propertyAlreadySet(AbstractCoordinateOperation.class, "setScope", "scope");
+            MetadataUtilities.propertyAlreadySet(AbstractCoordinateOperation.class, "setScope", "scope");
         }
     }
 }

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -46,6 +46,7 @@ import org.apache.sis.internal.jaxb.refe
 import org.apache.sis.internal.jaxb.Context;
 import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.internal.metadata.ReferencingServices;
+import org.apache.sis.internal.metadata.MetadataUtilities;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.util.collection.Containers;
@@ -422,7 +423,7 @@ class AbstractSingleOperation extends Ab
         if (method == null) {
             method = value;
         } else {
-            ReferencingUtilities.propertyAlreadySet(AbstractSingleOperation.class, "setMethod", "method");
+            MetadataUtilities.propertyAlreadySet(AbstractSingleOperation.class, "setMethod", "method");
         }
     }
 
@@ -497,7 +498,7 @@ class AbstractSingleOperation extends Ab
             CC_OperationMethod.store(values, parameters.values(), replacements);
             parameters = Parameters.unmodifiable(parameters);
         } else {
-            ReferencingUtilities.propertyAlreadySet(AbstractSingleOperation.class, "setParameters", "parameterValue");
+            MetadataUtilities.propertyAlreadySet(AbstractSingleOperation.class, "setParameters", "parameterValue");
         }
     }
 

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultOperationMethod.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultOperationMethod.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultOperationMethod.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultOperationMethod.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -48,7 +48,7 @@ import org.apache.sis.internal.metadata.
 import org.apache.sis.internal.jaxb.gco.StringAdapter;
 import org.apache.sis.internal.jaxb.referencing.CC_OperationMethod;
 import org.apache.sis.internal.referencing.NilReferencingObject;
-import org.apache.sis.internal.referencing.ReferencingUtilities;
+import org.apache.sis.internal.metadata.MetadataUtilities;
 import org.apache.sis.parameter.DefaultParameterDescriptorGroup;
 import org.apache.sis.parameter.Parameterized;
 import org.apache.sis.referencing.NamedIdentifier;
@@ -798,7 +798,7 @@ public class DefaultOperationMethod exte
         if (sourceDimensions == null) {
             sourceDimensions = value;
         } else {
-            ReferencingUtilities.propertyAlreadySet(DefaultOperationMethod.class, "setSourceDimensions", "sourceDimensions");
+            MetadataUtilities.propertyAlreadySet(DefaultOperationMethod.class, "setSourceDimensions", "sourceDimensions");
         }
     }
 
@@ -811,7 +811,7 @@ public class DefaultOperationMethod exte
         if (targetDimensions == null) {
             targetDimensions = value;
         } else {
-            ReferencingUtilities.propertyAlreadySet(DefaultOperationMethod.class, "setTargetDimensions", "targetDimensions");
+            MetadataUtilities.propertyAlreadySet(DefaultOperationMethod.class, "setTargetDimensions", "targetDimensions");
         }
     }
 
@@ -845,7 +845,7 @@ public class DefaultOperationMethod exte
             formula = (formula == null) ? new DefaultFormula(citation)
                       : new DefaultFormula(formula.getFormula(), citation);
         } else {
-            ReferencingUtilities.propertyAlreadySet(DefaultOperationMethod.class, "setFormulaCitation", "formulaCitation");
+            MetadataUtilities.propertyAlreadySet(DefaultOperationMethod.class, "setFormulaCitation", "formulaCitation");
         }
     }
 
@@ -857,7 +857,7 @@ public class DefaultOperationMethod exte
             formula = (formula == null) ? new DefaultFormula(description)
                       : new DefaultFormula(new SimpleInternationalString(description), formula.getCitation());
         } else {
-            ReferencingUtilities.propertyAlreadySet(DefaultOperationMethod.class, "setFormulaDescription", "formula");
+            MetadataUtilities.propertyAlreadySet(DefaultOperationMethod.class, "setFormulaDescription", "formula");
         }
     }
 
@@ -922,7 +922,7 @@ public class DefaultOperationMethod exte
         if (parameters == null) {
             parameters = CC_OperationMethod.group(super.getName(), descriptors);
         } else {
-            ReferencingUtilities.propertyAlreadySet(DefaultOperationMethod.class, "setDescriptors", "parameter");
+            MetadataUtilities.propertyAlreadySet(DefaultOperationMethod.class, "setDescriptors", "parameter");
         }
     }
 

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultPassThroughOperation.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultPassThroughOperation.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultPassThroughOperation.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultPassThroughOperation.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -29,6 +29,7 @@ import org.opengis.referencing.crs.Coord
 import org.opengis.referencing.crs.CompoundCRS;
 import org.apache.sis.referencing.operation.transform.PassThroughTransform;
 import org.apache.sis.internal.referencing.ReferencingUtilities;
+import org.apache.sis.internal.metadata.MetadataUtilities;
 import org.apache.sis.util.UnsupportedImplementationException;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ComparisonMode;
@@ -316,7 +317,7 @@ public class DefaultPassThroughOperation
         if (operation == null) {
             operation = op;
         } else {
-            ReferencingUtilities.propertyAlreadySet(DefaultPassThroughOperation.class, "setOperation", "coordOperation");
+            MetadataUtilities.propertyAlreadySet(DefaultPassThroughOperation.class, "setOperation", "coordOperation");
         }
     }
 

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -278,7 +278,7 @@ class ConcatenatedTransform extends Abst
             if (matrix2 != null) {
                 final Matrix matrix = Matrices.multiply(matrix2, matrix1);
                 if (Matrices.isIdentity(matrix, IDENTITY_TOLERANCE)) {
-                    return MathTransforms.identity(matrix.getNumRow() - 1);     // Returns a cached instance.
+                    return MathTransforms.identity(matrix.getNumRow() - 1);         // Returns a cached instance.
                 }
                 /*
                  * NOTE: It is quite tempting to "fix rounding errors" in the matrix before to create the transform.
@@ -322,7 +322,7 @@ class ConcatenatedTransform extends Abst
         if (areInverse(tr1, tr2) || areInverse(tr2, tr1)) {
             assert tr1.getSourceDimensions() == tr2.getTargetDimensions();
             assert tr1.getTargetDimensions() == tr2.getSourceDimensions();
-            return MathTransforms.identity(tr1.getSourceDimensions());      // Returns a cached instance.
+            return MathTransforms.identity(tr1.getSourceDimensions());          // Returns a cached instance.
         }
         /*
          * Gives a chance to AbstractMathTransform to returns an optimized object.
@@ -921,7 +921,7 @@ class ConcatenatedTransform extends Abst
      */
     @Override
     public boolean equals(final Object object, final ComparisonMode mode) {
-        if (object == this) { // Slight optimization
+        if (object == this) {                                                   // Slight optimization
             return true;
         }
         /*

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ReferencingUtilitiesTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ReferencingUtilitiesTest.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ReferencingUtilitiesTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ReferencingUtilitiesTest.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -22,9 +22,9 @@ import org.opengis.referencing.cs.*;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.datum.PrimeMeridian;
+import org.opengis.referencing.IdentifiedObject;
 import org.apache.sis.referencing.datum.HardCodedDatum;
 import org.apache.sis.referencing.crs.HardCodedCRS;
-import org.apache.sis.internal.metadata.WKTKeywords;
 import org.apache.sis.util.Utilities;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
@@ -38,7 +38,7 @@ import static org.apache.sis.internal.re
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.5 (derived from 0.4)
- * @version 0.6
+ * @version 0.7
  * @module
  */
 public final strictfp class ReferencingUtilitiesTest extends TestCase {
@@ -84,8 +84,21 @@ public final strictfp class ReferencingU
     }
 
     /**
+     * Tests {@link ReferencingUtilities#getPropertiesForModifiedCRS(IdentifiedObject, String...)}.
+     *
+     * @since 0.7
+     */
+    @Test
+    public void testGetPropertiesForModifiedCRS() {
+        assertEquals("WGS 84", getPropertiesForModifiedCRS(HardCodedCRS.WGS84_3D).get(IdentifiedObject.NAME_KEY));
+        assertEquals("WGS 84", getPropertiesForModifiedCRS(HardCodedCRS.GEOID_4D).get(IdentifiedObject.NAME_KEY));
+    }
+
+    /**
      * Tests {@link ReferencingUtilities#toPropertyName(Class, Class)}.
      *
+     * @see WKTUtilitiesTest#testToType()
+     *
      * @since 0.6
      */
     @Test
@@ -102,22 +115,4 @@ public final strictfp class ReferencingU
         assertEquals("timeCS",           toPropertyName(CoordinateSystem.class, TimeCS          .class).toString());
         assertEquals("verticalCS",       toPropertyName(CoordinateSystem.class, VerticalCS      .class).toString());
     }
-
-    /**
-     * Tests {@link ReferencingUtilities#toWKTType(Class, Class)}.
-     */
-    @Test
-    public void testType() {
-        assertNull  (                         toWKTType(CoordinateSystem.class, CoordinateSystem.class));
-        assertEquals(WKTKeywords.affine,      toWKTType(CoordinateSystem.class, AffineCS        .class));
-        assertEquals(WKTKeywords.Cartesian,   toWKTType(CoordinateSystem.class, CartesianCS     .class));
-        assertEquals(WKTKeywords.cylindrical, toWKTType(CoordinateSystem.class, CylindricalCS   .class));
-        assertEquals(WKTKeywords.ellipsoidal, toWKTType(CoordinateSystem.class, EllipsoidalCS   .class));
-        assertEquals(WKTKeywords.linear,      toWKTType(CoordinateSystem.class, LinearCS        .class));
-//      assertEquals(WKTKeywords.parametric,  toWKTType(CoordinateSystem.class, ParametricCS    .class));
-        assertEquals(WKTKeywords.polar,       toWKTType(CoordinateSystem.class, PolarCS         .class));
-        assertEquals(WKTKeywords.spherical,   toWKTType(CoordinateSystem.class, SphericalCS     .class));
-        assertEquals(WKTKeywords.temporal,    toWKTType(CoordinateSystem.class, TimeCS          .class));
-        assertEquals(WKTKeywords.vertical,    toWKTType(CoordinateSystem.class, VerticalCS      .class));
-    }
 }

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ServicesForMetadataTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ServicesForMetadataTest.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ServicesForMetadataTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ServicesForMetadataTest.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -16,17 +16,26 @@
  */
 package org.apache.sis.internal.referencing;
 
+import java.util.Map;
+import java.util.Collections;
 import org.opengis.geometry.Envelope;
 import org.opengis.metadata.extent.GeographicBoundingBox;
 import org.opengis.metadata.extent.VerticalExtent;
+import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.crs.GeographicCRS;
+import org.opengis.referencing.crs.SingleCRS;
 import org.opengis.referencing.operation.TransformException;
+import org.opengis.util.FactoryException;
+import org.apache.sis.internal.metadata.ReferencingServices;
 import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
 import org.apache.sis.metadata.iso.extent.DefaultVerticalExtent;
 import org.apache.sis.metadata.iso.extent.DefaultSpatialTemporalExtent;
 import org.apache.sis.geometry.GeneralEnvelope;
+import org.apache.sis.referencing.CRS;
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.referencing.crs.HardCodedCRS;
+import org.apache.sis.referencing.factory.GeodeticObjectFactory;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
@@ -41,7 +50,7 @@ import static org.apache.sis.test.TestUt
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.5
- * @version 0.5
+ * @version 0.7
  * @module
  */
 @DependsOn({
@@ -154,4 +163,54 @@ public final strictfp class ServicesForM
         verifySpatialExtent((GeographicBoundingBox) getSingleton(extent.getSpatialExtent()));
         verifyVerticalExtent(CommonCRS.Vertical.MEAN_SEA_LEVEL, extent.getVerticalExtent());
     }
+
+    /**
+     * Tests {@link ServicesForMetadata#createCompoundCRS ReferencingUtilities.createCompoundCRS(…)}.
+     *
+     * @throws FactoryException if a CRS can not be created.
+     *
+     * @see <a href="https://issues.apache.org/jira/browse/SIS-303">SIS-303</a>
+     *
+     * @since 0.7
+     */
+    @Test
+    public void testCreateCompoundCRS() throws FactoryException {
+        final ReferencingServices services = ServicesForMetadata.getInstance();
+        final GeodeticObjectFactory factory = new GeodeticObjectFactory();
+        final Map<String,String> properties = Collections.singletonMap(CoordinateReferenceSystem.NAME_KEY, "WGS 84 (4D)");
+        /*
+         * createCompoundCRS(…) should not combine GeographicCRS with non-ellipsoidal height.
+         */
+        CoordinateReferenceSystem compound = services.createCompoundCRS(factory, factory, properties,
+                HardCodedCRS.WGS84, HardCodedCRS.GRAVITY_RELATED_HEIGHT, HardCodedCRS.TIME);
+        assertArrayEqualsIgnoreMetadata(new SingleCRS[] {HardCodedCRS.WGS84, HardCodedCRS.GRAVITY_RELATED_HEIGHT, HardCodedCRS.TIME},
+                CRS.getSingleComponents(compound).toArray());
+        /*
+         * createCompoundCRS(…) should combine GeographicCRS with ellipsoidal height.
+         */
+        compound = services.createCompoundCRS(factory, factory, properties,
+                HardCodedCRS.WGS84, HardCodedCRS.ELLIPSOIDAL_HEIGHT);
+        assertArrayEqualsIgnoreMetadata(new SingleCRS[] {HardCodedCRS.WGS84_3D},
+                CRS.getSingleComponents(compound).toArray());
+        /*
+         * createCompoundCRS(…) should combine GeographicCRS with ellipsoidal height and keep time.
+         */
+        compound = services.createCompoundCRS(factory, factory, properties,
+                HardCodedCRS.WGS84, HardCodedCRS.ELLIPSOIDAL_HEIGHT, HardCodedCRS.TIME);
+        assertArrayEqualsIgnoreMetadata(new SingleCRS[] {HardCodedCRS.WGS84_3D, HardCodedCRS.TIME},
+                CRS.getSingleComponents(compound).toArray());
+        /*
+         * Non-standard feature: accept (VerticalCRS + GeodeticCRS) order.
+         * The test below use the reverse order for all axes compared to the previous test.
+         */
+        compound = services.createCompoundCRS(factory, factory, properties,
+                HardCodedCRS.TIME, HardCodedCRS.ELLIPSOIDAL_HEIGHT, HardCodedCRS.WGS84_φλ);
+        final Object[] components = CRS.getSingleComponents(compound).toArray();
+        assertEquals(2, components.length);
+        assertEqualsIgnoreMetadata(HardCodedCRS.TIME, components[0]);
+        assertInstanceOf("Shall be a three-dimensional geographic CRS.", GeographicCRS.class, components[1]);
+        assertAxisDirectionsEqual("Shall be a three-dimensional geographic CRS.",
+                ((CoordinateReferenceSystem) components[1]).getCoordinateSystem(),
+                AxisDirection.UP, AxisDirection.NORTH, AxisDirection.EAST);
+    }
 }

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -1000,6 +1000,40 @@ public final strictfp class GeodeticObje
     }
 
     /**
+     * Tests the parsing of a compound CRS from a WKT 1 string with ellipsoidal height and its conversion
+     * to a three-dimensional geographic CRS.
+     *
+     * @throws ParseException if the parsing failed.
+     *
+     * @see <a href="https://issues.apache.org/jira/browse/SIS-317">SIS-317</a>
+     *
+     * @since 0.7
+     */
+    @Test
+    @DependsOnMethod("testCompoundCRS")
+    public void testCompoundWKT1() throws ParseException {
+        final GeographicCRS crs = parse(GeographicCRS.class,
+                "COMPD_CS[“WGS 84 (3D)”,\n" +
+                "  GEOGCS[“WGS 84”,\n" +
+                "    DATUM[“World Geodetic System 1984”,\n" +
+                "      SPHEROID[“WGS84”, 6378137.0, 298.257223563]],\n" +
+                "      PRIMEM[“Greenwich”, 0.0],\n" +
+                "    UNIT[“degree”, 0.017453292519943295],\n" +
+                "    AXIS[“Longitude”, EAST],\n" +
+                "    AXIS[“Latitude”, NORTH]],\n" +
+                "  VERT_CS[“Ellipsoidal height”,\n" +
+                "    VERT_DATUM[“Ellipsoid”, 2002],\n" +
+                "    UNIT[“metre”, 1],\n" +
+                "    AXIS[“Ellipsoidal height”, UP]]]");
+
+        final CoordinateSystem cs = crs.getCoordinateSystem();
+        assertEquals("dimension", 3, cs.getDimension());
+        assertLongitudeAxisEquals(cs.getAxis(0));
+        assertLatitudeAxisEquals (cs.getAxis(1));
+        assertUnboundedAxisEquals("Ellipsoidal height", "h", AxisDirection.UP, SI.METRE, cs.getAxis(2));
+    }
+
+    /**
      * Tests the production of a warning messages when the WKT contains unknown elements.
      *
      * @throws ParseException if the parsing failed.

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/parameter/DefaultParameterDescriptorTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/parameter/DefaultParameterDescriptorTest.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/parameter/DefaultParameterDescriptorTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/parameter/DefaultParameterDescriptorTest.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -28,6 +28,7 @@ import org.apache.sis.measure.Measuremen
 import org.apache.sis.metadata.iso.ImmutableIdentifier;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.internal.util.Constants;
+import org.apache.sis.io.wkt.Convention;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
@@ -42,7 +43,7 @@ import static org.apache.sis.test.Metada
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.6
+ * @version 0.7
  * @module
  */
 @DependsOn(org.apache.sis.referencing.AbstractIdentifiedObjectTest.class)
@@ -314,7 +315,7 @@ public final strictfp class DefaultParam
         final DefaultParameterDescriptor<Double> descriptor = create("Real number", 4, 8, 5, SI.METRE);
         assertWktEquals("PARAMETER[“Integer param”, 5]", create("Integer param", 4, 8, 5));
         assertWktEquals("PARAMETER[“Real number”, 5.0, LENGTHUNIT[“metre”, 1]]", descriptor);
-        assertEquals("Parameter[\"Real number\", 5.0, Unit[\"metre\", 1]]", descriptor.toString());
+        assertWktEquals(Convention.WKT2_SIMPLIFIED, "Parameter[“Real number”, 5.0, Unit[“metre”, 1]]", descriptor);
     }
 
     /**

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/AbstractReferenceSystemTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/AbstractReferenceSystemTest.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/AbstractReferenceSystemTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/AbstractReferenceSystemTest.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -108,9 +108,8 @@ public final strictfp class AbstractRefe
                 new DefaultTemporalExtent()))); // TODO: needs sis-temporal module for testing that one.
         final AbstractReferenceSystem object = new AbstractReferenceSystem(properties);
 
-        assertEquals(
-                "ReferenceSystem[\"My “object”.\", AUTHORITY[\"EPSG\", \"4326\"]]",
-                object.toString(Convention.WKT1));
+        assertTrue(object.toString(Convention.WKT1).startsWith(
+                "ReferenceSystem[\"My “object”.\", AUTHORITY[\"EPSG\", \"4326\"]]"));
 
         assertWktEquals(Convention.WKT1,
                 "ReferenceSystem[“My \"object\".”, AUTHORITY[“EPSG”, “4326”]]",

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/IdentifiedObjectsTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/IdentifiedObjectsTest.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/IdentifiedObjectsTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/IdentifiedObjectsTest.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -59,6 +59,7 @@ public final strictfp class IdentifiedOb
         assertFalse(isHeuristicMatchForName(object, "testmyCode"));
         assertFalse(isHeuristicMatchForName(object, "other:myCode"));
         assertFalse(isHeuristicMatchForName(object, "test"));
+        assertFalse(isHeuristicMatchForName(null,   "myCode"));
 
         // Test the alias.
         assertTrue (isHeuristicMatchForName(object, "myName"));

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultGeographicCRSTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultGeographicCRSTest.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultGeographicCRSTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultGeographicCRSTest.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -38,11 +38,12 @@ import static org.apache.sis.test.TestUt
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.6
+ * @version 0.7
  * @module
  */
 @DependsOn({
-    DefaultGeodeticCRSTest.class
+    DefaultGeodeticCRSTest.class,
+    DefaultVerticalCRSTest.class
 })
 public final strictfp class DefaultGeographicCRSTest extends TestCase {
     /**
@@ -166,6 +167,33 @@ public final strictfp class DefaultGeogr
     }
 
     /**
+     * Tests WKT 2 formatting of a three-dimensional CRS.
+     *
+     * <p>This CRS used in this test is equivalent to {@code EPSG:4979} except for axis order,
+     * since EPSG puts latitude before longitude.</p>
+     *
+     * @see #testWKT1_For3D()
+     *
+     * @since 0.7
+     */
+    @Test
+    @DependsOnMethod("testWKT2")
+    public void testWKT2_For3D() {
+        assertWktEquals(Convention.WKT2,
+                "GEODCRS[“WGS 84 (3D)”,\n" +
+                "  DATUM[“World Geodetic System 1984”,\n" +
+                "    ELLIPSOID[“WGS84”, 6378137.0, 298.257223563, LENGTHUNIT[“metre”, 1]]],\n" +
+                "    PRIMEM[“Greenwich”, 0.0, ANGLEUNIT[“degree”, 0.017453292519943295]],\n" +
+                "  CS[ellipsoidal, 3],\n" +
+                "    AXIS[“Longitude (L)”, east, ORDER[1], ANGLEUNIT[“degree”, 0.017453292519943295]],\n" +
+                "    AXIS[“Latitude (B)”, north, ORDER[2], ANGLEUNIT[“degree”, 0.017453292519943295]],\n" +
+                "    AXIS[“Ellipsoidal height (h)”, up, ORDER[3], LENGTHUNIT[“metre”, 1]],\n" +
+                "  AREA[“World”],\n" +
+                "  BBOX[-90.00, -180.00, 90.00, 180.00]]",
+                HardCodedCRS.WGS84_3D);
+    }
+
+    /**
      * Tests WKT 2 simplified formatting.
      */
     @Test
@@ -207,7 +235,7 @@ public final strictfp class DefaultGeogr
     }
 
     /**
-     * Tests WKT 2 formatting on a CRS using a prime meridian other than Greenwich.
+     * Tests WKT 2 formatting of a CRS using a prime meridian other than Greenwich.
      *
      * <p>This CRS used in this test is equivalent to {@code EPSG:4807} except for axis order,
      * since EPSG defines (<var>latitude</var>, <var>longitude</var>) in grades.</p>
@@ -265,4 +293,34 @@ public final strictfp class DefaultGeogr
                 "  AXIS[“Latitude”, NORTH]]",
                 HardCodedCRS.NTF);
     }
+
+    /**
+     * Tests WKT 1 formatting of a three-dimensional CRS. Such CRS can not be represented directly in WKT 1 format.
+     * Consequently, the formatter will need to split the three-dimensional geographic CRS into a two-dimensional
+     * geographic CRS followed by an ellipsoidal height. Such construction is illegal according ISO 19111, so this
+     * split shall be done on-the-fly only for formatting purpose.
+     *
+     * @see #testWKT2_For3D()
+     * @see <a href="https://issues.apache.org/jira/browse/SIS-317">SIS-317</a>
+     *
+     * @since 0.7
+     */
+    @Test
+    @DependsOnMethod("testWKT1")
+    public void testWKT1_For3D() {
+        assertWktEquals(Convention.WKT1,
+                "COMPD_CS[“WGS 84 (3D)”,\n" +
+                "  GEOGCS[“WGS 84”,\n" +
+                "    DATUM[“World Geodetic System 1984”,\n" +
+                "      SPHEROID[“WGS84”, 6378137.0, 298.257223563]],\n" +
+                "      PRIMEM[“Greenwich”, 0.0],\n" +
+                "    UNIT[“degree”, 0.017453292519943295],\n" +
+                "    AXIS[“Longitude”, EAST],\n" +
+                "    AXIS[“Latitude”, NORTH]],\n" +
+                "  VERT_CS[“Ellipsoidal height”,\n" +
+                "    VERT_DATUM[“Ellipsoid”, 2002],\n" +
+                "    UNIT[“metre”, 1],\n" +
+                "    AXIS[“Ellipsoidal height”, UP]]]",
+                HardCodedCRS.WGS84_3D);
+    }
 }

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultGeodeticDatumTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultGeodeticDatumTest.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultGeodeticDatumTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultGeodeticDatumTest.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -45,13 +45,13 @@ import static org.apache.sis.referencing
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.7
  * @module
  */
 @DependsOn({
-  DefaultPrimeMeridianTest.class,
-  DefaultEllipsoidTest.class,
-  BursaWolfParametersTest.class
+    DefaultPrimeMeridianTest.class,
+    DefaultEllipsoidTest.class,
+    BursaWolfParametersTest.class
 })
 public final strictfp class DefaultGeodeticDatumTest extends XMLTestCase {
     /**
@@ -104,13 +104,21 @@ public final strictfp class DefaultGeode
      */
     @Test
     public void testIsHeuristicMatchForName() {
-        final DefaultGeodeticDatum datum = new DefaultGeodeticDatum(GeodeticDatumMock.WGS84);
+        DefaultGeodeticDatum datum = new DefaultGeodeticDatum(GeodeticDatumMock.WGS84);
         assertFalse(datum.isHeuristicMatchForName("WGS72"));
         assertTrue (datum.isHeuristicMatchForName("WGS84"));
         assertTrue (datum.isHeuristicMatchForName("WGS 84"));
         assertTrue (datum.isHeuristicMatchForName("WGS_84"));
         assertTrue (datum.isHeuristicMatchForName("D_WGS_84"));
         assertFalse(datum.isHeuristicMatchForName("E_WGS_84"));
+
+        datum = HardCodedDatum.NTF;
+        assertFalse(datum.isHeuristicMatchForName("WGS84"));
+        assertTrue (datum.isHeuristicMatchForName("Nouvelle Triangulation Française"));
+        assertTrue (datum.isHeuristicMatchForName("Nouvelle Triangulation Francaise"));
+        assertTrue (datum.isHeuristicMatchForName("Nouvelle Triangulation Française (Paris)"));
+        assertTrue (datum.isHeuristicMatchForName("Nouvelle Triangulation Francaise (Paris)"));
+        assertFalse(datum.isHeuristicMatchForName("Nouvelle Triangulation Francaise (Greenwich)"));
     }
 
     /**

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -31,6 +31,7 @@ import org.opengis.referencing.crs.Geogr
 import org.opengis.referencing.crs.ProjectedCRS;
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.internal.system.Loggers;
+import org.apache.sis.internal.util.Constants;
 import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.Utilities;
 
@@ -113,7 +114,7 @@ public final strictfp class EPSGInstalle
      */
     private static InstallationScriptProvider getScripts() {
         final InstallationScriptProvider scripts = new InstallationScriptProvider.Default();
-        assumeTrue(scripts.getAuthority().equals("EPSG"));
+        assumeTrue(scripts.getAuthorities().contains(Constants.EPSG));
         return scripts;
     }
 

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/integration/ConsistencyTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/integration/ConsistencyTest.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/integration/ConsistencyTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/integration/ConsistencyTest.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -17,23 +17,25 @@
 package org.apache.sis.test.integration;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
-import java.util.Locale;
 import java.util.Set;
-import java.util.TimeZone;
 import java.text.ParseException;
+import org.opengis.metadata.Identifier;
 import org.opengis.util.FactoryException;
 import org.opengis.util.NoSuchIdentifierException;
-import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.apache.sis.referencing.factory.FactoryDataException;
+import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.referencing.CRS;
 import org.apache.sis.io.wkt.Convention;
 import org.apache.sis.io.wkt.Warnings;
 import org.apache.sis.io.wkt.WKTFormat;
 import org.apache.sis.io.TableAppender;
 import org.apache.sis.io.wkt.UnformattableObjectException;
+import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.Utilities;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
@@ -66,6 +68,15 @@ public final strictfp class ConsistencyT
     ));
 
     /**
+     * Codes to exclude from the {@link #lookup(CoordinateReferenceSystem, CoordinateReferenceSystem)} test.
+     * The reason why those tests are excluded now is related to the way JSR-275 parse units. We may resolve
+     * those issues when we will replace JSR-275 by another library.
+     */
+    private static final Set<String> LOOKUP_EXCLUDES = Collections.singleton(
+            "EPSG:5754"         // Poolbeg height. Uses British foot (1936).
+    );
+
+    /**
      * Verifies the WKT consistency of all CRS instances.
      *
      * @throws FactoryException if an error other than "unsupported operation method" occurred.
@@ -73,10 +84,14 @@ public final strictfp class ConsistencyT
     @Test
     public void testCoordinateReferenceSystems() throws FactoryException {
         assumeTrue(RUN_EXTENSIVE_TESTS);
-        final WKTFormat v1 = new WKTFormat(Locale.US, TimeZone.getTimeZone("UTC"));
-        final WKTFormat v2 = new WKTFormat(Locale.US, TimeZone.getTimeZone("UTC"));
-        v1.setConvention(Convention.WKT1);
-        v2.setConvention(Convention.WKT2);
+        final WKTFormat v1  = new WKTFormat(null, null);
+        final WKTFormat v1c = new WKTFormat(null, null);
+        final WKTFormat v2  = new WKTFormat(null, null);
+        final WKTFormat v2s = new WKTFormat(null, null);
+        v1 .setConvention(Convention.WKT1);
+        v1c.setConvention(Convention.WKT1_COMMON_UNITS);
+        v2 .setConvention(Convention.WKT2);
+        v2s.setConvention(Convention.WKT2_SIMPLIFIED);
         for (final String code : CRS.getAuthorityFactory(null).getAuthorityCodes(CoordinateReferenceSystem.class)) {
             if (!EXCLUDES.contains(code)) {
                 final CoordinateReferenceSystem crs;
@@ -89,20 +104,20 @@ public final strictfp class ConsistencyT
                     print(code, "WARNING", e.getLocalizedMessage());
                     continue;
                 }
-                parseAndFormat(v2, code, crs);
+                lookup(parseAndFormat(v2,  code, crs), crs);
+                lookup(parseAndFormat(v2s, code, crs), crs);
                 /*
                  * There is more information lost in WKT 1 than in WKT 2, so we can not test everything.
                  * For example we can not format fully three-dimensional geographic CRS because the unit
                  * is not the same for all axes. We can not format neither some axis directions.
                  */
-                if (crs.getCoordinateSystem().getDimension() == 3 && (crs instanceof GeographicCRS)) {
-                    continue;
-                }
                 try {
                     parseAndFormat(v1, code, crs);
                 } catch (UnformattableObjectException e) {
                     print(code, "WARNING", e.getLocalizedMessage());
+                    continue;
                 }
+                parseAndFormat(v1c, code, crs);
             }
         }
     }
@@ -120,14 +135,17 @@ public final strictfp class ConsistencyT
     }
 
     /**
-     * Format the given CRS using the given formatter, parses it and reformat again.
+     * Formats the given CRS using the given formatter, parses it and reformat again.
      * Then the two WKT are compared.
      *
-     * @param f    The formatter to use.
-     * @param code The authority code, used only in case of errors.
-     * @param crs  The CRS to test.
+     * @param  f    The formatter to use.
+     * @param  code The authority code, used only in case of errors.
+     * @param  crs  The CRS to test.
+     * @return The parsed CRS.
      */
-    private static void parseAndFormat(final WKTFormat f, final String code, final CoordinateReferenceSystem crs) {
+    private static CoordinateReferenceSystem parseAndFormat(final WKTFormat f,
+            final String code, final CoordinateReferenceSystem crs)
+    {
         String wkt = f.format(crs);
         final Warnings warnings = f.getWarnings();
         if (warnings != null && !warnings.getExceptions().isEmpty()) {
@@ -142,7 +160,7 @@ public final strictfp class ConsistencyT
             out.println();
             e.printStackTrace(out);
             fail(e.getLocalizedMessage());
-            return;
+            return null;
         }
         final String again = f.format(parsed);
         final CharSequence[] expectedLines = CharSequences.splitOnEOL(wkt);
@@ -202,5 +220,30 @@ public final strictfp class ConsistencyT
             throw e;
         }
         assertEquals("Unexpected number of lines.", expectedLines.length, actualLines.length);
+        return parsed;
+    }
+
+    /**
+     * Verifies that {@code IdentifiedObjects.lookupURN(…)} on the parsed CRS can find back the original CRS.
+     */
+    private static void lookup(final CoordinateReferenceSystem parsed, final CoordinateReferenceSystem crs)
+            throws FactoryException
+    {
+        final Identifier id = IdentifiedObjects.getIdentifier(crs, null);
+        if (LOOKUP_EXCLUDES.contains(IdentifiedObjects.toString(id))) {
+            return;
+        }
+        /*
+         * Lookup operation is not going to work if the CRS are not approximatively equal.
+         */
+        final String urn = IdentifiedObjects.toURN(crs.getClass(), id);
+        assertNotNull(crs.getName().getCode(), urn);
+        assertTrue(urn, Utilities.deepEquals(crs, parsed, ComparisonMode.DEBUG));
+        /*
+         * Now test the lookup operation. Since the parsed CRS has an identifier,
+         * that lookup operation should not do a lot of work actually.
+         */
+        final String lookup = IdentifiedObjects.lookupURN(parsed, null);
+        assertEquals("Failed to lookup the parsed CRS.", urn, lookup);
     }
 }

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -35,6 +35,7 @@ import org.junit.BeforeClass;
     org.apache.sis.internal.referencing.j2d.ShapeUtilitiesTest.class,
     org.apache.sis.internal.referencing.PositionalAccuracyConstantTest.class,
     org.apache.sis.internal.referencing.ReferencingUtilitiesTest.class,
+    org.apache.sis.internal.referencing.WKTUtilitiesTest.class,
     org.apache.sis.internal.jaxb.referencing.CodeTest.class,
     org.apache.sis.internal.jaxb.referencing.SecondDefiningParameterTest.class,
 
@@ -94,10 +95,10 @@ import org.junit.BeforeClass;
     org.apache.sis.referencing.cs.CoordinateSystemsTest.class,
     org.apache.sis.referencing.cs.HardCodedCSTest.class,
     org.apache.sis.referencing.crs.AbstractCRSTest.class,
+    org.apache.sis.referencing.crs.DefaultVerticalCRSTest.class,
     org.apache.sis.referencing.crs.DefaultGeodeticCRSTest.class,
     org.apache.sis.referencing.crs.DefaultGeocentricCRSTest.class,
     org.apache.sis.referencing.crs.DefaultGeographicCRSTest.class,
-    org.apache.sis.referencing.crs.DefaultVerticalCRSTest.class,
     org.apache.sis.referencing.crs.DefaultTemporalCRSTest.class,
     org.apache.sis.referencing.crs.DefaultEngineeringCRSTest.class,
     org.apache.sis.referencing.crs.DefaultImageCRSTest.class,

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/converter/FallbackConverter.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/converter/FallbackConverter.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/converter/FallbackConverter.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/converter/FallbackConverter.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -20,9 +20,9 @@ import java.util.Arrays;
 import java.util.Set;
 import java.util.EnumSet;
 import java.util.Iterator;
+import org.apache.sis.math.FunctionProperty;
 import org.apache.sis.util.Classes;
 import org.apache.sis.util.ObjectConverter;
-import org.apache.sis.math.FunctionProperty;
 import org.apache.sis.util.UnconvertibleObjectException;
 import org.apache.sis.util.collection.TreeTable;
 import org.apache.sis.util.ArgumentChecks;

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/DataDirectory.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/DataDirectory.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/DataDirectory.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/system/DataDirectory.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -153,7 +153,7 @@ public enum DataDirectory {
                     else buffer.setCharAt(i, Character.toLowerCase(c));
                 }
                 final String name = buffer.toString();
-                final Path dir = root.resolve(name);
+                final Path dir = root.resolve(name).normalize();
                 try {
                     if (Files.isDirectory(dir)) {
                         directory = dir;

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Numerics.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Numerics.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Numerics.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Numerics.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -87,10 +87,13 @@ public final class Numerics extends Stat
      *
      * By extension, the same threshold value is used for comparing other floating point values.
      *
+     * <p>The current value is set to the smallest power of 10 which allow the
+     * {@code org.apache.sis.test.integration.ConsistencyTest} to pass.</p>
+     *
      * @see org.apache.sis.internal.referencing.Formulas#LINEAR_TOLERANCE
      * @see org.apache.sis.internal.referencing.Formulas#ANGULAR_TOLERANCE
      */
-    public static final double COMPARISON_THRESHOLD = 1E-14;
+    public static final double COMPARISON_THRESHOLD = 1E-13;
 
     /**
      * Bit mask to isolate the sign bit of non-{@linkplain Double#isNaN(double) NaN} values in a

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/X364.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/X364.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/X364.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/X364.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -33,7 +33,7 @@ import org.apache.sis.util.resources.Err
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.7
  * @module
  *
  * @see <a href="http://en.wikipedia.org/wiki/ANSI_escape_code">Wikipedia: ANSI escape codes</a>
@@ -44,6 +44,8 @@ public enum X364 {
     /** Normal intensity (not {@link #BOLD}).        */ NORMAL              ((byte) 22, null),
     /** Bold intensity.                              */ BOLD                ((byte)  1, null),
     /** Faint intensity.                             */ FAINT               ((byte)  2, null),
+    /** Single underline.                            */ UNDERLINE           ((byte)  4, null),
+    /** No underline.                                */ NO_UNDERLINE        ((byte) 24, null),
     /** Red foreground color, normal intensity.      */ FOREGROUND_RED      ((byte) 31, "red"),
     /** Green foreground color, normal intensity.    */ FOREGROUND_GREEN    ((byte) 32, "green"),
     /** Yellow foreground color, normal intensity.   */ FOREGROUND_YELLOW   ((byte) 33, "yellow"),
@@ -69,7 +71,7 @@ public enum X364 {
      */
     private static final X364[] NAMED;
     static {
-        NAMED = Arrays.copyOfRange(values(), 4, 11);
+        NAMED = Arrays.copyOfRange(values(), 6, 13);
     }
 
     /**

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/io/IO.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/io/IO.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/io/IO.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/io/IO.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -46,8 +46,8 @@ public final class IO extends Static {
      * of wrappers defined in this package around a flushable object, invokes the
      * {@link Flushable#flush() flush()} method on that object. Otherwise do nothing.
      *
-     * <p>Chains of wrappers are followed until a {@code Flushable}
-     * instance is found, if any. The search stops at the first occurrence found.</p>
+     * <p>Chains of wrappers are followed until a {@code Flushable} instance is found, if any.
+     * The search stops at the first occurrence found.</p>
      *
      * @param  out The stream or buffer to flush, or {@code null}.
      * @throws IOException if an error occurred while flushing the given stream.
@@ -67,10 +67,10 @@ public final class IO extends Static {
      * of wrappers defined in this package around a closeable object, invokes the
      * {@link Closeable#close() close()} method on that object. Otherwise do nothing.
      *
-     * <p>Chains of wrappers are followed until a {@code Closeable}
-     * instance is found, if any. The first {@link Flushable} instance found <em>before</em> the
-     * {@code Closeable} one, if any, is {@linkplain Flushable#flush() flushed}. The search stops
-     * at the first {@code Closeable} occurrence found.</p>
+     * <p>Chains of wrappers are followed until a {@code Closeable} instance is found, if any.
+     * The first {@link Flushable} instance found <em>before</em> the {@code Closeable} one,
+     * if any, is {@linkplain Flushable#flush() flushed}.
+     * The search stops at the first {@code Closeable} occurrence found.</p>
      *
      * @param  out The stream or buffer to close, or {@code null}.
      * @throws IOException if an error occurred while closing the given stream.

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/setup/package-info.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/setup/package-info.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/setup/package-info.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/setup/package-info.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -20,7 +20,7 @@
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.7
  * @module
  */
 package org.apache.sis.setup;

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/logging/Logging.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/logging/Logging.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/logging/Logging.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/logging/Logging.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -170,6 +170,9 @@ public final class Logging extends Stati
         String name = classe.getName();
         final int separator = name.lastIndexOf('.');
         name = (separator >= 1) ? name.substring(0, separator) : "";
+        if (name.startsWith("org.apache.sis.internal.")) {
+            name = "org.apache.sis" + name.substring(23);       // Remove the "internal" part from SIS package name.
+        }
         return getLogger(name);
     }
 

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/logging/MonolineFormatter.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/logging/MonolineFormatter.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/logging/MonolineFormatter.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/logging/MonolineFormatter.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -111,7 +111,7 @@ import org.apache.sis.internal.jdk7.JDK7
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.4
+ * @version 0.7
  * @module
  *
  * @see SimpleFormatter
@@ -544,6 +544,7 @@ loop:   for (int i=0; ; i++) {
     /**
      * Returns the {@link #colors} map, creating it if needed.
      */
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
     private SortedMap<Level,X364> colors() {
         if (colors == null) {
             colors = new TreeMap<Level,X364>(COMPARATOR);
@@ -642,19 +643,17 @@ loop:   for (int i=0; ; i++) {
              * This level will be formatted with a colorized background if ANSI escape sequences are enabled.
              */
             int margin = buffer.length();
+            String levelColor = "", levelReset = "";
             if (SHOW_LEVEL) {
                 if (colors) {
-                    buffer.append(colorAt(level));
+                    levelColor = colorAt(level);
+                    levelReset = X364.BACKGROUND_DEFAULT.sequence();
                 }
-                final int offset = buffer.length();
+                final int offset = buffer.append(levelColor).length();
                 buffer.append(level.getLocalizedName())
                       .append(CharSequences.spaces(levelWidth - (buffer.length() - offset)));
                 margin += buffer.length() - offset;
-                if (colors) {
-                    buffer.append(X364.BACKGROUND_DEFAULT.sequence());
-                }
-                buffer.append(' ');
-                margin++;
+                buffer.append(levelReset).append(' ');
             }
             /*
              * Appends the logger name or source class name, in long of short form.
@@ -692,8 +691,8 @@ loop:   for (int i=0; ; i++) {
              */
             String bodyLineSeparator = writer.getLineSeparator();
             final String lineSeparator = JDK7.lineSeparator();
-            if (bodyLineSeparator.length() != lineSeparator.length() + margin) {
-                bodyLineSeparator = lineSeparator + CharSequences.spaces(margin);
+            if (bodyLineSeparator.length() != lineSeparator.length() + margin + 1) {
+                bodyLineSeparator = lineSeparator + levelColor + CharSequences.spaces(margin) + levelReset + ' ';
                 writer.setLineSeparator(bodyLineSeparator);
             }
             if (colors && !emphase) {

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] Wed Mar  2 22:31:02 2016
@@ -181,6 +181,11 @@ public final class Errors extends Indexe
         public static final short CanNotTransformEnvelopeToGeodetic = 174;
 
         /**
+         * Can not use the {0} geodetic parameters: {1}
+         */
+        public static final short CanNotUseGeodeticParameters_2 = 218;
+
+        /**
          * Circular reference.
          */
         public static final short CircularReference = 52;
@@ -474,6 +479,11 @@ public final class Errors extends Indexe
         public static final short IncompatibleDatum_2 = 186;
 
         /**
+         * Can not use the “{1}” format with “{0}”.
+         */
+        public static final short IncompatibleFormat_2 = 217;
+
+        /**
          * Property “{0}” has an incompatible value.
          */
         public static final short IncompatiblePropertyValue_1 = 45;

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1733385&r1=1733384&r2=1733385&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] Wed Mar  2 22:31:02 2016
@@ -47,6 +47,7 @@ CanNotSetParameterValue_1         = Can
 CanNotSetPropertyValue_1          = Can not set a value for property \u201c{0}\u201d.
 CanNotTransformEnvelope           = Can not transform envelope.
 CanNotTransformEnvelopeToGeodetic = Can not transform envelope to a geodetic CRS.
+CanNotUseGeodeticParameters_2     = Can not use the {0} geodetic parameters: {1}
 CircularReference                 = Circular reference.
 ClassNotFinal_1                   = Class \u2018{0}\u2019 is not final.
 CloneNotSupported_1               = Can not clone an object of type \u2018{0}\u2019.
@@ -104,6 +105,7 @@ IllegalUnicodeCodePoint_2         = Valu
 IllegalUnitFor_2                  = Unit of measurement \u201c{1}\u201d is not valid for \u201c{0}\u201d values.
 IncompatibleCoordinateSystemTypes = Incompatible coordinate system types.
 IncompatibleDatum_2               = Datum of \u201c{1}\u201d shall be \u201c{0}\u201d.
+IncompatibleFormat_2              = Can not use the \u201c{1}\u201d format with \u201c{0}\u201d.
 IncompatiblePropertyValue_1       = Property \u201c{0}\u201d has an incompatible value.
 IncompatibleUnit_1                = Unit \u201c{0}\u201d is incompatible with current value.
 IncompatibleUnits_2               = Units \u201c{0}\u201d and \u201c{1}\u201d are incompatible.



Mime
View raw message