sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1731689 [3/4] - in /sis/trunk: ./ core/ core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ core/sis-metadata/src/main/java/org/apache/sis/io/wkt/ core/sis...
Date Mon, 22 Feb 2016 17:12:03 GMT
Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java?rev=1731689&r1=1731688&r2=1731689&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java [UTF-8] Mon Feb 22 17:12:02 2016
@@ -17,6 +17,7 @@
 package org.apache.sis.referencing.factory.sql;
 
 import java.util.Locale;
+import java.util.ServiceLoader;
 import java.io.IOException;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
@@ -27,27 +28,26 @@ import java.util.logging.Level;
 import java.util.logging.LogRecord;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
+import java.io.BufferedReader;
 import org.apache.sis.util.StringBuilders;
 import org.apache.sis.internal.metadata.sql.ScriptRunner;
+import org.apache.sis.internal.metadata.sql.SQLUtilities;
 import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.util.CharSequences;
-import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.resources.Messages;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.logging.PerformanceLevel;
 
 // Branch-specific imports
-import org.apache.sis.internal.jdk7.Files;
-import org.apache.sis.internal.jdk7.Path;
 import org.apache.sis.internal.jdk8.BiFunction;
 
 
 /**
  * Runs the SQL scripts for creating an EPSG database.
  *
+ * See {@code EPSGDataFormatter} in the test directory for more information about how the scripts are formatted.
+ *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.7
  * @version 0.7
@@ -55,14 +55,6 @@ import org.apache.sis.internal.jdk8.BiFu
  */
 final class EPSGInstaller extends ScriptRunner {
     /**
-     * The embedded SQL scripts to execute for creating the EPSG database, in that order.
-     * The {@code ".sql"} suffix is omitted. The {@code "Grant"} script must be last.
-     */
-    private static final String[] SCRIPTS = {
-        "Tables", "Data", "Patches", "FKeys", "Indexes", "Grant"         // "Grant" must be last.
-    };
-
-    /**
      * The pattern for an {@code "UPDATE … SET … REPLACE"} instruction.
      * Example:
      *
@@ -71,7 +63,7 @@ final class EPSGInstaller extends Script
      *     SET datum_name = replace(datum_name, CHAR(182), CHAR(10));
      * }
      */
-    private static final String REPLACE_STATEMENT =
+    static final String REPLACE_STATEMENT =
             "\\s*UPDATE\\s+[\\w\\.\" ]+\\s+SET\\s+(\\w+)\\s*=\\s*replace\\s*\\(\\s*\\1\\W+.*";
 
     /**
@@ -95,7 +87,7 @@ final class EPSGInstaller extends Script
      * @throws SQLException if an error occurred while executing a SQL statement.
      */
     public EPSGInstaller(final Connection connection) throws SQLException {
-        super(connection, "ISO-8859-1", 100);
+        super(connection, 100);
         boolean isReplaceSupported = false;
         final DatabaseMetaData metadata = connection.getMetaData();
         final String functions = metadata.getStringFunctions();
@@ -138,29 +130,41 @@ final class EPSGInstaller extends Script
              * Mapping from the table names used in the SQL scripts to the original names used in the MS-Access database.
              * We use those original names because they are easier to read than the names in SQL scripts.
              */
-            replace(SQLTranslator.TABLE_PREFIX + "alias",                      "Alias");
-            replace(SQLTranslator.TABLE_PREFIX + "area",                       "Area");
-            replace(SQLTranslator.TABLE_PREFIX + "change",                     "Change");
-            replace(SQLTranslator.TABLE_PREFIX + "coordinateaxis",             "Coordinate Axis");
-            replace(SQLTranslator.TABLE_PREFIX + "coordinateaxisname",         "Coordinate Axis Name");
-            replace(SQLTranslator.TABLE_PREFIX + "coordoperation",             "Coordinate_Operation");
-            replace(SQLTranslator.TABLE_PREFIX + "coordoperationmethod",       "Coordinate_Operation Method");
-            replace(SQLTranslator.TABLE_PREFIX + "coordoperationparam",        "Coordinate_Operation Parameter");
-            replace(SQLTranslator.TABLE_PREFIX + "coordoperationparamusage",   "Coordinate_Operation Parameter Usage");
-            replace(SQLTranslator.TABLE_PREFIX + "coordoperationparamvalue",   "Coordinate_Operation Parameter Value");
-            replace(SQLTranslator.TABLE_PREFIX + "coordoperationpath",         "Coordinate_Operation Path");
-            replace(SQLTranslator.TABLE_PREFIX + "coordinatereferencesystem",  "Coordinate Reference System");
-            replace(SQLTranslator.TABLE_PREFIX + "coordinatesystem",           "Coordinate System");
-            replace(SQLTranslator.TABLE_PREFIX + "datum",                      "Datum");
-            replace(SQLTranslator.TABLE_PREFIX + "deprecation",                "Deprecation");
-            replace(SQLTranslator.TABLE_PREFIX + "ellipsoid",                  "Ellipsoid");
-            replace(SQLTranslator.TABLE_PREFIX + "namingsystem",               "Naming System");
-            replace(SQLTranslator.TABLE_PREFIX + "primemeridian",              "Prime Meridian");
-            replace(SQLTranslator.TABLE_PREFIX + "supersession",               "Supersession");
-            replace(SQLTranslator.TABLE_PREFIX + "unitofmeasure",              "Unit of Measure");
-            replace(SQLTranslator.TABLE_PREFIX + "versionhistory",             "Version History");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "alias",                      "Alias");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "area",                       "Area");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "change",                     "Change");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordinateaxis",             "Coordinate Axis");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordinateaxisname",         "Coordinate Axis Name");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordoperation",             "Coordinate_Operation");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordoperationmethod",       "Coordinate_Operation Method");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordoperationparam",        "Coordinate_Operation Parameter");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordoperationparamusage",   "Coordinate_Operation Parameter Usage");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordoperationparamvalue",   "Coordinate_Operation Parameter Value");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordoperationpath",         "Coordinate_Operation Path");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordinatereferencesystem",  "Coordinate Reference System");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordinatesystem",           "Coordinate System");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "datum",                      "Datum");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "deprecation",                "Deprecation");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "ellipsoid",                  "Ellipsoid");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "namingsystem",               "Naming System");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "primemeridian",              "Prime Meridian");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "supersession",               "Supersession");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "unitofmeasure",              "Unit of Measure");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "versionhistory",             "Version History");
+            if (isEnumTypeSupported) {
+                addReplacement(SQLTranslator.TABLE_PREFIX + "datum_kind",             "Datum Kind");
+                addReplacement(SQLTranslator.TABLE_PREFIX + "crs_kind",               "CRS Kind");
+                addReplacement(SQLTranslator.TABLE_PREFIX + "cs_kind",                "CS Kind");
+                addReplacement(SQLTranslator.TABLE_PREFIX + "table_name",             "Table Name");
+            }
             prependNamespace(schema);
         }
+        if (!isEnumTypeSupported) {
+            addReplacement(SQLTranslator.TABLE_PREFIX + "datum_kind", "VARCHAR(24)");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "crs_kind",   "VARCHAR(24)");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "cs_kind",    "VARCHAR(24)");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "table_name", "VARCHAR(80)");
+        }
     }
 
     /**
@@ -169,12 +173,41 @@ final class EPSGInstaller extends Script
     final void prependNamespace(final String schema) {
         modifyReplacements(new BiFunction<String,String,String>() {
             @Override public String apply(String key, String value) {
-                return schema + '.' + identifierQuote + value + identifierQuote;
+                return key.startsWith(SQLTranslator.TABLE_PREFIX) ?
+                        schema + '.' + identifierQuote + value + identifierQuote : value;
             }
         });
     }
 
     /**
+     * Invoked for each text found in a SQL statement. This method replaces {@code ''} by {@code Null}.
+     * The intend is to consistently use the null value for meaning "no information", which is not the
+     * same than "information is an empty string". This replacement is okay in this particular case
+     * since there is no field in the EPSG database for which we really want an empty string.
+     *
+     * @param sql   The whole SQL statement.
+     * @param lower Index of the first character of the text in {@code sql}.
+     * @param upper Index after the last character of the text in {@code sql}.
+     */
+    @Override
+    protected void editText(final StringBuilder sql, final int lower, final int upper) {
+        final String replacement;
+        switch (upper - lower) {
+            default: {
+                return;
+            }
+            /*
+             * Replace '' by Null for every table.
+             */
+            case 2: {
+                replacement = "Null";
+                break;
+            }
+        }
+        sql.replace(lower, upper, replacement);
+    }
+
+    /**
      * Modifies the SQL statement before to execute it, or omit unsupported statements.
      *
      * @throws SQLException if an error occurred while executing the SQL statement.
@@ -190,6 +223,15 @@ final class EPSGInstaller extends Script
         if (CharSequences.equalsIgnoreCase(sql, "COMMIT")) {
             return 0;
         }
+        if (!isGrantOnTableSupported && CharSequences.regionMatches(sql, 0, "GRANT")) {
+            return 0;
+        }
+        if (!isEnumTypeSupported && CharSequences.regionMatches(sql, 0, "CREATE")) {
+            final String t = CharSequences.trimWhitespaces(sql, 6, 12).toString();
+            if (t.equals("TYPE") || t.equals("CAST")) {
+                return 0;
+            }
+        }
         if (statementToSkip != null && statementToSkip.reset(sql).matches()) {
             return 0;
         }
@@ -200,50 +242,27 @@ final class EPSGInstaller extends Script
     }
 
     /**
-     * Processes to the creation of the EPSG database using the files in the given directory.
-     * The given directory should contain at least files similar to the following ones
-     * (files without {@code ".sql"} extension are ignored):
-     *
-     * <ul>
-     *   <li>{@code EPSG_v8_18.mdb_Tables_PostgreSQL.sql}</li>
-     *   <li>{@code EPSG_v6_18.mdb_Data_PostgreSQL.sql}</li>
-     *   <li>{@code EPSG_v6_18.mdb_FKeys_PostgreSQL.sql}</li>
-     *   <li>Optional but recommended: {@code EPSG_v6_18.mdb_Indexes_PostgreSQL.sql}.</li>
-     * </ul>
-     *
-     * The suffix may be different (for example {@code "_MySQL.sql"} instead of {@code "_PostgreSQL.sql"})
-     * and the version number may be different.
-     *
-     * <p>If the given directory is {@code null}, then the scripts will be read from the resources.
-     * If no resources is found, then an exception will be thrown.
+     * Processes to the creation of the EPSG database using the SQL scripts from the given provider.
      *
      * @throws IOException if an error occurred while reading an input.
      * @throws SQLException if an error occurred while executing a SQL statement.
      */
-    public void run(final Path scriptDirectory) throws SQLException, IOException {
+    public void run(InstallationScriptProvider scriptProvider) throws SQLException, IOException {
         long time = System.nanoTime();
-        if (scriptDirectory == null) {
-            log(Messages.getResources(null).getLogRecord(Level.INFO, Messages.Keys.CreatingSchema_2,
-                    Constants.EPSG, getConnection().getMetaData().getURL()));
-        }
-        int numScripts = SCRIPTS.length;
-        if (!isGrantOnTableSupported) {
-            numScripts--;
+        log(Messages.getResources(null).getLogRecord(Level.INFO, Messages.Keys.CreatingSchema_2, Constants.EPSG,
+                SQLUtilities.getSimplifiedURL(getConnection().getMetaData())));
+        if (scriptProvider == null) {
+            scriptProvider = lookupProvider();
         }
+        final String[] scripts = scriptProvider.getScriptNames();
         int numRows = 0;
-        for (int i=0; i<numScripts; i++) {
-            final String script = SCRIPTS[i] + ".sql";
-            final InputStream in;
-            if (scriptDirectory != null) {
-                in = Files.newInputStream(scriptDirectory.resolve(script));
-            } else {
-                in = EPSGInstaller.class.getResourceAsStream(script);
-                if (in == null) {
-                    throw new FileNotFoundException(Errors.format(Errors.Keys.FileNotFound_1, script));
-                }
+        for (int i=0; i<scripts.length; i++) {
+            final BufferedReader in = scriptProvider.getScriptContent(i);
+            try {
+                numRows += run(scripts[i], in);
+            } finally {
+                in.close();
             }
-            numRows += run(script, in);
-            // The stream will be closed by the run method.
         }
         time = System.nanoTime() - time;
         log(Messages.getResources(null).getLogRecord(
@@ -252,6 +271,18 @@ final class EPSGInstaller extends Script
     }
 
     /**
+     * Searches for a SQL script provider on the classpath before to fallback on the default provider.
+     */
+    private static InstallationScriptProvider lookupProvider() {
+        for (final InstallationScriptProvider p : ServiceLoader.load(InstallationScriptProvider.class)) {
+            if (Constants.EPSG.equals(p.getAuthority())) {
+                return p;
+            }
+        }
+        return new InstallationScriptProvider.Default();
+    }
+
+    /**
      * Logs a message reporting the failure to create EPSG database.
      */
     final void logFailure(final Locale locale) {

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.java?rev=1731689&r1=1731688&r2=1731689&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.java [UTF-8] Mon Feb 22 17:12:02 2016
@@ -22,6 +22,7 @@ import java.util.Locale;
 import java.sql.DatabaseMetaData;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.Types;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
@@ -129,6 +130,15 @@ public class SQLTranslator {
     static final String TABLE_PREFIX = "epsg_";
 
     /**
+     * The columns that may be of {@code BOOLEAN} type instead of {@code SMALLINT}.
+     */
+    private static final String[] BOOLEAN_FIELDS = {
+        "SHOW_CRS",
+        "SHOW_OPERATION",
+        "DEPRECATED"
+    };
+
+    /**
      * The name of the catalog that contains the EPSG tables, or {@code null} or an empty string.
      * <ul>
      *   <li>The {@code ""} value retrieves the EPSG schema without a catalog.</li>
@@ -184,6 +194,14 @@ public class SQLTranslator {
     private final String quote;
 
     /**
+     * {@code true} if the database uses the {@code BOOLEAN} type instead than {@code SMALLINT}
+     * for the {@code show_crs}, {@code show_operation} and all {@code deprecated} fields.
+     *
+     * @see #useBoolean()
+     */
+    private boolean useBoolean;
+
+    /**
      * {@code true} if one of the {@link #SENTINEL} tables exist.
      * If {@code false}, then {@link EPSGInstaller} needs to be run.
      *
@@ -276,6 +294,26 @@ public class SQLTranslator {
         if (translateColumns) {
             accessToAnsi.put("ORDER", "coord_axis_order");
         }
+        /*
+         * Detect if the database uses boolean types where applicable.
+         * We arbitrarily use the Datum table as a representative value.
+         */
+        String deprecated = "DEPRECATED";
+        if (md.storesLowerCaseIdentifiers()) {
+            deprecated = deprecated.toLowerCase(Locale.US);
+        }
+        final ResultSet result = md.getColumns(catalog, schema, null, deprecated);
+        try {
+            while (result.next()) {
+                if (CharSequences.endsWith(result.getString("TABLE_NAME"), "Datum", true)) {
+                    final int type = result.getInt("DATA_TYPE");
+                    useBoolean = (type == Types.BOOLEAN) || (type == Types.BIT);
+                    break;
+                }
+            }
+        } finally {
+            result.close();
+        }
     };
 
     /**
@@ -318,6 +356,14 @@ public class SQLTranslator {
     }
 
     /**
+     * Returns {@code true} if the database uses the {@code BOOLEAN} type instead than {@code SMALLINT}
+     * for the {@code show_crs}, {@code show_operation} and all {@code deprecated} fields.
+     */
+    final boolean useBoolean() {
+        return useBoolean;
+    }
+
+    /**
      * If the given string is empty, returns {@code null} instead.
      */
     private static String nonEmpty(final String s) {
@@ -380,6 +426,43 @@ public class SQLTranslator {
                 }
             }
         }
-        return ansi.append(sql, end, sql.length()).toString();
+        ansi.append(sql, end, sql.length());
+        /*
+         * If the database use the BOOLEAN type instead of SMALLINT, replaces "deprecated=0' by "deprecated=false".
+         */
+        if (useBoolean) {
+            int w = ansi.indexOf("WHERE");
+            if (w >= 0) {
+                w += 5;
+                for (final String field : BOOLEAN_FIELDS) {
+                    int p = ansi.indexOf(field, w);
+                    if (p >= 0) {
+                        p += field.length();
+                        if (!replaceIfEquals(ansi, p, "=0", "=FALSE") &&
+                            !replaceIfEquals(ansi, p, "<>0", "=TRUE"))
+                        {
+                            // Remove "ABS" in "ABS(DEPRECATED)" or "ABS(CO.DEPRECATED)".
+                            if ((p = ansi.lastIndexOf("(", p)) > w) {
+                                replaceIfEquals(ansi, p-3, "ABS", "");
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return ansi.toString();
+    }
+
+    /**
+     * Replaces the text at the given position in the buffer if it is equals to the {@code expected} text.
+     */
+    private static boolean replaceIfEquals(final StringBuilder ansi, final int pos,
+            final String expected, final String replacement)
+    {
+        if (CharSequences.regionMatches(ansi, pos, expected)) {
+            ansi.replace(pos, pos + expected.length(), replacement);
+            return true;
+        }
+        return false;
     }
 }

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=1731689&r1=1731688&r2=1731689&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] Mon Feb 22 17:12:02 2016
@@ -16,9 +16,12 @@
  */
 
 /**
- * Factories for geodetic objects defined in a SQL database.
+ * Factories for geodetic objects defined in a SQL database, typically the EPSG dataset.
  * 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:
  *
@@ -39,22 +42,25 @@
  * <div class="section">The EPSG dataset</div>
  * A widely-used factory is the <a href="http://www.epsg.org">EPSG geodetic dataset</a>.
  * EPSG codes are numerical identifiers.
- * For example {@code "EPSG::4326"} is the EPSG identifier for the <cite>"WGS 84"</cite> geographic CRS.
+ * For example {@code "EPSG:4326"} is the EPSG identifier for the <cite>"WGS 84"</cite> geographic CRS.
  * As an extension, the Apache SIS implementation accepts names as well as numeric identifiers.
  * For example the two following method calls fetch the same object:
  *
  * <ul>
- *   <li>{@code createProjectedCRS("NTF (Paris) / Lambert zone II")}</li>
  *   <li>{@code createProjectedCRS("27572")}</li>
+ *   <li>{@code createProjectedCRS("NTF (Paris) / Lambert zone II")}</li>
  * </ul>
  *
- * However names may be ambiguous since the same name may be used for more than one object.
+ * <div class="note"><b>Note:</b> names may be ambiguous since the same name may be used for more than one object.
  * This is the case of <cite>"WGS 84"</cite> for example. If such an ambiguity is found, an exception will be thrown.
+ * For more determinism, the numerical codes are preferred.</div>
+ *
  *
- * <p>When an error is discovered in a Coordinate Reference System (CRS) definition, the EPSG group does not apply the
+ * <div class="section">How deprecated entries are handled</div>
+ * When an error is discovered in a Coordinate Reference System (CRS) definition, the EPSG group does not apply the
  * correction directly on the erroneous object (unless the correction is very minor).
  * Instead, the erroneous object is deprecated and a new one is created.
- * Apache SIS handles deprecated objects as below:</p>
+ * Apache SIS handles deprecated objects as below:
  *
  * <ul>
  *   <li>Deprecated objects are not listed in the collection returned by the

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java?rev=1731689&r1=1731688&r2=1731689&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/Initializer.java [UTF-8] Mon Feb 22 17:12:02 2016
@@ -227,21 +227,27 @@ final class Initializer {
      */
     final double getAndStore(final ParameterDescriptor<? extends Number> descriptor) {
         if (descriptor == null) {
-            return 0;   // Default value for all parameters except scale factor.
+            return 0;                           // Default value for all parameters except scale factor.
         }
+        /*
+         * Get the parameter value, or its default value if the parameter was not set. That default value
+         * (which is specified by the descriptor of the user-supplied parameters) is not necessarily the
+         * same than the default value of the map projection implementation (which is specified by the
+         * descriptor given in argument to this method).
+         */
         final double value = parameters.doubleValue(descriptor);    // Apply a unit conversion if needed.
         final Number defaultValue = descriptor.getDefaultValue();
         if (defaultValue == null || !defaultValue.equals(value)) {
             MapProjection.validate(descriptor, value);
-            context.getOrCreate(descriptor).setValue(value);
+            context.parameter(descriptor.getName().getCode()).setValue(value);
         }
         return value;
     }
 
     /**
-     * Same as {@link #getAndStore(Parameters, ParameterDescriptor)}, but returns the given default value
-     * if the parameter is not specified.  This method shall be used only for parameters having a default
-     * value more complex than what we can represent in {@link ParameterDescriptor#getDefaultValue()}.
+     * Same as {@link #getAndStore(ParameterDescriptor)}, but returns the given default value if the parameter
+     * is not specified.  This method shall be used only for parameters having a default value more complex than
+     * what we can represent in {@link ParameterDescriptor#getDefaultValue()}.
      */
     final double getAndStore(final ParameterDescriptor<Double> descriptor, final double defaultValue) {
         final Double value = parameters.getValue(descriptor);   // Apply a unit conversion if needed.

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java?rev=1731689&r1=1731688&r2=1731689&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java [UTF-8] Mon Feb 22 17:12:02 2016
@@ -600,25 +600,25 @@ public class ContextualParameters extend
      * @throws ParameterNotFoundException if there is no parameter of the given name.
      */
     @Override
+    @SuppressWarnings({"unchecked", "rawtypes"})
     public synchronized ParameterValue<?> parameter(final String name) throws ParameterNotFoundException {
         final GeneralParameterDescriptor desc = descriptor.descriptor(name);
         if (!(desc instanceof ParameterDescriptor<?>)) {
             throw parameterNotFound(name);
         }
         /*
-         * Search for existing parameter instance. This implementation does not scale,
-         * but should be okay since the amount of parameters is typically very small
-         * (rarely more than 6 parameters in map projections).
+         * Search for existing parameter instance. This implementation does not scale, but should be okay since
+         * the amount of parameters is typically very small (rarely more than 6 parameters in map projections).
          */
         for (int i=0; i < values.length; i++) {
             ParameterValue<?> p = values[i];
             if (p == null) {
-                p = ((ParameterDescriptor<?>) desc).createValue();
-                values[i] = p;
-            } else if (p.getDescriptor() != desc) {  // Identity comparison should be okay here.
-                continue;
+                values[i] = p = new ContextualParameter((ParameterDescriptor<?>) desc);
+                return p;
+            }
+            if (p.getDescriptor() == desc) {                    // Identity comparison should be okay here.
+                return p;
             }
-            return p;   // Found or created a parameter.
         }
         /*
          * We may reach this point if map projection construction is completed (i.e. 'completeTransform(…)' has

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java?rev=1731689&r1=1731688&r2=1731689&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java [UTF-8] Mon Feb 22 17:12:02 2016
@@ -36,6 +36,8 @@ import org.opengis.parameter.ParameterVa
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.parameter.ParameterNotFoundException;
+import org.opengis.parameter.InvalidParameterNameException;
+import org.opengis.parameter.InvalidParameterValueException;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.cs.CoordinateSystem;
 import org.opengis.referencing.cs.EllipsoidalCS;
@@ -627,11 +629,17 @@ public class DefaultMathTransformFactory
          * The intend is to make sure that we have room for the parameters that {@code setEllipsoids(…)}
          * may write.
          *
+         * <p>A side effect of this method is that the copy operation may perform a check of
+         * parameter value validity. This may result in an {@link InvalidParameterNameException}
+         * or {@link InvalidParameterValueException} to be thrown.</p>
+         *
          * @param writable {@code true} if this method should also check that the parameters group is not
          *        an instance of {@link UnmodifiableParameterValueGroup}. Current implementation assumes
          *        that modifiable parameters are instances of {@link DefaultParameterValueGroup}.
+         * @throws IllegalArgumentException if the copy can not be performed because a parameter has
+         *         a unrecognized name or an illegal value.
          */
-        private void ensureCompatibleParameters(final boolean writable) {
+        private void ensureCompatibleParameters(final boolean writable) throws IllegalArgumentException {
             final ParameterDescriptorGroup expected = provider.getParameters();
             if (parameters.getDescriptor() != expected ||
                     (writable &&  (parameters instanceof Parameters)
@@ -784,8 +792,10 @@ public class DefaultMathTransformFactory
          * @return The exception if the operation failed, or {@code null} if none. This exception is not thrown now
          *         because the caller may succeed in creating the transform anyway, or otherwise may produce a more
          *         informative exception.
+         * @throws IllegalArgumentException if the operation fails because a parameter has a unrecognized name or an
+         *         illegal value.
          */
-        final RuntimeException setEllipsoids(final OperationMethod method) {
+        final RuntimeException setEllipsoids(final OperationMethod method) throws IllegalArgumentException {
             ensureCompatibleParameters(false);
             int n;
             if (method instanceof AbstractProvider) {
@@ -910,21 +920,21 @@ public class DefaultMathTransformFactory
                         Errors.Keys.UnsupportedImplementation_1, Classes.getClass(method)), methodName);
             }
             /*
-             * If the user's parameters do not contain semi-major and semi-minor axis lengths, infer
-             * them from the ellipsoid. We have to do that because those parameters are often omitted,
-             * since the standard place where to provide this information is in the ellipsoid object.
-             */
-            if (context != null) {
-                context.provider   = method;
-                context.parameters = parameters;
-                failure = context.setEllipsoids(method);
-                parameters = context.parameters;
-            }
-            /*
-             * Catch only exceptions which may be the result of improper parameter usage (e.g. a value out of range).
-             * Do not catch exception caused by programming errors (e.g. null pointer exception).
+             * Will catch only exceptions that may be the result of improper parameter usage (e.g. a value out
+             * of range). Do not catch exceptions caused by programming errors (e.g. null pointer exception).
              */
             try {
+                /*
+                 * If the user's parameters do not contain semi-major and semi-minor axis lengths, infer
+                 * them from the ellipsoid. We have to do that because those parameters are often omitted,
+                 * since the standard place where to provide this information is in the ellipsoid object.
+                 */
+                if (context != null) {
+                    context.provider   = method;
+                    context.parameters = parameters;
+                    failure = context.setEllipsoids(method);
+                    parameters = context.parameters;
+                }
                 transform = ((MathTransformProvider) method).createMathTransform(this, parameters);
             } catch (RuntimeException exception) {  // (IllegalArgumentException | IllegalStateException) on the JDK7 branch.
                 throw new InvalidGeodeticParameterException(exception.getLocalizedMessage(), exception);
@@ -1243,7 +1253,7 @@ public class DefaultMathTransformFactory
                 parserConstructor = c;
             }
             p = c.newInstance(this);
-        } catch (Exception e) { // (ReflectiveOperationException) on JDK7 branch.
+        } catch (Exception e) {                     // (ReflectiveOperationException) on JDK7 branch.
             throw new FactoryException(e);
         }
         /*

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameterTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameterTest.java?rev=1731689&r1=1731688&r2=1731689&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameterTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameterTest.java [UTF-8] Mon Feb 22 17:12:02 2016
@@ -31,7 +31,7 @@ import org.apache.sis.test.XMLTestCase;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.LoggingWatcher;
-import org.apache.sis.util.logging.Logging;
+import org.junit.After;
 import org.junit.Rule;
 import org.junit.Test;
 
@@ -52,19 +52,22 @@ import static org.junit.Assert.*;
 public final strictfp class CC_GeneralOperationParameterTest extends XMLTestCase {
     /**
      * A JUnit rule for listening to log events emitted during execution of {@link #testGroupMergeBecauseExtraParameter()}.
-     * This rule verifies that the log message contains the expected information. The expected message is something like
-     * "No parameter named "Parameter B" was found".
+     * This rule is used by test methods for verifying that the log message contains the expected information.
+     * The expected message is something like "No parameter named "Parameter B" was found".
      *
      * <p>This field is public because JUnit requires us to do so, but should be considered as an implementation details
      * (it should have been a private field).</p>
      */
     @Rule
-    public final LoggingWatcher listener = new LoggingWatcher(Logging.getLogger(Loggers.XML)) {
-        @Override protected void verifyMessage(final String message) {
-            assertTrue(message, message.contains("Parameter B"));
-            assertTrue(message, message.contains("Group"));
-        }
-    };
+    public final LoggingWatcher loggings = new LoggingWatcher(Loggers.XML);
+
+    /**
+     * Verifies that no unexpected warning has been emitted in any test defined in this class.
+     */
+    @After
+    public void assertNoUnexpectedLog() {
+        loggings.assertNoUnexpectedLog();
+    }
 
     /**
      * Creates a parameter descriptor as unmarshalled by JAXB, without {@code valueClass}.
@@ -305,7 +308,7 @@ public final strictfp class CC_GeneralOp
                 create("Parameter A", "Remarks A.", false, 3),
                 create("Parameter C", "Remarks C.", false, 4));
 
-        listener.maximumLogCount = 1;
+        loggings.assertNoUnexpectedLog();
         final ParameterDescriptorGroup merged =
                 (ParameterDescriptorGroup) CC_GeneralOperationParameter.merge(provided, complete);
         assertNotSame(complete, provided);
@@ -313,6 +316,8 @@ public final strictfp class CC_GeneralOp
         assertSame   ("remarks",       complete.getRemarks(), merged.getRemarks());
         assertEquals ("minimumOccurs", 1,                     merged.getMinimumOccurs());
         assertEquals ("maximumOccurs", 2,                     merged.getMaximumOccurs());
+        loggings.assertNextLogContains("Parameter B", "Group");
+        loggings.assertNoUnexpectedLog();
 
         final Iterator<GeneralParameterDescriptor> itc = complete.descriptors().iterator();
         final Iterator<GeneralParameterDescriptor> itm = merged  .descriptors().iterator();

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java?rev=1731689&r1=1731688&r2=1731689&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java [UTF-8] Mon Feb 22 17:12:02 2016
@@ -24,7 +24,6 @@ import org.opengis.referencing.crs.CRSAu
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.apache.sis.util.ComparisonMode;
-import org.apache.sis.util.logging.Logging;
 import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.referencing.crs.HardCodedCRS;
@@ -35,6 +34,7 @@ import org.apache.sis.referencing.factor
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.LoggingWatcher;
 import org.apache.sis.test.TestCase;
+import org.junit.After;
 import org.junit.Rule;
 import org.junit.Test;
 
@@ -51,26 +51,18 @@ import static org.apache.sis.test.Assert
  */
 public final strictfp class AuthorityFactoriesTest extends TestCase {
     /**
-     * A JUnit {@linkplain Rule rule} for listening to log events. This field is public because JUnit requires
-     * us to do so, but should be considered as an implementation details (it should have been a private field).
+     * A JUnit {@link Rule} for listening to log events. This field is public because JUnit requires us to
+     * do so, but should be considered as an implementation details (it should have been a private field).
      */
     @Rule
-    public final LoggingWatcher listener = new Listener();
+    public final LoggingWatcher loggings = new LoggingWatcher(Loggers.CRS_FACTORY);
 
     /**
-     * Implementation of the {@link AuthorityFactoriesTest#listener} rule.
+     * Verifies that no unexpected warning has been emitted in any test defined in this class.
      */
-    private static final class Listener extends LoggingWatcher {
-        /** The logged message. */
-        String message;
-
-        /** Creates a new log listener. */
-        Listener() {super(Logging.getLogger(Loggers.CRS_FACTORY));}
-
-        /** Stores the log message. */
-        @Override protected void verifyMessage(final String message) {
-            this.message = message;
-        }
+    @After
+    public void assertNoUnexpectedLog() {
+        loggings.assertNoUnexpectedLog();
     }
 
     /**
@@ -108,25 +100,23 @@ public final strictfp class AuthorityFac
     public void testVersionedEPSG() throws FactoryException {
         final CRSAuthorityFactory factory = AuthorityFactories.ALL;
         final GeographicCRS crs = factory.createGeographicCRS("EPSG:4326");
+        loggings.assertNoUnexpectedLog();
 
-        listener.maximumLogCount = 1;
         assertSame(crs, factory.createGeographicCRS("urn:ogc:def:crs:EPSG:6.11.2:4326"));
         assertSame(crs, factory.createGeographicCRS("urn:ogc:def:crs:EPSG:6.11.2:4326"));
-        String message = ((Listener) listener).message;
-        assertTrue(message, message.contains("6.11.2"));
+        loggings.assertNextLogContains("6.11.2");
+        loggings.assertNoUnexpectedLog();
 
-        listener.maximumLogCount = 1;
         assertSame(crs, factory.createGeographicCRS("urn:ogc:def:crs:EPSG:7.04:4326"));
-        message = ((Listener) listener).message;
-        assertTrue(message, message.contains("7.04"));
+        loggings.assertNextLogContains("7.04");
+        loggings.assertNoUnexpectedLog();
 
-        listener.maximumLogCount = 1;
         assertSame(crs, factory.createGeographicCRS("urn:ogc:def:crs:EPSG:7.10:4326"));
-        message = ((Listener) listener).message;
-        assertTrue(message, message.contains("7.10"));
+        loggings.assertNextLogContains("7.10");
+        loggings.assertNoUnexpectedLog();
 
-        assertEquals(0, listener.maximumLogCount);
         assertSame(crs, factory.createGeographicCRS("urn:ogc:def:crs:EPSG::4326"));
+        loggings.assertNoUnexpectedLog();
     }
 
     /**

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/CRSTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/CRSTest.java?rev=1731689&r1=1731688&r2=1731689&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/CRSTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/CRSTest.java [UTF-8] Mon Feb 22 17:12:02 2016
@@ -84,13 +84,7 @@ public final strictfp class CRSTest exte
         verifyForCode(CommonCRS.WGS72 .geographic3D(), "EPSG:4985");
         verifyForCode(CommonCRS.ETRS89.geographic3D(), "EPSG:4937");
         verifyForCode(CommonCRS.Vertical.MEAN_SEA_LEVEL.crs(), "EPSG:5714");
-        /*
-         * Following test is skipped when using the EPSG factory because EPSG uses
-         * the "Gravity-related depth" axis name while ISO 19111 mandates "Depth".
-         */
-        if (EPSGFactoryFallback.PENDING_NEXT_EPSG) {
-            verifyForCode(CommonCRS.Vertical.DEPTH.crs(), "EPSG:5715");
-        }
+        verifyForCode(CommonCRS.Vertical.DEPTH.crs(), "EPSG:5715");
     }
 
     /**

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/CommonCRSTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/CommonCRSTest.java?rev=1731689&r1=1731688&r2=1731689&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/CommonCRSTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/CommonCRSTest.java [UTF-8] Mon Feb 22 17:12:02 2016
@@ -167,9 +167,6 @@ public final strictfp class CommonCRSTes
             assertSame  (name, crs.getDatum(), e.datum());                      // Datum after CRS creation.
             assertEquals(name, datumName, datum.getName().getCode());
             assertEquals(name, datumType, datum.getVerticalDatumType());
-            if (!EPSGFactoryFallback.PENDING_NEXT_EPSG && e == CommonCRS.Vertical.DEPTH) {
-                continue;   // Pending the renaming of "Gravity-related depth" as "Depth" in EPSG database.
-            }
             assertEquals(name, axisName,  crs.getCoordinateSystem().getAxis(0).getName().getCode());
         }
     }

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/EPSGFactoryFallbackTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/EPSGFactoryFallbackTest.java?rev=1731689&r1=1731688&r2=1731689&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/EPSGFactoryFallbackTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/EPSGFactoryFallbackTest.java [UTF-8] Mon Feb 22 17:12:02 2016
@@ -87,6 +87,8 @@ public final strictfp class EPSGFactoryF
         verifyCreate(CommonCRS.WGS84 .geocentric(),            "4978");
         verifyCreate(CommonCRS.WGS72 .geocentric(),            "4984");
         verifyCreate(CommonCRS.ETRS89.geocentric(),            "4936");
+        verifyCreate(CommonCRS.WGS84 .geographic(),       "EPSG:4326");
+        verifyCreate(CommonCRS.WGS72 .geographic(),      "EPSG::4322");
         verifyCreate(CommonCRS.WGS84 .geographic3D(),          "4979");
         verifyCreate(CommonCRS.WGS72 .geographic3D(),          "4985");
         verifyCreate(CommonCRS.ETRS89.geographic3D(),          "4937");
@@ -125,9 +127,6 @@ public final strictfp class EPSGFactoryF
             final ArrayList<String> codes = new ArrayList<String>(EPSGFactoryFallback.INSTANCE.getAuthorityCodes(CoordinateReferenceSystem.class));
             Collections.shuffle(codes, TestUtilities.createRandomNumberGenerator());
             for (final String code : codes) {
-                if (!EPSGFactoryFallback.PENDING_NEXT_EPSG && code.equals("5715")) {
-                    continue;
-                }
                 final CoordinateReferenceSystem crs = EPSGFactoryFallback.INSTANCE.createCoordinateReferenceSystem(code);
                 final CoordinateReferenceSystem expected = EPSG.createCoordinateReferenceSystem(code);
                 assertTrue(code, Utilities.deepEquals(expected, crs, ComparisonMode.DEBUG));

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java?rev=1731689&r1=1731688&r2=1731689&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java [UTF-8] Mon Feb 22 17:12:02 2016
@@ -33,7 +33,6 @@ import org.apache.sis.internal.referenci
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.io.wkt.Convention;
-import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.LenientComparable;
 
@@ -43,6 +42,7 @@ import org.apache.sis.test.LoggingWatche
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.XMLTestCase;
+import org.junit.After;
 import org.junit.Test;
 import org.junit.Rule;
 
@@ -64,19 +64,23 @@ import static org.apache.sis.test.Refere
 public final strictfp class DefaultProjectedCRSTest extends XMLTestCase {
     /**
      * A JUnit rule for listening to log events emitted during execution of {@link #testWKT1_WithExplicitAxisLength()}.
-     * This rule verifies that the message logged contains the expected information. The expected message is something
-     * like "Parameter semi_minor could have been omitted but got a value that does not match the WGS84 ellipsoid".
+     * This rule is used by the test methods for verifying that the logged messages contain the expected information.
+     * The expected message is something like "Parameter semi_minor could have been omitted but got a value that does
+     * not match the WGS84 ellipsoid".
      *
      * <p>This field is public because JUnit requires us to do so, but should be considered as an implementation details
      * (it should have been a private field).</p>
      */
     @Rule
-    public final LoggingWatcher listener = new LoggingWatcher(Logging.getLogger(Loggers.COORDINATE_OPERATION)) {
-        @Override protected void verifyMessage(final String message) {
-            assertTrue(message, message.contains("semi_minor"));
-            assertTrue(message, message.contains("WGS84"));
-        }
-    };
+    public final LoggingWatcher loggings = new LoggingWatcher(Loggers.COORDINATE_OPERATION);
+
+    /**
+     * Verifies that no unexpected warning has been emitted in any test defined in this class.
+     */
+    @After
+    public void assertNoUnexpectedLog() {
+        loggings.assertNoUnexpectedLog();
+    }
 
     /**
      * An XML file in this package containing a projected CRS definition.
@@ -356,7 +360,6 @@ public final strictfp class DefaultProje
     @Test
     @DependsOnMethod("testWKT1")
     public void testWKT1_WithExplicitAxisLength() throws FactoryException {
-        listener.maximumLogCount = 1;
         final ProjectedCRS crs = new GeodeticObjectBuilder()
                 .setConversionMethod("Mercator (variant A)")
                 .setConversionName("Popular Visualisation Pseudo-Mercator")
@@ -386,7 +389,8 @@ public final strictfp class DefaultProje
                 "  AXIS[“Northing”, NORTH]]",
                 crs);
 
-        assertEquals("A warning should have been logged.", 0, listener.maximumLogCount);
+        loggings.assertNextLogContains("semi_minor", "WGS84");
+        loggings.assertNoUnexpectedLog();
     }
 
     /**

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactoryTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactoryTest.java?rev=1731689&r1=1731688&r2=1731689&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactoryTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactoryTest.java [UTF-8] Mon Feb 22 17:12:02 2016
@@ -39,11 +39,11 @@ import org.apache.sis.internal.system.Lo
 import org.apache.sis.metadata.iso.extent.Extents;
 import org.apache.sis.referencing.crs.HardCodedCRS;
 import org.apache.sis.referencing.datum.HardCodedDatum;
-import org.apache.sis.util.logging.Logging;
 import org.apache.sis.test.LoggingWatcher;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
+import org.junit.After;
 import org.junit.Rule;
 import org.junit.Test;
 
@@ -61,28 +61,18 @@ import static org.apache.sis.test.Assert
 @DependsOn(AuthorityFactoryProxyTest.class)
 public final strictfp class MultiAuthoritiesFactoryTest extends TestCase {
     /**
-     * A JUnit {@linkplain Rule rule} for listening to log events. This field is public because JUnit requires
-     * us to do so, but should be considered as an implementation details (it should have been a private field).
+     * A JUnit {@link Rule} for listening to log events. This field is public because JUnit requires us to
+     * do so, but should be considered as an implementation details (it should have been a private field).
      */
     @Rule
-    public final LoggingWatcher listener = new Listener();
+    public final LoggingWatcher loggings = new LoggingWatcher(Loggers.CRS_FACTORY);
 
     /**
-     * Implementation of the {@link MultiAuthoritiesFactoryTest#listener} rule.
+     * Verifies that no unexpected warning has been emitted in any test defined in this class.
      */
-    private static final class Listener extends LoggingWatcher {
-        /** Expected keywords in the log message. */
-        String[] expectedKeywords;
-
-        /** Creates a new log listener. */
-        Listener() {super(Logging.getLogger(Loggers.CRS_FACTORY));}
-
-        /** Verifies the log message. */
-        @Override protected void verifyMessage(final String message) {
-            for (final String keyword : expectedKeywords) {
-                assertTrue(message, message.contains(keyword));
-            }
-        }
+    @After
+    public void assertNoUnexpectedLog() {
+        loggings.assertNoUnexpectedLog();
     }
 
     /**
@@ -182,20 +172,20 @@ public final strictfp class MultiAuthori
 
         assertSame("MOCK1", mock1, factory.getAuthorityFactory(CRSAuthorityFactory.class, "mock1", null));
         assertSame("MOCK1", mock1, factory.getAuthorityFactory(CRSAuthorityFactory.class, "mock1", "2.3"));
+        loggings.assertNoUnexpectedLog();
 
-        listener.maximumLogCount = 1;
-        ((Listener) listener).expectedKeywords = new String[] {"CRSAuthorityFactory", "AuthorityFactoryMock", "MOCK1", "2.3"};
         assertSame("MOCK3", mock3, factory.getAuthorityFactory(CRSAuthorityFactory.class, "mock3", null));
-        assertEquals("Expected a warning about the extraneous MOCK1 factory.", 0, listener.maximumLogCount);
+        loggings.assertNextLogContains("CRSAuthorityFactory", "AuthorityFactoryMock", "MOCK1", "2.3");
+        loggings.assertNoUnexpectedLog();
 
-        listener.maximumLogCount = 1;
-        ((Listener) listener).expectedKeywords = new String[] {"CRSAuthorityFactory", "AuthorityFactoryMock", "MOCK3"};
         assertSame("MOCK5", mock5, factory.getAuthorityFactory(CRSAuthorityFactory.class, "mock5", null));
-        assertEquals("Expected a warning about the extraneous MOCK3 factory.", 0, listener.maximumLogCount);
+        loggings.assertNextLogContains("CRSAuthorityFactory", "AuthorityFactoryMock", "MOCK3");
+        loggings.assertNoUnexpectedLog();
 
         // Ask again the same factories. No logging should be emitted now, because we already logged.
         assertSame("MOCK3", mock3, factory.getAuthorityFactory(CRSAuthorityFactory.class, "mock3", null));
         assertSame("MOCK5", mock5, factory.getAuthorityFactory(CRSAuthorityFactory.class, "mock5", null));
+        loggings.assertNoUnexpectedLog();
     }
 
     /**
@@ -325,10 +315,9 @@ public final strictfp class MultiAuthori
         /*
          * Following should log a warning telling that the authority factories do not match.
          */
-        listener.maximumLogCount = 1;
-        ((Listener) listener).expectedKeywords = new String[] {"MOCK:4326", "MOCK:2.3:84"};
         assertTrue(factory.createFromCoordinateReferenceSystemCodes("MOCK:4326", "MOCK:2.3:84").isEmpty());
-        assertEquals("Expected a warning about mismatched factories.", 0, listener.maximumLogCount);
+        loggings.assertNextLogContains("MOCK:4326", "MOCK:2.3:84");
+        loggings.assertNoUnexpectedLog();
     }
 
     /**

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGFactoryTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGFactoryTest.java?rev=1731689&r1=1731688&r2=1731689&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGFactoryTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGFactoryTest.java [UTF-8] Mon Feb 22 17:12:02 2016
@@ -63,6 +63,7 @@ import org.apache.sis.referencing.factor
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.Ignore;
+import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.apache.sis.test.TestCase;
@@ -116,7 +117,7 @@ public final strictfp class EPSGFactoryT
     }
 
     /**
-     * Force releases of JDBC connections after the tests in this class.
+     * Forces release of JDBC connections after the tests in this class.
      *
      * @throws FactoryException if an error occurred while closing the connections.
      */
@@ -129,29 +130,19 @@ public final strictfp class EPSGFactoryT
     }
 
     /**
-     * Words that we expect to find in each log messages to be emitted.
+     * A JUnit {@link Rule} for listening to log events. This field is public because JUnit requires us to
+     * do so, but should be considered as an implementation details (it should have been a private field).
      */
-    private String[][] expectedLogWords;
+    @Rule
+    public final LoggingWatcher loggings = new LoggingWatcher(Loggers.CRS_FACTORY);
 
     /**
-     * A JUnit {@linkplain Rule rule} for listening to log events. This field is public
-     * because JUnit requires us to do so, but should be considered as an implementation
-     * details (it should have been a private field).
+     * Verifies that no unexpected warning has been emitted in any test defined in this class.
      */
-    @Rule
-    public final LoggingWatcher listener = new LoggingWatcher(Logging.getLogger(Loggers.CRS_FACTORY)) {
-        /**
-         * Ensures that the logging message contains some expected words.
-         */
-        @Override
-        protected void verifyMessage(final String message) {
-            if (expectedLogWords != null) {
-                for (final String word : expectedLogWords[expectedLogWords.length - (maximumLogCount + 1)]) {
-                    assertTrue(message, message.contains(word));
-                }
-            }
-        }
-    };
+    @After
+    public void assertNoUnexpectedLog() {
+        loggings.assertNoUnexpectedLog();
+    }
 
     /**
      * Tests {@link EPSGDataAccess#tableMatches(String, String)}.
@@ -163,7 +154,7 @@ public final strictfp class EPSGFactoryT
     }
 
     /**
-     * Tests the "WGS 84" geographic CRS (EPSG::4326).
+     * Tests the "WGS 84" geographic CRS (EPSG:4326).
      *
      * @throws FactoryException if an error occurred while querying the factory.
      */
@@ -173,16 +164,17 @@ public final strictfp class EPSGFactoryT
         final GeographicCRS crs = factory.createGeographicCRS("EPSG:4326");
         assertEpsgNameAndIdentifierEqual("WGS 84", 4326, crs);
         assertEpsgNameAndIdentifierEqual("World Geodetic System 1984", 6326, crs.getDatum());
-        assertAxisDirectionsEqual("EPSG::6422", crs.getCoordinateSystem(), AxisDirection.NORTH, AxisDirection.EAST);
+        assertAxisDirectionsEqual("EPSG:6422", crs.getCoordinateSystem(), AxisDirection.NORTH, AxisDirection.EAST);
 
         final BursaWolfParameters[] bwp = ((DefaultGeodeticDatum) crs.getDatum()).getBursaWolfParameters();
         assertEquals("Expected no Bursa-Wolf parameters.", 0, bwp.length);
 
         assertSame("CRS shall be cached", crs, factory.createCoordinateReferenceSystem("4326"));
+        assertSame("Shall accept \"::\"", crs, factory.createGeographicCRS("EPSG::4326"));
     }
 
     /**
-     * Tests the "Datum 73" geographic CRS (EPSG::4274), which has a datum different than the WGS84 one.
+     * Tests the "Datum 73" geographic CRS (EPSG:4274), which has a datum different than the WGS84 one.
      *
      * @throws FactoryException if an error occurred while querying the factory.
      */
@@ -202,7 +194,7 @@ public final strictfp class EPSGFactoryT
     }
 
     /**
-     * Tests the "Lao 1997" geographic CRS (EPSG::4993) with an ellipsoidal height.
+     * Tests the "Lao 1997" geographic CRS (EPSG:4993) with an ellipsoidal height.
      *
      * @throws FactoryException if an error occurred while querying the factory.
      */
@@ -220,7 +212,7 @@ public final strictfp class EPSGFactoryT
     }
 
     /**
-     * Tests the "ITRF93" geocentric CRS (EPSG::4915).
+     * Tests the "ITRF93" geocentric CRS (EPSG:4915).
      *
      * @throws FactoryException if an error occurred while querying the factory.
      */
@@ -237,7 +229,7 @@ public final strictfp class EPSGFactoryT
     }
 
     /**
-     * Tests the "NAD27(76) / UTM zone 15N" projected CRS (EPSG::2027).
+     * Tests the "NAD27(76) / UTM zone 15N" projected CRS (EPSG:2027).
      *
      * @throws FactoryException if an error occurred while querying the factory.
      */
@@ -273,7 +265,7 @@ public final strictfp class EPSGFactoryT
     }
 
     /**
-     * Tests the "Beijing 1954 / 3-degree Gauss-Kruger CM 135E" projected CRS (EPSG::2442).
+     * Tests the "Beijing 1954 / 3-degree Gauss-Kruger CM 135E" projected CRS (EPSG:2442).
      * This projected CRS has (North, East) axis orientations instead of (East, North).
      *
      * @throws FactoryException if an error occurred while querying the factory.
@@ -409,7 +401,7 @@ public final strictfp class EPSGFactoryT
     }
 
     /**
-     * Tests the "Barcelona Grid B1" engineering CRS (EPSG::5801).
+     * Tests the "Barcelona Grid B1" engineering CRS (EPSG:5801).
      *
      * @throws FactoryException if an error occurred while querying the factory.
      */
@@ -454,43 +446,80 @@ public final strictfp class EPSGFactoryT
         final List<CoordinateReferenceSystem> components = crs.getComponents();
         assertEquals("components.size()", 2, components.size());
         assertEpsgNameAndIdentifierEqual("NTF (Paris)",      4807, components.get(0));
-        assertEpsgNameAndIdentifierEqual("NGF IGN69 height", 5720, components.get(1));
+        assertEpsgNameAndIdentifierEqual("NGF-IGN69 height", 5720, components.get(1));
 
         assertAxisDirectionsEqual("(no EPSG code)", crs.getCoordinateSystem(),
                 AxisDirection.NORTH, AxisDirection.EAST, AxisDirection.UP);
 
         final GeographicBoundingBox bbox = CRS.getGeographicBoundingBox(crs);
         assertNotNull("No bounding box. Maybe an older EPSG database is used?", bbox);
-        assertEquals("southBoundLatitude", 42.25, bbox.getSouthBoundLatitude(), STRICT);
-        assertEquals("northBoundLatitude", 51.10, bbox.getNorthBoundLatitude(), STRICT);
-        assertEquals("westBoundLongitude", -5.20, bbox.getWestBoundLongitude(), STRICT);
+        assertEquals("southBoundLatitude", 42.33, bbox.getSouthBoundLatitude(), STRICT);
+        assertEquals("northBoundLatitude", 51.14, bbox.getNorthBoundLatitude(), STRICT);
+        assertEquals("westBoundLongitude", -4.87, bbox.getWestBoundLongitude(), STRICT);
         assertEquals("eastBoundLongitude",  8.23, bbox.getEastBoundLongitude(), STRICT);
 
         assertSame("CRS shall be cached", crs, factory.createCoordinateReferenceSystem("7400"));
     }
 
     /**
+     * Tests creation of deprecated coordinate systems.
+     *
+     * @throws FactoryException if an error occurred while querying the factory.
+     */
+    @Test
+    public void testDeprecatedCoordinateSystems() throws FactoryException {
+        assumeNotNull(factory);
+        for (final Map.Entry<Integer,Integer> entry : EPSGDataAccess.deprecatedCS().entrySet()) {
+            final CoordinateSystem expected = factory.createEllipsoidalCS(entry.getValue().toString());
+            loggings.assertNoUnexpectedLog();
+            final String code = entry.getKey().toString();
+            final CoordinateSystem deprecated;
+            try {
+                deprecated = factory.createEllipsoidalCS(code);
+            } catch (FactoryException e) {
+                final String m = e.getMessage();
+                if (m.contains("9115") || m.contains("9116") || m.contains("9117") ||
+                    m.contains("9118") || m.contains("9119") || m.contains("9120"))
+                {
+                    // Unit "9116" to "9120" are known to be unsupported.
+                    continue;
+                }
+                throw e;
+            }
+            loggings.assertNextLogContains(code);
+            final int dimension = expected.getDimension();
+            assertEquals("dimension", dimension, deprecated.getDimension());
+            for (int i=0; i<dimension; i++) {
+                final CoordinateSystemAxis ref  = expected.getAxis(i);
+                final CoordinateSystemAxis axis = deprecated.getAxis(i);
+                assertEquals("name",         ref.getName(),         axis.getName());
+                assertEquals("alias",        ref.getAlias(),        axis.getAlias());
+                assertEquals("direction",    ref.getDirection(),    axis.getDirection());
+                assertEquals("rangeMeaning", ref.getRangeMeaning(), axis.getRangeMeaning());
+                assertEquals("unit",         ref.getUnit().toSI(),  axis.getUnit().toSI());
+            }
+        }
+    }
+
+    /**
      * Tests a legacy geographic CRS (no longer supported by EPSG).
      * This test verifies that the expected warnings are logged.
      *
      * @throws FactoryException if an error occurred while querying the factory.
      */
     @Test
-    @DependsOnMethod("testGeographic2D")
+    @DependsOnMethod({"testGeographic2D", "testDeprecatedCoordinateSystems"})
     public void testDeprecatedGeographic() throws FactoryException {
         assumeNotNull(factory);
 
-        listener.maximumLogCount = 2;
-        expectedLogWords = new String[][] {
-            {"EPSG:6405"},                      // Coordinate System 6405 is no longer supported by EPSG
-            {"EPSG:63266405", "4326"}           // EPSG no longer support codes in the 60000000 series.
-        };
-
         final GeographicCRS crs = factory.createGeographicCRS("63266405");
         assertEpsgNameAndIdentifierEqual("WGS 84 (deg)", 63266405, crs);
         assertAxisDirectionsEqual(null, crs.getCoordinateSystem(), AxisDirection.NORTH, AxisDirection.EAST);
-
         assertSame("CRS shall be cached", crs, factory.createCoordinateReferenceSystem("63266405"));
+
+        loggings.skipNextLogIfContains("EPSG:6405");                 // Coordinate System 6405 is no longer supported by EPSG
+        loggings.assertNextLogContains("EPSG:63266405", "4326");     // EPSG no longer support codes in the 60000000 series.
+        loggings.assertNoUnexpectedLog();
     }
 
     /**
@@ -500,22 +529,19 @@ public final strictfp class EPSGFactoryT
      * @throws FactoryException if an error occurred while querying the factory.
      */
     @Test
-    @DependsOnMethod("testDeprecatedGeographic")
+    @DependsOnMethod({"testDeprecatedGeographic", "testDeprecatedCoordinateSystems"})
     public void testDeprecatedProjected() throws FactoryException {
         assumeNotNull(factory);
 
-        listener.maximumLogCount = 3;
-        expectedLogWords = new String[][] {
-            {"EPSG:9823",  "1029"},              // Operation method 9823 has been replaced by 1029
-            {"EPSG:19968", "4086"},              // Coordinate Operation 19968 has been replaced by 4086
-            {"EPSG:3786",  "4088"}               // Coordinate Reference System 3786 has been replaced by 4088
-        };
-
         final ProjectedCRS crs = factory.createProjectedCRS("3786");
         assertEpsgNameAndIdentifierEqual("World Equidistant Cylindrical (Sphere)", 3786, crs);
         assertEpsgNameAndIdentifierEqual("Equidistant Cylindrical (Spherical)", 9823, crs.getConversionFromBase().getMethod());
         assertAxisDirectionsEqual("EPSG::4499", crs.getCoordinateSystem(), AxisDirection.EAST, AxisDirection.NORTH);
-        assertEquals("All warnings should have been logged at this point.", 0, listener.maximumLogCount);
+
+        loggings.assertNextLogContains("EPSG:9823",  "1029");    // Operation method 9823 has been replaced by 1029
+        loggings.assertNextLogContains("EPSG:19968", "4086");    // Coordinate Operation 19968 has been replaced by 4086
+        loggings.assertNextLogContains("EPSG:3786",  "4088");    // Coordinate Reference System 3786 has been replaced by 4088
+        loggings.assertNoUnexpectedLog();
 
         final ProjectedCRS replacement = factory.createProjectedCRS("4088");
         assertEpsgNameAndIdentifierEqual("World Equidistant Cylindrical (Sphere)", 4088, replacement);
@@ -589,7 +615,7 @@ public final strictfp class EPSGFactoryT
 
         final Set<String> ellipsoids = factory.getAuthorityCodes(Ellipsoid.class);
         assertFalse("Ellipsoid not found.",       ellipsoids.isEmpty());
-        assertTrue ("Check size() consistency.",  ellipsoids.size() >= 49);
+        assertTrue ("Check size() consistency.",  ellipsoids.size() >= 48);
         assertTrue ("Shall contain WGS84.",       ellipsoids.contains("7030"));
         assertTrue ("Shall contain GRS 1980.",    ellipsoids.contains("7019"));
 
@@ -743,7 +769,7 @@ public final strictfp class EPSGFactoryT
     }
 
     /**
-     * Tests the "UTM zone 10N" conversion (EPSG::16010).
+     * Tests the "UTM zone 10N" conversion (EPSG:16010).
      *
      * @throws FactoryException if an error occurred while querying the factory.
      */
@@ -789,7 +815,7 @@ public final strictfp class EPSGFactoryT
         } catch (AssertionError error) {
             out.println("The following contains more information about a JUnit test failure.");
             out.println("See the JUnit report for the stack trace. Below is a cache dump.");
-            out.println("See the operation method EPSG::9807 and compare with:");
+            out.println("See the operation method EPSG:9807 and compare with:");
             out.print  ("  - Method obtained directly:   "); out.println(System.identityHashCode(copMethod));
             out.print  ("  - Method obtained indirectly: "); out.println(System.identityHashCode(crsMethod));
             out.println("Content of EPSGFactory cache:");
@@ -799,7 +825,7 @@ public final strictfp class EPSGFactoryT
     }
 
     /**
-     * Tests longitude rotation (EPSG::1764). This is a very simple case for checking
+     * Tests longitude rotation (EPSG:1764). This is a very simple case for checking
      * that this part is okay before to try more complex transformations.
      *
      * @throws FactoryException if an error occurred while querying the factory.
@@ -809,13 +835,13 @@ public final strictfp class EPSGFactoryT
         assumeNotNull(factory);
         final CoordinateOperation operation = factory.createCoordinateOperation("1764");
         assertEpsgNameAndIdentifierEqual("NTF (Paris) to NTF (2)", 1764, operation);
-        assertInstanceOf("EPSG::1764", Transformation.class, operation);
+        assertInstanceOf("EPSG:1764", Transformation.class, operation);
         assertSame("Operation shall be cached", operation, factory.createCoordinateOperation("1764"));
     }
 
     /**
-     * Tests "BD72 to WGS 84 (1)" (EPSG::1609) transformation. This one has an unusual unit for the
-     * "Scale difference" parameter (EPSG::8611). The value is 0.999999 and the unit is "unity" (EPSG::9201)
+     * Tests "BD72 to WGS 84 (1)" (EPSG:1609) transformation. This one has an unusual unit for the
+     * "Scale difference" parameter (EPSG:8611). The value is 0.999999 and the unit is "unity" (EPSG:9201)
      * instead of the usual "parts per million" (EPSG:9202).
      *
      * @throws FactoryException if an error occurred while querying the factory.
@@ -892,7 +918,6 @@ public final strictfp class EPSGFactoryT
         assertTrue("contains(“EPSG::1989”)", all.contains(operation3));
 
         int count = 0;
-        listener.maximumLogCount = all.size();              // Ignore log message for unsupported operation methods.
         for (final CoordinateOperation tr : all) {
             assertSame("sourceCRS", sourceCRS, tr.getSourceCRS());
             assertSame("targetCRS", targetCRS, tr.getTargetCRS());
@@ -902,6 +927,7 @@ public final strictfp class EPSGFactoryT
             count++;
         }
         assertEquals(count, all.size());        // Size may have been modified after above loop.
+        loggings.clear();                       // Too installation-dependent for testing them.
     }
 
     /**
@@ -924,7 +950,7 @@ public final strictfp class EPSGFactoryT
                 "  AXIS[“Geodetic longitude”, EAST]]");
         /*
          * First, search for a CRS with axis order that does not match the ones in the EPSG database.
-         * IdentifiedObjectFinder should not accept EPSG::4326 as a match for the given CRS.
+         * IdentifiedObjectFinder should not accept EPSG:4326 as a match for the given CRS.
          */
         assertEquals("Full scan should be enabled by default.",
                 IdentifiedObjectFinder.Domain.VALID_DATASET, finder.getSearchDomain());

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=1731689&r1=1731688&r2=1731689&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] Mon Feb 22 17:12:02 2016
@@ -17,25 +17,35 @@
 package org.apache.sis.referencing.factory.sql;
 
 import java.util.Map;
+import java.util.Set;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.regex.Pattern;
+import javax.sql.DataSource;
 import java.sql.Connection;
+import java.sql.Statement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import javax.sql.DataSource;
 import org.opengis.util.FactoryException;
 import org.opengis.referencing.crs.GeographicCRS;
+import org.opengis.referencing.crs.ProjectedCRS;
 import org.apache.sis.referencing.CommonCRS;
-import org.apache.sis.internal.metadata.sql.TestDatabase;
+import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.Utilities;
+
+// Test dependencies
+import org.apache.sis.internal.metadata.sql.TestDatabase;
+import org.apache.sis.test.LoggingWatcher;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
+import org.junit.After;
+import org.junit.Ignore;
+import org.junit.Rule;
 import org.junit.Test;
 
 import static org.junit.Assert.*;
-
-// Branch-dependent imports
-import org.apache.sis.internal.jdk7.Path;
+import static org.junit.Assume.*;
 
 
 /**
@@ -54,35 +64,150 @@ import org.apache.sis.internal.jdk7.Path
 @DependsOn(EPSGFactoryTest.class)
 public final strictfp class EPSGInstallerTest extends TestCase {
     /**
+     * A JUnit rule for listening to log events emitted during execution of tests.
+     * This rule is used by tests that verifies the log message content.
+     *
+     * <p>This field is public because JUnit requires us to do so, but should be considered
+     * as an implementation details (it should have been a private field).</p>
+     */
+    @Rule
+    public final LoggingWatcher loggings = new LoggingWatcher(Loggers.CRS_FACTORY);
+
+    /**
+     * Verifies that no unexpected warning has been emitted in any test defined in this class.
+     */
+    @After
+    public void assertNoUnexpectedLog() {
+        loggings.assertNoUnexpectedLog();
+    }
+
+    /**
+     * Tests the {@link EPSGInstaller#REPLACE_STATEMENT} pattern.
+     */
+    @Test
+    public void testReplacePattern() {
+        // Statement as in the EPSG scripts since EPSG version 7.06.
+        assertTrue(Pattern.matches(EPSGInstaller.REPLACE_STATEMENT,
+                "UPDATE epsg_datum\n" +
+                "SET datum_name = replace(datum_name, CHR(182), CHR(10))"));
+
+        // Statement as in the EPSG scripts prior to EPSG version 7.06.
+        assertTrue(Pattern.matches(EPSGInstaller.REPLACE_STATEMENT,
+                "UPDATE epsg_datum\n" +
+                "SET datum_name = replace(datum_name, CHAR(182), CHAR(10))"));
+
+        // Modified statement with MS-Access table name in a schema.
+        assertTrue(Pattern.matches(EPSGInstaller.REPLACE_STATEMENT,
+                "UPDATE epsg.\"Alias\"\n" +
+                "SET object_table_name = replace(object_table_name, CHR(182), CHR(10))"));
+
+        // Like above, but the table name contains a space.
+        assertTrue(Pattern.matches(EPSGInstaller.REPLACE_STATEMENT,
+                "UPDATE epsg.\"Coordinate Axis\"\n" +
+                "SET coord_axis_orientation = replace(coord_axis_orientation, CHR(182), CHR(10))"));
+    }
+
+    /**
+     * Returns the SQL scripts needed for testing the database creation,
+     * or skip the JUnit test if those scripts are not found.
+     */
+    private static InstallationScriptProvider getScripts() {
+        final InstallationScriptProvider scripts = new InstallationScriptProvider.Default();
+        assumeTrue(scripts.getAuthority().equals("EPSG"));
+        return scripts;
+    }
+
+    /**
      * Tests the creation of an EPSG database on Derby.
-     * This test is skipped if no Derby or JavaDB driver has been found.
+     * This test is skipped if Derby/JavaDB is not found, or if the SQL scripts are not found.
      *
      * @throws Exception if an error occurred while creating the database.
      */
     @Test
     public void testCreationOnDerby() throws Exception {
-        final Path scripts = TestDatabase.directory("ExternalSources");
+        final InstallationScriptProvider scripts = getScripts();            // Needs to be invoked first.
         final DataSource ds = TestDatabase.create("test");
         try {
             createAndTest(ds, scripts);
         } finally {
             TestDatabase.drop(ds);
         }
+        loggings.assertNextLogContains("EPSG", "jdbc:derby:memory:test");
+        loggings.assertNoUnexpectedLog();
+    }
+
+    /**
+     * Tests the creation of an EPSG database on HSQLDB.
+     * This test is skipped if the SQL scripts are not found.
+     *
+     * <p>This test is skipped by default because HSQLDB changes the {@code java.util.logging} configuration,
+     * which causes failures in all Apache SIS tests that verify the logging messages after execution of this
+     * test. This impact this {@code EPSGInstallerTest} class, but also other test classes.</p>
+     *
+     * @throws Exception if an error occurred while creating the database.
+     */
+    @Test
+    @Ignore("Skipped for protecting java.util.logging configuration against changes.")
+    public void testCreationOnHSQLDB() throws Exception {
+        final InstallationScriptProvider scripts = getScripts();            // Needs to be invoked first.
+        final DataSource ds = (DataSource) Class.forName("org.hsqldb.jdbc.JDBCDataSource").newInstance();
+        ds.getClass().getMethod("setURL", String.class).invoke(ds, "jdbc:hsqldb:mem:test");
+        try {
+            createAndTest(ds, scripts);
+        } finally {
+            final Connection c = ds.getConnection(); Statement s = c.createStatement();
+            try {
+                s.execute("SHUTDOWN");
+            } finally {
+                c.close();
+            }
+        }
+        loggings.assertNextLogContains("EPSG", "jdbc:hsqldb:mem:test");
+        loggings.assertNoUnexpectedLog();
     }
 
     /**
-     * Requests the WGS84 coordinate reference system from the EPSG database at the given source.
-     * It should trig the creation of the EPSG database.
+     * Requests the "WGS84" and the "WGS72 / UTM zone 15N" coordinate reference systems from the EPSG database
+     * at the given {@code DataSource}. Those requests should trig the creation of the EPSG database.
      */
-    private static void createAndTest(final DataSource ds, final Path scripts) throws SQLException, FactoryException {
+    private void createAndTest(final DataSource ds, final InstallationScriptProvider scriptProvider)
+            throws SQLException, FactoryException
+    {
         final Map<String,Object> properties = new HashMap<String,Object>();
         assertNull(properties.put("dataSource", ds));
-        assertNull(properties.put("scriptDirectory", scripts));
+        assertNull(properties.put("scriptProvider", scriptProvider));
         assertEquals("Should not contain EPSG tables before we created them.", 0, countCRSTables(ds));
+        loggings.assertNoUnexpectedLog();       // Should not yet have logged anything at this point.
+
         final EPSGFactory factory = new EPSGFactory(properties);
         try {
+            /*
+             * Fetch the "WGS 84" coordinate reference system.
+             */
             final GeographicCRS crs = factory.createGeographicCRS("4326");
             assertTrue(Utilities.deepEquals(CommonCRS.WGS84.geographic(), crs, ComparisonMode.DEBUG));
+            /*
+             * Fetch the "WGS 72 / UTM zone 15" coordinate system.
+             * This implies the creation of a coordinate operation.
+             */
+            final ProjectedCRS p = factory.createProjectedCRS("EPSG:32215");
+            assertTrue(Utilities.deepEquals(CommonCRS.WGS72.UTM(1, -93), p, ComparisonMode.DEBUG));
+            /*
+             * Get the authority codes. We choose a type that implies an SQL statement
+             * with both "DEPRECATED" and "SHOW_CRS" conditions in their "WHERE" clause.
+             */
+            Set<String> codes = factory.getAuthorityCodes(GeographicCRS.class);
+            assertTrue("4979", codes.contains("4979"));     // A non-deprecated code.
+            assertTrue("4329", codes.contains("4329"));     // A deprecated code.
+            /*
+             * Following forces the authority factory to iterate over all codes.
+             * Since the iterator returns only non-deprecated codes, EPSG:4329
+             * should not be included. The intend is to verify that the fields
+             * of type BOOLEAN have been properly handled.
+             */
+            codes = new HashSet<String>(codes);
+            assertTrue ("4979", codes.contains("4979"));
+            assertFalse("4329", codes.contains("4329"));
         } finally {
             factory.close();
         }

Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/integration/DefaultMetadataTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/integration/DefaultMetadataTest.java?rev=1731689&r1=1731688&r2=1731689&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/integration/DefaultMetadataTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/integration/DefaultMetadataTest.java [UTF-8] Mon Feb 22 17:12:02 2016
@@ -50,16 +50,20 @@ import org.apache.sis.referencing.cs.Def
 import org.apache.sis.referencing.crs.DefaultVerticalCRS;
 import org.apache.sis.internal.jaxb.metadata.replace.ReferenceSystemMetadata;
 import org.apache.sis.internal.jaxb.gmx.Anchor;
+import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.referencing.NamedIdentifier;
 import org.apache.sis.util.iso.SimpleInternationalString;
 import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.xml.Namespaces;
 import org.apache.sis.xml.MarshallerPool;
 import org.apache.sis.xml.IdentifierSpace;
+import org.apache.sis.test.LoggingWatcher;
 import org.apache.sis.test.TestUtilities;
 import org.apache.sis.test.XMLComparator;
 import org.apache.sis.test.XMLTestCase;
 import org.apache.sis.test.DependsOn;
+import org.junit.After;
+import org.junit.Rule;
 import org.junit.Test;
 
 import static org.apache.sis.test.Assert.*;
@@ -86,6 +90,21 @@ import org.apache.sis.internal.geoapi.ev
 @DependsOn(ReferencingInMetadataTest.class)
 public strictfp class DefaultMetadataTest extends XMLTestCase {
     /**
+     * A JUnit {@link Rule} for listening to log events. This field is public because JUnit requires us to
+     * do so, but should be considered as an implementation details (it should have been a private field).
+     */
+    @Rule
+    public final LoggingWatcher loggings = new LoggingWatcher(Loggers.XML);
+
+    /**
+     * Verifies that no unexpected warning has been emitted in any test defined in this class.
+     */
+    @After
+    public void assertNoUnexpectedLog() {
+        loggings.assertNoUnexpectedLog();
+    }
+
+    /**
      * Sets the temporal extent. The current implementation does nothing, because {@code sis-metadata} does not have
      * any dependency to {@code sis-temporal}. However a future version or an other module may implement this method.
      *
@@ -415,5 +434,6 @@ public strictfp class DefaultMetadataTes
         pool.recycle(unmarshaller);
         final DefaultMetadata expected = createHardCoded();
         assertTrue(metadata.equals(expected, ComparisonMode.DEBUG));
+        loggings.skipNextLogIfContains("sis-temporal");
     }
 }

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=1731689&r1=1731688&r2=1731689&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] Mon Feb 22 17:12:02 2016
@@ -185,6 +185,7 @@ import org.junit.BeforeClass;
     org.apache.sis.referencing.factory.MultiAuthoritiesFactoryTest.class,
     org.apache.sis.referencing.factory.sql.EPSGFactoryTest.class,
     org.apache.sis.referencing.factory.sql.EPSGInstallerTest.class,
+    org.apache.sis.referencing.factory.sql.EPSGDataFormatterTest.class,
     org.apache.sis.referencing.EPSGFactoryFallbackTest.class,
     org.apache.sis.referencing.AuthorityFactoriesTest.class,
     org.apache.sis.referencing.CRSTest.class,

Modified: sis/trunk/core/sis-referencing/src/test/resources/org/apache/sis/referencing/operation/Conversion.xml
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/resources/org/apache/sis/referencing/operation/Conversion.xml?rev=1731689&r1=1731688&r2=1731689&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/test/resources/org/apache/sis/referencing/operation/Conversion.xml (original)
+++ sis/trunk/core/sis-referencing/src/test/resources/org/apache/sis/referencing/operation/Conversion.xml Mon Feb 22 17:12:02 2016
@@ -26,7 +26,7 @@
                 xmlns:xlink        = "http://www.w3.org/1999/xlink"
                 gml:id             = "WorldMercator">
 
-  <gml:identifier codeSpace="test">3395</gml:identifier>  <!-- Not the real EPSG::3395 -->
+  <gml:identifier codeSpace="test">3395</gml:identifier>                    <!-- Not the real EPSG:3395 -->
   <gml:name>World Mercator</gml:name>
   <gml:domainOfValidity>
     <gmd:EX_Extent>
@@ -64,7 +64,7 @@
   </gml:coordinateOperationAccuracy>
   <gml:method>
     <gml:OperationMethod gml:id="Mercator">
-      <gml:identifier codeSpace="test">19883</gml:identifier>  <!-- Not the real EPSG::19883 -->
+      <gml:identifier codeSpace="test">19883</gml:identifier>               <!-- Not the real EPSG:19883 -->
       <gml:name>Mercator (1SP)</gml:name>
       <gml:formula>See EPSG guide.</gml:formula>
       <gml:sourceDimensions>2</gml:sourceDimensions>




Mime
View raw message