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/03 23:51:43 UTC
svn commit: r1728389 - 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/referencing/factory/sql/ s...
Author: desruisseaux
Date: Wed Feb 3 22:51:42 2016
New Revision: 1728389
URL: http://svn.apache.org/viewvc?rev=1728389&view=rev
Log:
Minor adjustments in EPSGInstaller test and in documentation.
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/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/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.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=1728389&r1=1728388&r2=1728389&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] Wed Feb 3 22:51:42 2016
@@ -343,7 +343,7 @@ public abstract class Initializer {
* @return The data source.
* @throws Exception if the data source can not be created.
*/
- public static DataSource forJavaDB(final String path) throws Exception {
+ static DataSource forJavaDB(final String path) throws Exception {
try {
return forJavaDB(path, Thread.currentThread().getContextClassLoader());
} catch (ClassNotFoundException e) {
@@ -397,14 +397,24 @@ public abstract class Initializer {
try {
ds.getConnection().close(); // Does the actual shutdown.
} catch (SQLException e) { // This is the expected exception.
- Level level = Level.CONFIG;
- if (e.getErrorCode() != 45000 || !"08006".equals(e.getSQLState())) {
- level = Level.WARNING;
+ final LogRecord record = new LogRecord(Level.CONFIG, e.getLocalizedMessage());
+ if (!isNormalShutdown(e)) {
+ record.setLevel(Level.WARNING);
+ record.setThrown(e);
}
- final LogRecord record = new LogRecord(level, e.getLocalizedMessage());
record.setLoggerName(Loggers.SQL);
Logging.log(Initializer.class, "shutdown", record);
}
}
}
+
+ /**
+ * Returns {@code true} if the given exception is the one that we expect in a normal 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) {
+ 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=1728389&r1=1728388&r2=1728389&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] Wed Feb 3 22:51:42 2016
@@ -19,7 +19,6 @@ package org.apache.sis.internal.metadata
import java.util.Map;
import java.util.HashMap;
import java.util.Locale;
-import java.util.function.BiFunction;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
@@ -35,6 +34,9 @@ import org.apache.sis.util.ArgumentCheck
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.resources.Errors;
+// Branch-specific imports
+import java.util.function.BiFunction;
+
/**
* Run SQL scripts. The script is expected to use a standardized syntax, where the {@value #QUOTE} character
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=1728389&r1=1728388&r2=1728389&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] Wed Feb 3 22:51:42 2016
@@ -18,6 +18,7 @@ package org.apache.sis.internal.metadata
import java.sql.SQLException;
import javax.sql.DataSource;
+import org.apache.sis.util.Debug;
import org.apache.sis.internal.system.DataDirectory;
import static org.junit.Assume.*;
@@ -38,6 +39,17 @@ import java.nio.file.Path;
*/
public final strictfp class TestDatabase {
/**
+ * Data source to an alternative database to use for testing purpose.
+ * If {@code null}, an in-memory Derby or JavaDB database will be used.
+ *
+ * This field is occasionally set to a non-null value (e.g. a connection to a PostgreSQL database) only for
+ * debugging purpose. In such case, it is developer responsibility to ensure that the appropriate driver is
+ * registered in his development environment (we may not declare them in the {@code pom.xml} file).
+ */
+ @Debug
+ private static final DataSource TEST_DATABASE = null;
+
+ /**
* Do not allow (for now) instantiation of this class.
*/
private TestDatabase() {
@@ -67,6 +79,9 @@ public final strictfp class TestDatabase
* @throws Exception if an error occurred while creating the database.
*/
public static DataSource create(final String name) throws Exception {
+ if (TEST_DATABASE != null) {
+ return TEST_DATABASE;
+ }
final DataSource ds;
try {
ds = Initializer.forJavaDB("memory:" + name);
@@ -85,12 +100,15 @@ public final strictfp class TestDatabase
* @throws Exception if an error occurred while dropping the database.
*/
public static void drop(final DataSource ds) throws Exception {
+ if (ds == TEST_DATABASE) {
+ return;
+ }
ds.getClass().getMethod("setCreateDatabase", String.class).invoke(ds, "no");
ds.getClass().getMethod("setConnectionAttributes", String.class).invoke(ds, "drop=true");
try {
ds.getConnection();
} catch (SQLException e) { // This is the expected exception.
- if (e.getErrorCode() != 45000 || !"08006".equals(e.getSQLState())) {
+ if (!Initializer.isNormalShutdown(e)) {
throw e;
}
}
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=1728389&r1=1728388&r2=1728389&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] Wed Feb 3 22:51:42 2016
@@ -415,7 +415,7 @@ public class EPSGFactory extends Concurr
try {
if (!tr.isTableFound()) {
install(connection);
- tr.setup(connection.getMetaData()); // Set only on success.
+ tr.setup(connection.getMetaData()); // Set only on success.
}
} finally {
translator = tr; // Set only after installation in order to block other threads.
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=1728389&r1=1728388&r2=1728389&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] Wed Feb 3 22:51:42 2016
@@ -41,6 +41,7 @@ import org.apache.sis.util.logging.Perfo
// Branch-specific imports
import java.nio.file.Files;
import java.nio.file.Path;
+import org.apache.sis.util.CharSequences;
/**
@@ -169,6 +170,14 @@ final class EPSGInstaller extends Script
*/
@Override
protected int execute(final StringBuilder sql) throws SQLException, IOException {
+ /*
+ * The SQL scripts provided by EPSG contains some lines with only a "COMMIT" statement.
+ * This statement is not understood by all databases, and interferes with our calls to
+ * setAutoCommit(false) ... commit() / rollback().
+ */
+ if (CharSequences.equalsIgnoreCase(sql, "COMMIT")) {
+ return 0;
+ }
if (statementToSkip != null && statementToSkip.reset(sql).matches()) {
return 0;
}
Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.java?rev=1728389&r1=1728388&r2=1728389&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.java [UTF-8] Wed Feb 3 22:51:42 2016
@@ -58,13 +58,15 @@ import java.util.function.Function;
* <li>{@code SELECT * FROM epsg."Coordinate Reference System"}</li>
* </ul></div>
*
- * In addition to the MS-Access format, EPSG also provides the dataset as <cite>Data Description Language</cite> (DDL)
- * scripts for PostgreSQL, MySQL and Oracle databases. But the table names and some column names in those scripts differ
- * from the ones used in the MS-Access database. The following table summarizes the name changes:
+ * In addition to the file in MS-Access format, EPSG also provides the dataset as SQL files for PostgreSQL,
+ * MySQL and Oracle databases. Those SQL files are used as both <cite>Data Description Language</cite> (DDL)
+ * and <cite>Data Manipulation Language</cite> (DML).
+ * But the table names and some column names in those scripts differ from the ones used in the MS-Access database.
+ * The following table summarizes the name changes:
*
* <table class="sis">
* <caption>Table and column names</caption>
- * <tr><th>Element</th><th>Name in MS-Access database</th> <th>Name in DDL scripts</th></tr>
+ * <tr><th>Element</th><th>Name in MS-Access database</th> <th>Name in SQL scripts</th></tr>
* <tr><td>Table</td> <td>{@code Alias}</td> <td>{@code epsg_alias}</td></tr>
* <tr><td>Table</td> <td>{@code Area}</td> <td>{@code epsg_area}</td></tr>
* <tr><td>Table</td> <td>{@code Coordinate Axis}</td> <td>{@code epsg_coordinateaxis}</td></tr>
@@ -191,8 +193,8 @@ public class SQLTranslator implements Fu
/**
* Creates a new SQL translator for the database described by the given metadata.
- * This constructor detects automatically the dialect: the characters to use for quoting identifiers, and whether
- * the table names are the ones used in the MS-Access database or in the Data Definition Language (DDL) scripts.
+ * This constructor detects automatically the dialect: the characters to use for quoting identifiers,
+ * and whether the table names are the ones used in the MS-Access database or in the SQL scripts.
*
* <p>If the given catalog or schema name is non-null, then the {@linkplain DatabaseMetaData#getTables
* search for EPSG tables} will be restricted to the catalog or schema of that name.
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=1728389&r1=1728388&r2=1728389&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] Wed Feb 3 22:51:42 2016
@@ -46,7 +46,7 @@ public final strictfp class EPSGInstalle
*/
@Test
public void testCreationOnDerby() throws Exception {
- final Path scripts = TestDatabase.directory("Scripts");
+ final Path scripts = TestDatabase.directory("ExternalSources");
final DataSource ds = TestDatabase.create("test");
try (Connection c = ds.getConnection()) {
try (EPSGInstaller installer = new EPSGInstaller(c)) {
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=1728389&r1=1728388&r2=1728389&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] Wed Feb 3 22:51:42 2016
@@ -198,7 +198,7 @@ public strictfp class CoordinateReferenc
row.remark = i18n.toString(getLocale());
}
}
- return row;
+ return new ByName(row);
}
/**
@@ -232,6 +232,152 @@ public strictfp class CoordinateReferenc
}
}
row.remark = message;
- return row;
+ return new ByName(row);
+ }
+
+ /**
+ * A row with an natural ordering that use the first part of the name before to use the authority code.
+ * We use only the part of the name prior some keywords (e.g. {@code "zone"}).
+ * For example if the following codes:
+ *
+ * {@preformat text
+ * EPSG:32609 WGS 84 / UTM zone 9N
+ * EPSG:32610 WGS 84 / UTM zone 10N
+ * }
+ *
+ * We compare only the "WGS 84 / UTM" string, then the code. This is a reasonably easy way to keep a more
+ * natural ordering ("9" sorted before "10", "UTM North" projections kept together and same for South).
+ */
+ 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.
+ */
+ 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 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".
+ */
+ 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.
+ };
+
+ /**
+ * A string derived from the {@link #name} to use for sorting.
+ */
+ private final String reducedName;
+
+ /**
+ * Creates a new row as a copy of the given row, but with a different natural ordering.
+ */
+ ByName(final Row row) {
+ super(row);
+ /*
+ * Get a copy of the name in all lower case.
+ */
+ final StringBuilder b = new StringBuilder(name);
+ for (int i=0; i<b.length(); i++) {
+ b.setCharAt(i, Character.toLowerCase(b.charAt(i)));
+ }
+ /*
+ * Cut the string to a shorter length if we find a keyword.
+ * This will result in many string equals, which will then be sorted by EPSG codes.
+ * This is useful when the EPSG codes give a better ordering than the alphabetic one
+ * (for example with Roman numbers).
+ */
+ int s = 0;
+ for (final String keyword : CUT_BEFORE) {
+ int i = b.lastIndexOf(keyword);
+ if (i > 0 && (s == 0 || i < s)) s = i;
+ }
+ for (final String keyword : CUT_AFTER) {
+ int i = b.lastIndexOf(keyword);
+ if (i >= 0) {
+ i += keyword.length();
+ if (i > s) s = i;
+ }
+ }
+ if (s != 0) b.setLength(s);
+ uniformizeZoneNumber(b);
+ reducedName = b.toString();
+ }
+
+ /**
+ * If the string ends with a number optionally followed by "N" or "S", replaces the hemisphere
+ * symbol by a sign and makes sure that the number uses at least 3 digits (e.g. "2N" → "+002").
+ */
+ private static void uniformizeZoneNumber(final StringBuilder b) {
+ if (b.indexOf("/") < 0) {
+ /*
+ * Do not process names like "WGS 84". We want to process only names like "WGS 84 / UTM zone 2N",
+ * otherwise the replacement of "WGS 84" by "WGS 084" causes unexpected sorting.
+ */
+ return;
+ }
+ int i = b.length();
+ char c = b.charAt(i - 1);
+ if (c == ')') {
+ // Ignore suffix like " (ftUS)".
+ i = b.lastIndexOf(" (");
+ if (i < 0) return;
+ c = b.charAt(i - 1);
+ }
+ char sign;
+ switch (c) {
+ default: sign = 0; break;
+ case 'e': case 'n': sign = '+'; i--; break;
+ case 'w': case 's': sign = '-'; i--; break;
+ }
+ int upper = i;
+ do {
+ if (i == 0) return;
+ c = b.charAt(--i);
+ } while (c >= '0' && c <= '9');
+ switch (upper - ++i) {
+ case 2: b.insert(i, '0'); upper++; break; // Found 2 digits.
+ case 1: b.insert(i, "00"); upper+=2; break; // Only one digit found.
+ case 0: return; // No digit.
+ }
+ if (sign != 0) {
+ b.insert(i, sign);
+ upper++;
+ }
+ b.setLength(upper);
+ }
+
+ /**
+ * Compares this row wit the given row for ordering by name.
+ */
+ @Override public int compareTo(final Row o) {
+ int n = reducedName.compareTo(((ByName) o).reducedName);
+ if (n == 0) {
+ n = super.compareTo(o);
+ }
+ return n;
+ }
}
}