You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2016/02/05 23:41:48 UTC
svn commit: r1728765 - in /sis/branches/JDK8/core:
sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/
sis-metadata/src/test/java/org/apache/sis/internal/metadata/sql/
sis-referencing/src/main/java/org/apache/sis/internal/referencing/ sis-...
Author: desruisseaux
Date: Fri Feb 5 22:41:47 2016
New Revision: 1728765
URL: http://svn.apache.org/viewvc?rev=1728765&view=rev
Log:
More tests of EPSGInstaller. Creation of EPSG database has been successfully tested on Derby and PostgreSQL.
Modified:
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java
sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/internal/metadata/sql/TestDatabase.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DatabaseListener.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/report/CoordinateReferenceSystems.java
Modified: sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java?rev=1728765&r1=1728764&r2=1728765&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java [UTF-8] Fri Feb 5 22:41:47 2016
@@ -398,7 +398,7 @@ public abstract class Initializer {
ds.getConnection().close(); // Does the actual shutdown.
} catch (SQLException e) { // This is the expected exception.
final LogRecord record = new LogRecord(Level.CONFIG, e.getLocalizedMessage());
- if (!isNormalShutdown(e)) {
+ if (!isSuccessfulShutdown(e)) {
record.setLevel(Level.WARNING);
record.setThrown(e);
}
@@ -409,12 +409,12 @@ public abstract class Initializer {
}
/**
- * Returns {@code true} if the given exception is the one that we expect in a normal shutdown of a Derby database.
+ * Returns {@code true} if the given exception is the one that we expect in successful shutdown of a Derby database.
*
* @param e The exception thrown by Derby.
* @return {@code true} if the exception indicates a successful shutdown.
*/
- static boolean isNormalShutdown(final SQLException e) {
+ static boolean isSuccessfulShutdown(final SQLException e) {
return e.getErrorCode() == 45000 && "08006".equals(e.getSQLState());
}
}
Modified: sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java?rev=1728765&r1=1728764&r2=1728765&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java [UTF-8] Fri Feb 5 22:41:47 2016
@@ -581,7 +581,7 @@ parseLine: while (pos < length) {
}
}
// The remaining of the statement to be executed.
- int end = CharSequences.skipTrailingWhitespaces(sql, begin, sql.length());
+ int end = CharSequences.skipTrailingWhitespaces(subSQL, begin, subSQL.length());
subSQL = (end > begin) ? sql.append(subSQL, begin, end).toString() : null;
}
}
Modified: sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/internal/metadata/sql/TestDatabase.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/internal/metadata/sql/TestDatabase.java?rev=1728765&r1=1728764&r2=1728765&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/internal/metadata/sql/TestDatabase.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/internal/metadata/sql/TestDatabase.java [UTF-8] Fri Feb 5 22:41:47 2016
@@ -106,9 +106,9 @@ public final strictfp class TestDatabase
ds.getClass().getMethod("setCreateDatabase", String.class).invoke(ds, "no");
ds.getClass().getMethod("setConnectionAttributes", String.class).invoke(ds, "drop=true");
try {
- ds.getConnection();
+ ds.getConnection().close();
} catch (SQLException e) { // This is the expected exception.
- if (!Initializer.isNormalShutdown(e)) {
+ if (!Initializer.isSuccessfulShutdown(e)) {
throw e;
}
}
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DatabaseListener.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DatabaseListener.java?rev=1728765&r1=1728764&r2=1728765&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DatabaseListener.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DatabaseListener.java [UTF-8] Fri Feb 5 22:41:47 2016
@@ -47,7 +47,9 @@ public final class DatabaseListener exte
}
/**
- * Invoked when a new database is created.
+ * Invoked when a new database is created. The current Apache SIS version does not create the EPSG database
+ * immediately. We rather rely on automatic installation by {@code EPSGInstaller} the first time that a CRS
+ * is requested. However we may revisit this policy in a future SIS version.
*
* @param connection Connection to the empty database.
* @throws SQLException if an error occurred while populating the database.
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java?rev=1728765&r1=1728764&r2=1728765&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java [UTF-8] Fri Feb 5 22:41:47 2016
@@ -494,7 +494,7 @@ public abstract class ConcurrentAuthorit
/**
* Confirms that the given factories can be closed. If any factory is still in use,
- * it will be removed from that {@cod factories} list and re-injected in the {@link #availableDAOs} queue.
+ * it will be removed from that {@code factories} list and re-injected in the {@link #availableDAOs} queue.
*/
private void confirmClose(final List<DAO> factories) {
assert !Thread.holdsLock(availableDAOs);
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java?rev=1728765&r1=1728764&r2=1728765&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java [UTF-8] Fri Feb 5 22:41:47 2016
@@ -328,7 +328,8 @@ public class EPSGFactory extends Concurr
* a {@link String} giving the name of the database schema where to create the EPSG tables.
* That schema shall <strong>not</strong> exist prior this method call;
* the schema will be created by this {@code install(…)} method.
- * If no schema is specified or if the schema an empty string, then the tables will be created without schema.
+ * If the schema is an empty string, then the tables will be created without schema.
+ * If no schema is specified, then the default schema is {@code "EPSG"}.
* If the database does not {@linkplain DatabaseMetaData#supportsSchemasInTableDefinitions() support
* schemas in table definitions} or in {@linkplain DatabaseMetaData#supportsSchemasInDataManipulation()
* data manipulation}, then this property is ignored.</li>
@@ -362,8 +363,11 @@ public class EPSGFactory extends Concurr
}
boolean success = false;
try {
- if (schema != null) {
- installer.setSchema(schema);
+ if (!"".equals(schema)) { // Schema may be null.
+ installer.setSchema(schema != null ? schema : Constants.EPSG);
+ if (catalog != null && !catalog.isEmpty()) {
+ installer.prependNamespace(catalog);
+ }
}
installer.run(scriptDirectory);
success = true;
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java?rev=1728765&r1=1728764&r2=1728765&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java [UTF-8] Fri Feb 5 22:41:47 2016
@@ -158,11 +158,18 @@ final class EPSGInstaller extends Script
replace(SQLTranslator.TABLE_PREFIX + "supersession", "Supersession");
replace(SQLTranslator.TABLE_PREFIX + "unitofmeasure", "Unit of Measure");
replace(SQLTranslator.TABLE_PREFIX + "versionhistory", "Version History");
- modifyReplacements((String key, String value) -> schema + '.' + identifierQuote + value + identifierQuote);
+ prependNamespace(schema);
}
}
/**
+ * Prepends the given schema or catalog to all table names.
+ */
+ final void prependNamespace(final String schema) {
+ modifyReplacements((key, value) -> schema + '.' + identifierQuote + value + identifierQuote);
+ }
+
+ /**
* Modifies the SQL statement before to execute it, or omit unsupported statements.
*
* @throws SQLException if an error occurred while executing the SQL statement.
Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java?rev=1728765&r1=1728764&r2=1728765&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java [UTF-8] Fri Feb 5 22:41:47 2016
@@ -16,20 +16,35 @@
*/
package org.apache.sis.referencing.factory.sql;
+import java.util.Map;
+import java.util.HashMap;
import java.sql.Connection;
+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.apache.sis.referencing.CommonCRS;
import org.apache.sis.internal.metadata.sql.TestDatabase;
+import org.apache.sis.util.ComparisonMode;
+import org.apache.sis.util.Utilities;
import org.apache.sis.test.DependsOn;
import org.apache.sis.test.TestCase;
import org.junit.Test;
+import static org.junit.Assert.*;
+
// Branch-dependent imports
import java.nio.file.Path;
/**
- * Tests {@link EPSGInstaller}. Every databases created by this test suite exists only in memory.
- * This class does not write anything to disk (except maybe some temporary files).
+ * Tests {@link EPSGInstaller} indirectly, through {@link EPSGFactory#install(Connection)}.
+ * We do not test {@code EPSGInstaller} directly because the EPSG database creation is costly,
+ * and we want to use the {@code EPSGFactory} for creating a few CRS for testing purpose.
+ *
+ * <p>Every databases created by this test suite exist only in memory.
+ * This class does not write anything to disk (except maybe some temporary files).</p>
*
* @author Martin Desruisseaux (Geomatys)
* @since 0.7
@@ -48,13 +63,44 @@ public final strictfp class EPSGInstalle
public void testCreationOnDerby() throws Exception {
final Path scripts = TestDatabase.directory("ExternalSources");
final DataSource ds = TestDatabase.create("test");
- try (Connection c = ds.getConnection()) {
- try (EPSGInstaller installer = new EPSGInstaller(c)) {
- installer.setSchema("EPSG");
- installer.run(scripts);
- }
+ try {
+ createAndTest(ds, scripts);
} finally {
TestDatabase.drop(ds);
}
}
+
+ /**
+ * Requests the WGS84 coordinate reference system from the EPSG database at the given source.
+ * It should trig the creation of the EPSG database.
+ */
+ private static void createAndTest(final DataSource ds, final Path scripts) throws SQLException, FactoryException {
+ final Map<String,Object> properties = new HashMap<>();
+ assertNull(properties.put("dataSource", ds));
+ assertNull(properties.put("scriptDirectory", scripts));
+ assertEquals("Should not contain EPSG tables before we created them.", 0, countCRSTables(ds));
+ try (EPSGFactory factory = new EPSGFactory(properties)) {
+ final GeographicCRS crs = factory.createGeographicCRS("4326");
+ assertTrue(Utilities.deepEquals(CommonCRS.WGS84.geographic(), crs, ComparisonMode.DEBUG));
+ }
+ assertEquals("Should contain EPSG tables after we created them.", 1, countCRSTables(ds));
+ }
+
+ /**
+ * Counts the number of {@code EPSG."Coordinate Reference System"} tables.
+ * It should be 0 or 1. Any schema other than "EPSG" causes a test failure.
+ */
+ private static int countCRSTables(final DataSource ds) throws SQLException {
+ int count = 0;
+ try (Connection c = ds.getConnection()) {
+ try (ResultSet r = c.getMetaData().getTables(null, null, "Coordinate Reference System", null)) {
+ while (r.next()) {
+ final String schema = r.getString("TABLE_SCHEM");
+ assertTrue(schema, "EPSG".equalsIgnoreCase(schema));
+ count++;
+ }
+ }
+ }
+ return count;
+ }
}
Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/report/CoordinateReferenceSystems.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/report/CoordinateReferenceSystems.java?rev=1728765&r1=1728764&r2=1728765&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/report/CoordinateReferenceSystems.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/report/CoordinateReferenceSystems.java [UTF-8] Fri Feb 5 22:41:47 2016
@@ -17,6 +17,9 @@
package org.apache.sis.referencing.report;
import java.util.Locale;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.TreeMap;
import java.io.File;
import java.io.IOException;
@@ -35,8 +38,14 @@ import org.opengis.referencing.crs.Engin
import org.opengis.referencing.crs.GeneralDerivedCRS;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.CRSAuthorityFactory;
+import org.opengis.referencing.datum.Datum;
import org.opengis.referencing.datum.VerticalDatumType;
+import org.opengis.referencing.operation.OperationMethod;
import org.opengis.test.report.AuthorityCodesReport;
+import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.referencing.CRS;
+import org.apache.sis.referencing.CommonCRS;
+import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.referencing.crs.AbstractCRS;
import org.apache.sis.referencing.cs.AxesConvention;
import org.apache.sis.util.logging.Logging;
@@ -46,18 +55,308 @@ import org.apache.sis.util.Deprecable;
import org.apache.sis.util.Utilities;
import org.apache.sis.util.Version;
+import static org.junit.Assert.*;
+
/**
* Generates a list of supported Coordinate Reference Systems in the current directory.
* This class is for manual execution after the EPSG database has been updated,
* or the projection implementations changed.
*
+ * <p><b>WARNING:</b>
+ * this class implements heuristic rules for nicer sorting (e.g. of CRS having numbers as Roman letters).
+ * Those heuristic rules were determined specifically for the EPSG dataset expanded with WMS codes.
+ * This class is not likely to produce good results for any other authorities, and many need to be updated
+ * after any upgrade of the EPSG dataset.</p>
+ *
* @author Martin Desruisseaux (Geomatys)
* @since 0.7
* @version 0.7
* @module
*/
-public strictfp class CoordinateReferenceSystems extends AuthorityCodesReport {
+public final strictfp class CoordinateReferenceSystems extends AuthorityCodesReport {
+ /**
+ * The titles of some sections in the list of CRS. We use sections for grouping related CRS together.
+ * By default (if no mapping is specified below), the section titles will be the datum names.
+ * But in some cases we use a slightly different title. Sometime the changes are only cosmetic
+ * (e.g. "Reseau Geodesique Francais" → "Réseau Géodésique Français").
+ * But sometime the changes have the effect of merging different datums under the same section.
+ * We do that only when the datums are closely related, and the decision to merge or not is taken on a
+ * case-by-case basis. For example we merge the "Arc 1950" and "Arc 1960" sections into a single "Arc" section,
+ * since those sections were small and we do not want to scatter the HTML page with too many sections.
+ * However we do not merge "NAD83" and "NAD83(HARN)" because those sections are already quite large,
+ * and merging them will result in a too large section.
+ *
+ * <p>The decision to merge or not is arbitrary. Generally, we try to avoid small sections (less that 5 CRS)
+ * but without merging together unrelated datums.</p>
+ */
+ private static final Map<String,String> SECTION_TITLES = new HashMap<>();
+ static {
+ rd("Arc 1950", "Arc");
+ rd("Arc 1960", "Arc");
+ rd("Ancienne Triangulation Francaise (Paris)", "Ancienne Triangulation Française");
+ rd("Australian Geodetic Datum 1966", "Australian Geodetic Datum");
+ rd("Australian Geodetic Datum 1984", "Australian Geodetic Datum");
+ rd("Australian Height Datum (Tasmania)", "Australian Height Datum");
+ rd("Azores Central Islands 1948", "Azores Central Islands");
+ rd("Azores Central Islands 1995", "Azores Central Islands");
+ rd("Azores Oriental Islands 1940", "Azores Oriental Islands");
+ rd("Azores Oriental Islands 1995", "Azores Oriental Islands");
+ rd("Baltic 1980", "Baltic");
+ rd("Baltic 1982", "Baltic");
+ rd("Baltic Sea", "Baltic");
+ rd("Batavia (Jakarta)", "Batavia");
+ rd("Bermuda 1957", "Bermuda");
+ rd("Bermuda 2000", "Bermuda");
+ rd("Bogota 1975 (Bogota)", "Bogota 1975");
+ rd("Carthage (Paris)", "Carthage");
+ rd("Bern 1938", "Bern / CH1903");
+ rd("CH1903", "Bern / CH1903");
+ rd("CH1903+", "Bern / CH1903");
+ rd("CH1903 (Bern)", "Bern / CH1903");
+ rd("Chatham Islands Datum 1971", "Chatham Islands Datum");
+ rd("Chatham Islands Datum 1979", "Chatham Islands Datum");
+ rd("Corrego Alegre 1961", "Corrego Alegre");
+ rd("Corrego Alegre 1970-72", "Corrego Alegre");
+ rd("Dealul Piscului 1930", "Dealul Piscului");
+ rd("Dealul Piscului 1970", "Dealul Piscului");
+ rd("Deutsches Haupthoehennetz 1985", "Deutsches Haupthoehennetz");
+ rd("Deutsches Haupthoehennetz 1992", "Deutsches Haupthoehennetz");
+ rd("Douala 1948", "Douala");
+ rd("Dunedin 1958", "Dunedin");
+ rd("Dunedin-Bluff 1960", "Dunedin");
+ rd("EGM2008 geoid", "EGM geoid");
+ rd("EGM84 geoid", "EGM geoid");
+ rd("EGM96 geoid", "EGM geoid");
+ rd("Egypt 1907", "Egypt");
+ rd("Egypt 1930", "Egypt");
+ rd("Egypt Gulf of Suez S-650 TL", "Egypt");
+ rd("EPSG example X", "Seismic bin grid datum"); // 2 spaces before "X".
+ rd("Estonia 1992", "Estonia");
+ rd("Estonia 1997", "Estonia");
+ rd("European Datum 1950", "European Datum");
+ rd("European Datum 1950(1977)", "European Datum");
+ rd("European Datum 1979", "European Datum");
+ rd("European Datum 1987", "European Datum");
+ rd("European Vertical Reference Frame 2000", "European Vertical Reference Frame");
+ rd("European Vertical Reference Frame 2007", "European Vertical Reference Frame");
+ rd("Fahud Height Datum", "Fahud");
+ rd("Fao 1979", "Fao");
+ rd("Faroe Datum 1954", "Faroe Islands");
+ rd("Faroe Islands Vertical Reference 2009", "Faroe Islands");
+ rd("fk89", "Faroe Islands");
+ rd("Fiji 1956", "Fiji");
+ rd("Fiji Geodetic Datum 1986", "Fiji");
+ rd("Greek (Athens)", "Greek");
+ rd("Greek Geodetic Reference System 1987", "Greek");
+ rd("Guadeloupe 1948", "Guadeloupe");
+ rd("Guadeloupe 1951", "Guadeloupe");
+ rd("Guadeloupe 1988", "Guadeloupe");
+ rd("Gunung Segara (Jakarta)", "Gunung Segara");
+ rd("Guyane Francaise", "Centre Spatial Guyanais 1967"); // For a deprecated CRS.
+ rd("Hong Kong 1963", "Hong Kong");
+ rd("Hong Kong 1963(67)", "Hong Kong");
+ rd("Hong Kong 1980", "Hong Kong");
+ rd("Hong Kong Chart Datum", "Hong Kong");
+ rd("Hong Kong Principal Datum", "Hong Kong");
+ rd("Hungarian Datum 1909", "Hungarian Datum");
+ rd("Hungarian Datum 1972", "Hungarian Datum");
+ rd("IGN 1962 Kerguelen", "IGN");
+ rd("IGN 1966", "IGN");
+ rd("IGN 1988 LS", "IGN");
+ rd("IGN 1988 MG", "IGN");
+ rd("IGN 1988 SB", "IGN");
+ rd("IGN 1988 SM", "IGN");
+ rd("IGN 1992 LD", "IGN");
+ rd("IGN Astro 1960", "IGN");
+ rd("IGN53 Mare", "IGN");
+ rd("IGN56 Lifou", "IGN");
+ rd("IGN63 Hiva Oa", "IGN");
+ rd("IGN72 Grande Terre", "IGN");
+ rd("IGN72 Nuku Hiva", "IGN");
+ rd("IGN78 Corsica", "IGN");
+ rd("Indian 1954", "Indian");
+ rd("Indian 1960", "Indian");
+ rd("Indian 1975", "Indian");
+ rd("International Great Lakes Datum 1955", "International Great Lakes Datum");
+ rd("International Great Lakes Datum 1985", "International Great Lakes Datum");
+ rd("International Terrestrial Reference Frame 1988", "International Terrestrial Reference Frame");
+ rd("International Terrestrial Reference Frame 1989", "International Terrestrial Reference Frame");
+ rd("International Terrestrial Reference Frame 1990", "International Terrestrial Reference Frame");
+ rd("International Terrestrial Reference Frame 1991", "International Terrestrial Reference Frame");
+ rd("International Terrestrial Reference Frame 1992", "International Terrestrial Reference Frame");
+ rd("International Terrestrial Reference Frame 1993", "International Terrestrial Reference Frame");
+ rd("International Terrestrial Reference Frame 1994", "International Terrestrial Reference Frame");
+ rd("International Terrestrial Reference Frame 1996", "International Terrestrial Reference Frame");
+ rd("International Terrestrial Reference Frame 1997", "International Terrestrial Reference Frame");
+ rd("International Terrestrial Reference Frame 2000", "International Terrestrial Reference Frame");
+ rd("International Terrestrial Reference Frame 2005", "International Terrestrial Reference Frame");
+ rd("International Terrestrial Reference Frame 2008", "International Terrestrial Reference Frame");
+ rd("Islands Net 1993", "Islands Net");
+ rd("Islands Net 2004", "Islands Net");
+ rd("Jamaica 1875", "Jamaica");
+ rd("Jamaica 1969", "Jamaica");
+ rd("Jamaica 2001", "Jamaica");
+ rd("Kalianpur 1880", "Kalianpur");
+ rd("Kalianpur 1937", "Kalianpur");
+ rd("Kalianpur 1962", "Kalianpur");
+ rd("Kalianpur 1975", "Kalianpur");
+ rd("Kertau (RSO)", "Kertau");
+ rd("Kertau 1968", "Kertau");
+ rd("Korean Datum 1985", "Korean Datum");
+ rd("Korean Datum 1995", "Korean Datum");
+ rd("Kuwait Oil Company", "Kuwait Oil Company / Kuwait Utility");
+ rd("Kuwait PWD", "Kuwait Oil Company / Kuwait Utility");
+ rd("Kuwait Utility", "Kuwait Oil Company / Kuwait Utility");
+ rd("Lao 1993", "Lao");
+ rd("Lao National Datum 1997", "Lao");
+ rd("Lisbon 1890", "Lisbon");
+ rd("Lisbon 1890 (Lisbon)", "Lisbon");
+ rd("Lisbon 1937", "Lisbon");
+ rd("Lisbon 1937 (Lisbon)", "Lisbon");
+ rd("Cote d'Ivoire", "Locodjo 1965"); // For a deprecated CRS.
+ rd("Madeira 1936", "Porto Santo"); // For a deprecated CRS.
+ rd("Makassar (Jakarta)", "Makassar");
+ rd("Manoca 1962", "Manoca");
+ rd("Martinique 1938", "Martinique");
+ rd("Martinique 1955", "Martinique");
+ rd("Martinique 1987", "Martinique");
+ rd("Maupiti 83", "Maupiti");
+ rd("Maupiti SAU 2001", "Maupiti");
+ rd("Missao Hidrografico Angola y Sao Tome 1951", "Missao Hidrografico Angola y Sao Tome");
+ rd("Mhast", "Missao Hidrografico Angola y Sao Tome");
+ rd("Mhast (offshore)", "Missao Hidrografico Angola y Sao Tome");
+ rd("Mhast (onshore)", "Missao Hidrografico Angola y Sao Tome");
+ rd("Militar-Geographische Institut (Ferro)", "Militar-Geographische Institut");
+ rd("Monte Mario (Rome)", "Monte Mario");
+ rd("Moorea 87", "Moorea");
+ rd("Moorea SAU 1981", "Moorea");
+ rd("Nahrwan 1934", "Nahrwan");
+ rd("Nahrwan 1967", "Nahrwan");
+ rd("Naparima 1955", "Naparima");
+ rd("Naparima 1972", "Naparima");
+ rd("Nivellement General de la Corse 1948", "Nivellement Général Corse / France / Nouvelle-Calédonie / Polynésie Française / Luxembourd / Guyanais");
+ rd("Nivellement General de la France - IGN69", "Nivellement Général Corse / France / Nouvelle-Calédonie / Polynésie Française / Luxembourd / Guyanais");
+ rd("Nivellement General de la France - Lallemand", "Nivellement Général Corse / France / Nouvelle-Calédonie / Polynésie Française / Luxembourd / Guyanais");
+ rd("Nivellement General de Nouvelle Caledonie", "Nivellement Général Corse / France / Nouvelle-Calédonie / Polynésie Française / Luxembourd / Guyanais");
+ rd("Nivellement General de Polynesie Francaise", "Nivellement Général Corse / France / Nouvelle-Calédonie / Polynésie Française / Luxembourd / Guyanais");
+ rd("Nivellement General du Luxembourg", "Nivellement Général Corse / France / Nouvelle-Calédonie / Polynésie Française / Luxembourd / Guyanais");
+ rd("Nivellement General Guyanais 1977", "Nivellement Général Corse / France / Nouvelle-Calédonie / Polynésie Française / Luxembourd / Guyanais");
+ rd("NGO 1948 (Oslo)", "NGO 1948");
+ rd("NAD27 Michigan", "North American Datum 1927 — Michigan");
+ rd("NAD83 (High Accuracy Reference Network)", "North American Datum 1983 — High Accuracy Reference Network");
+ rd("NAD83 (National Spatial Reference System 2007)", "North American Datum 1983 — National Spatial Reference System 2007");
+ rd("NAD83 Canadian Spatial Reference System", "North American Datum 1983 — Canadian Spatial Reference System");
+ rd("Nord Sahara 1959 (Paris)", "Nord Sahara 1959");
+ rd("Nord de Guerre (Paris)", "Ancienne Triangulation Française");
+ rd("Nouvelle Triangulation Francaise", "Nouvelle Triangulation Française");
+ rd("Nouvelle Triangulation Francaise (Paris)", "Nouvelle Triangulation Française");
+ rd("Ordnance Datum Newlyn (Orkney Isles)", "Ordnance Datum Newlyn");
+ rd("OSGB 1936", "OSGB");
+ rd("OSGB 1970 (SN)", "OSGB");
+ rd("Padang 1884 (Jakarta)", "Padang 1884");
+ rd("PDO Height Datum 1993", "PDO Survey / Height Datum 1993");
+ rd("PDO Survey Datum 1993", "PDO Survey / Height Datum 1993");
+ rd("Pitcairn 1967", "Pitcairn");
+ rd("Pitcairn 2006", "Pitcairn");
+ rd("Porto Santo 1936", "Porto Santo");
+ rd("Porto Santo 1995", "Porto Santo");
+ rd("Posiciones Geodesicas Argentinas 1994", "Posiciones Geodesicas Argentinas");
+ rd("Posiciones Geodesicas Argentinas 1998", "Posiciones Geodesicas Argentinas");
+ rd("Posiciones Geodesicas Argentinas 2007", "Posiciones Geodesicas Argentinas");
+ rd("Qatar 1948", "Qatar");
+ rd("Qatar 1974", "Qatar");
+ rd("Qatar National Datum 1995", "Qatar");
+ rd("Qornoq 1927", "Qornoq");
+ rd("Reseau Geodesique Nouvelle Caledonie 1991", "Réseau Géodésique de Nouvelle-Calédonie");
+ rd("Reseau Geodesique de Nouvelle Caledonie 91-93", "Réseau Géodésique de Nouvelle-Calédonie");
+ rd("Reseau National Belge 1950", "Réseau National Belge");
+ rd("Reseau National Belge 1950 (Brussels)", "Réseau National Belge");
+ rd("Reseau National Belge 1972", "Réseau National Belge");
+ rd("Reunion 1947", "Réunion");
+ rd("Reunion 1989", "Réunion");
+ rd("Rikets hojdsystem 1900", "Rikets hojdsystem");
+ rd("Rikets hojdsystem 1970", "Rikets hojdsystem");
+ rd("Rikets hojdsystem 2000", "Rikets hojdsystem");
+ rd("Samboja", "Gunung Segara"); // For a deprecated CRS.
+ rd("Segora", "Gunung Segara"); // For a deprecated CRS.
+ rd("Sierra Leone 1968", "Sierra Leone");
+ rd("Sierra Leone Colony 1924", "Sierra Leone");
+ rd("SIRGAS-Chile", "SIRGAS");
+ rd("SIRGAS-ROU98", "SIRGAS");
+ rd("SIRGAS_ES2007.8", "SIRGAS");
+ rd("South American Datum 1969", "South American Datum");
+ rd("South American Datum 1969(96)", "South American Datum");
+ rd("Sri Lanka Datum 1999", "Sri Lanka");
+ rd("Sri Lanka Vertical Datum", "Sri Lanka");
+ rd("Stockholm 1938 (Stockholm)", "Stockholm 1938");
+ rd("Sudan", "Adindan"); // For a deprecated CRS.
+ rd("System Jednotne Trigonometricke Site Katastralni (Ferro)", "System Jednotne Trigonometricke Site Katastralni");
+ rd("System Jednotne Trigonometricke Site Katastralni/05", "System Jednotne Trigonometricke Site Katastralni");
+ rd("System Jednotne Trigonometricke Site Katastralni/05 (Ferro)", "System Jednotne Trigonometricke Site Katastralni");
+ rd("Tahaa 54", "Tahaa");
+ rd("Tahaa SAU 2001", "Tahaa");
+ rd("Tahiti 52", "Tahiti");
+ rd("Tahiti 79", "Tahiti");
+ rd("Taiwan Datum 1967", "Taiwan Datum");
+ rd("Taiwan Datum 1997", "Taiwan Datum");
+ rd("Tananarive 1925 (Paris)", "Tananarive 1925");
+ rd("Viti Levu 1912", "Viti Levu");
+ rd("Viti Levu 1916", "Viti Levu"); // For a deprecated CRS.
+ rd("Voirol 1875", "Voirol");
+ rd("Voirol 1875 (Paris)", "Voirol");
+ rd("Voirol 1879", "Voirol");
+ rd("Voirol 1879 (Paris)", "Voirol");
+ rd("WGS 72 Transit Broadcast Ephemeris", "World Geodetic System 1972 — Transit Broadcast Ephemeris");
+ rd("Yellow Sea 1956", "Yellow Sea");
+ rd("Yellow Sea 1985", "Yellow Sea");
+ }
+
+ /**
+ * Shortcut for {@link #SECTION_TITLES} initialization.
+ * {@code "rd"} stands for "rename datum".
+ */
+ private static void rd(final String datum, final String display) {
+ assertNull(datum, SECTION_TITLES.put(datum, display));
+ }
+
+ /**
+ * The keywords before which to cut the CRS names. The main intend here is to preserve the
+ * "far west", "west", "central west", "central", "central east", "east", "far east" order.
+ */
+ private static final String[] CUT_BEFORE = {
+ " far west", // "MAGNA-SIRGAS / Colombia Far West zone"
+ " far east",
+ " west", // "Bogota 1975 / Colombia West zone"
+ " east", // "Bogota 1975 / Colombia East Central zone"
+ " central", // "Korean 1985 / Central Belt" (between "East Belt" and "West Belt")
+ " old central", // "NAD Michigan / Michigan Old Central"
+ " bogota zone", // "Bogota 1975 / Colombia Bogota zone"
+ // Do not declare "North" and "South" as it causes confusion with "WGS 84 / North Pole" and other cases.
+ };
+
+ /**
+ * The keywords after which to cut the CRS names.
+ *
+ * Note: alphabetical sorting of Roman numbers work for zones from I to VIII inclusive.
+ * If there is more zones (for example with "JGD2000 / Japan Plane Rectangular"), then
+ * we need to cut before those numbers in order to use sorting by EPSG codes instead.
+ *
+ * Note 2: if alphabetical sorting is okay for Roman numbers, it is actually preferable
+ * because it give better position of names with height like "zone II + NGF IGN69 height".
+ */
+ private static final String[] CUT_AFTER = {
+ " cs ", // "JGD2000 / Japan Plane Rectangular CS IX"
+ " tm", // "ETRS89 / TM35FIN(E,N)" — we want to not interleave them between "TM35" and "TM36".
+ " dktm", // "ETRS89 / DKTM1 + DVR90 height"
+ "-gk", // "ETRS89 / ETRS-GK19FIN"
+// " philippines zone ", // "Luzon 1911 / Philippines zone IV"
+// " california zone ", // "NAD27 / California zone V"
+// " ngo zone ", // "NGO 1948 (Oslo) / NGO zone I"
+// " lambert zone ", // "NTF (Paris) / Lambert zone II + NGF IGN69 height"
+ "fiji 1956 / utm zone " // Two zones: 60S and 1S with 60 before 1.
+ };
+
/**
* The symbol to write in from of EPSG code of CRS having an axis order different
* then the (longitude, latitude) one.
@@ -84,8 +383,8 @@ public strictfp class CoordinateReferenc
properties.setProperty("FACTORY.VERSION.SUFFIX", ", together with other sources");
properties.setProperty("DESCRIPTION", "<p><b>Notation:</b></p>\n" +
"<ul>\n" +
- " <li>The " + YX_ORDER + " symbol in front of authority codes (${PERCENT.ANNOTATED} of them)" +
- " identifies the CRS having an axis order different than (<var>easting</var>, <var>northing</var>).</li>\n" +
+ " <li>The " + YX_ORDER + " symbol in front of authority codes (${PERCENT.ANNOTATED} of them) identifies" +
+ " left-handed coordinate systems (for example with <var>latitude</var> axis before <var>longitude</var>).</li>\n" +
" <li>The <del>codes with a strike</del> (${PERCENT.DEPRECATED} of them) identify deprecated CRS." +
" In some cases, the remarks column indicates the replacement.</li>\n" +
"</ul>");
@@ -94,20 +393,6 @@ public strictfp class CoordinateReferenc
}
/**
- * Returns the current Apache SIS version, with the {@code -SNAPSHOT} trailing part omitted.
- *
- * @return The current Apache SIS version.
- */
- private static String getVersion() {
- String version = Version.SIS.toString();
- final int snapshot = version.lastIndexOf('-');
- if (snapshot >= 2) {
- version = version.substring(0, snapshot);
- }
- return version;
- }
-
- /**
* Generates the HTML report.
*
* @param args Ignored.
@@ -123,14 +408,31 @@ public strictfp class CoordinateReferenc
}
/**
- * Creates the remarks for the given CRS.
+ * Returns the current Apache SIS version, with the {@code -SNAPSHOT} trailing part omitted.
+ *
+ * @return The current Apache SIS version.
+ */
+ private static String getVersion() {
+ String version = Version.SIS.toString();
+ final int snapshot = version.lastIndexOf('-');
+ if (snapshot >= 2) {
+ version = version.substring(0, snapshot);
+ }
+ return version;
+ }
+
+ /**
+ * Creates the text to show in the "Remarks" column for the given CRS.
*/
private String getRemark(final CoordinateReferenceSystem crs) {
if (crs instanceof GeographicCRS) {
return (crs.getCoordinateSystem().getDimension() == 3) ? "Geographic 3D" : "Geographic";
}
if (crs instanceof GeneralDerivedCRS) {
- return ((GeneralDerivedCRS) crs).getConversionFromBase().getMethod().getName().getCode().replace('_', ' ');
+ final OperationMethod method = ((GeneralDerivedCRS) crs).getConversionFromBase().getMethod();
+ return "<a href=\"CoordinateOperationMethods.html#"
+ + IdentifiedObjects.getIdentifier(method, Citations.EPSG).getCode()
+ + "\">" + method.getName().getCode().replace('_', ' ') + "</a>";
}
if (crs instanceof GeocentricCRS) {
final CoordinateSystem cs = crs.getCoordinateSystem();
@@ -172,6 +474,9 @@ public strictfp class CoordinateReferenc
*/
@Override
protected Row createRow(final String code, final IdentifiedObject object) {
+ if (code.equals("EPSG:5804")) {
+ System.out.println("");
+ }
final Row row = super.createRow(code, object);
final CoordinateReferenceSystem crs = (CoordinateReferenceSystem) object;
final CoordinateReferenceSystem crsXY = AbstractCRS.castOrCopy(crs).forConvention(AxesConvention.RIGHT_HANDED);
@@ -198,7 +503,8 @@ public strictfp class CoordinateReferenc
row.remark = i18n.toString(getLocale());
}
}
- return new ByName(row);
+ ((ByName) row).setup(CRS.getSingleComponents(crs).get(0).getDatum());
+ return row;
}
/**
@@ -218,21 +524,32 @@ public strictfp class CoordinateReferenc
} catch (FactoryException e) {
Logging.unexpectedException(null, CoordinateReferenceSystems.class, "createRow", e);
}
- String message;
if (code.startsWith("AUTO2:")) {
// It is normal to be unable to instantiate an "AUTO" CRS,
// because those authority codes need parameters.
- message = "Projected";
row.hasError = false;
+ row.remark = "Projected";
+ ((ByName) row).setup(CommonCRS.WGS84.datum());
} else {
- message = exception.getMessage();
+ String message = exception.getMessage();
if (message.contains("Unable to format units in UCUM")) {
// Simplify a very long and badly formatted message.
message = "Unable to format units in UCUM";
}
+ row.remark = message;
+ ((ByName) row).setup(null);
}
- row.remark = message;
- return new ByName(row);
+ return row;
+ }
+
+ /**
+ * Invoked by {@link AuthorityCodesReport} for creating a new row instance.
+ *
+ * @return The new row instance.
+ */
+ @Override
+ protected Row newRow() {
+ return new ByName();
}
/**
@@ -250,52 +567,39 @@ public strictfp class CoordinateReferenc
*/
private static final class ByName extends Row {
/**
- * The keywords before which to cut the name. The main intend here is to preserve the
- * "far west", "west", "central west", "central", "central east", "east", "far east" order.
+ * A string derived from the {@link #name} to use for sorting.
*/
- private static final String[] CUT_BEFORE = {
- " far west", // "MAGNA-SIRGAS / Colombia Far West zone"
- " far east",
- " west", // "Bogota 1975 / Colombia West zone"
- " east", // "Bogota 1975 / Colombia East Central zone"
- " central", // "Korean 1985 / Central Belt" (between "East Belt" and "West Belt")
- " old central", // "NAD Michigan / Michigan Old Central"
- " bogota zone", // "Bogota 1975 / Colombia Bogota zone"
- // Do not declare "North" and "South" as it causes confusion with "WGS 84 / North Pole" and other cases.
- };
+ private String reducedName;
/**
- * The keywords after which to cut the name.
- *
- * Note: alphabetical sorting of Roman numbers work for zones from I to VIII inclusive.
- * If there is more zones (for example with "JGD2000 / Japan Plane Rectangular"), then
- * we need to cut before those numbers in order to use sorting by EPSG codes instead.
- *
- * Note 2: if alphabetical sorting is okay for Roman numbers, it is actually preferable
- * because it give better position of names with height like "zone II + NGF IGN69 height".
+ * The datum name, or {@code null} if unknown.
+ * If non-null, this is used for grouping CRS names by sections.
*/
- private static final String[] CUT_AFTER = {
- " cs ", // "JGD2000 / Japan Plane Rectangular CS IX"
- " tm", // "ETRS89 / TM35FIN(E,N)" — we want to not interleave them between "TM35" and "TM36".
- " dktm", // "ETRS89 / DKTM1 + DVR90 height"
- "-gk", // "ETRS89 / ETRS-GK19FIN"
-// " philippines zone ", // "Luzon 1911 / Philippines zone IV"
-// " california zone ", // "NAD27 / California zone V"
-// " ngo zone ", // "NGO 1948 (Oslo) / NGO zone I"
-// " lambert zone ", // "NTF (Paris) / Lambert zone II + NGF IGN69 height"
- "fiji 1956 / utm zone " // Two zones: 60S and 1S with 60 before 1.
- };
+ String section;
/**
- * A string derived from the {@link #name} to use for sorting.
+ * Creates a new row.
*/
- private final String reducedName;
+ ByName() {
+ }
/**
- * Creates a new row as a copy of the given row, but with a different natural ordering.
+ * Computes the {@link #reducedName} field value.
*/
- ByName(final Row row) {
- super(row);
+ final void setup(final Datum datum) {
+ if (datum != null) {
+ section = datum.getName().getCode();
+ } else {
+ // Temporary patch (TODO: remove after we implemented the missing methods in SIS)
+ if (name.startsWith("NSIDC EASE-Grid")) {
+ section = "Unspecified datum";
+ } else if (code.equals("EPSG:2163")) {
+ section = "Unspecified datum";
+ } else if (code.equals("EPSG:5818")) {
+ section = "Seismic bin grid datum";
+ }
+ }
+ section = SECTION_TITLES.getOrDefault(section, section);
/*
* Get a copy of the name in all lower case.
*/
@@ -370,9 +674,10 @@ public strictfp class CoordinateReferenc
}
/**
- * Compares this row wit the given row for ordering by name.
+ * Compares this row with the given row for ordering by name.
*/
- @Override public int compareTo(final Row o) {
+ @Override
+ public int compareTo(final Row o) {
int n = reducedName.compareTo(((ByName) o).reducedName);
if (n == 0) {
n = super.compareTo(o);
@@ -380,4 +685,60 @@ public strictfp class CoordinateReferenc
return n;
}
}
+
+ /**
+ * Sorts the rows, then inserts sections between CRS instances that use different datums.
+ */
+ @Override
+ protected void sortRows() {
+ super.sortRows();
+ @SuppressWarnings("SuspiciousToArrayCall")
+ final ByName[] data = rows.toArray(new ByName[rows.size()]);
+ final Map<String,String> sections = new TreeMap<>();
+ for (final ByName row : data) {
+ final String section = row.section;
+ if (section != null) {
+ sections.put(CharSequences.toASCII(section).toString().toLowerCase(), section);
+ }
+ }
+ rows.clear();
+ /*
+ * Recopy the rows, but section-by-section. We do this sorting here instead than in the Row.compareTo(Row)
+ * method in order to preserve the alphabetical order of rows with unknown datum.
+ * Algorithm below is inefficient, but this class should be rarely used anyway and only by site maintainer.
+ */
+ for (final String section : sections.values()) {
+ final Row separator = new Row();
+ separator.isSectionHeader = true;
+ separator.name = section;
+ rows.add(separator);
+ boolean found = false;
+ for (int i=0; i<data.length; i++) {
+ final ByName row = data[i];
+ if (row != null) {
+ if (row.section != null) {
+ found = section.equals(row.section);
+ }
+ if (found) {
+ rows.add(row);
+ data[i] = null;
+ found = true;
+ }
+ }
+ }
+ }
+ boolean found = false;
+ for (final ByName row : data) {
+ if (row != null) {
+ if (!found) {
+ final Row separator = new Row();
+ separator.isSectionHeader = true;
+ separator.name = "Unknown";
+ rows.add(separator);
+ }
+ rows.add(row);
+ found = true;
+ }
+ }
+ }
}