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 2017/05/08 00:11:15 UTC
svn commit: r1794274 - in /sis/branches/JDK8: ./ core/sis-metadata/
core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/
core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/
core/sis-metadata/src/test/java/org/apache/sis/intern...
Author: desruisseaux
Date: Mon May 8 00:11:14 2017
New Revision: 1794274
URL: http://svn.apache.org/viewvc?rev=1794274&view=rev
Log:
Initial port of MetadataWriter, not yet fully enabled.
Added:
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataWriter.java (with props)
sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataWriterTest.java (with props)
Modified:
sis/branches/JDK8/core/sis-metadata/pom.xml
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Dialect.java
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/SQLBuilder.java
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataSource.java
sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/internal/metadata/sql/ScriptRunnerTest.java
sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/IdentifierGeneratorTest.java
sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataSourceTest.java
sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties
sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties
sis/branches/JDK8/ide-project/NetBeans/nbproject/project.properties
sis/branches/JDK8/pom.xml
Modified: sis/branches/JDK8/core/sis-metadata/pom.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/pom.xml?rev=1794274&r1=1794273&r2=1794274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/pom.xml (original)
+++ sis/branches/JDK8/core/sis-metadata/pom.xml Mon May 8 00:11:14 2017
@@ -146,6 +146,11 @@ Implementations of metadata derived from
<type>test-jar</type>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.postgresql</groupId>
+ <artifactId>postgresql</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
Modified: sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Dialect.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Dialect.java?rev=1794274&r1=1794273&r2=1794274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Dialect.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Dialect.java [UTF-8] Mon May 8 00:11:14 2017
@@ -26,38 +26,38 @@ import org.apache.sis.util.CharSequences
* that can not (to our knowledge) be inferred from the {@link DatabaseMetaData}.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 0.7
+ * @version 0.8
* @since 0.7
* @module
*/
-enum Dialect {
+public enum Dialect {
/**
* The database is presumed to use ANSI SQL syntax.
*/
- ANSI(null),
+ ANSI(null, false),
/**
* The database uses Derby syntax. This is ANSI, with some constraints that PostgreSQL does not have
* (for example column with {@code UNIQUE} constraint must explicitly be specified as {@code NOT NULL}).
*/
- DERBY("derby"),
+ DERBY("derby", false),
/**
* The database uses HSQL syntax. This is ANSI, but does not allow {@code INSERT} statements inserting many lines.
* It also have a {@code SHUTDOWN} command which is specific to HSQLDB.
*/
- HSQL("hsqldb"),
+ HSQL("hsqldb", false),
/**
* The database uses PostgreSQL syntax. This is ANSI, but provided an a separated
* enumeration value because it allows a few additional commands like {@code VACUUM}.
*/
- POSTGRESQL("postgresql"),
+ POSTGRESQL("postgresql", true),
/**
* The database uses Oracle syntax. This is ANSI, but without {@code "AS"} keyword.
*/
- ORACLE("oracle");
+ ORACLE("oracle", false);
/**
* The protocol in JDBC URL, or {@code null} if unknown.
@@ -66,10 +66,24 @@ enum Dialect {
private final String protocol;
/**
+ * Whether this dialect support table inheritance.
+ */
+ public final boolean isTableInheritanceSupported;
+
+ /**
+ * {@code true} if child tables inherit the index of their parent tables.
+ * This feature is not yet supported in PostgreSQL.
+ *
+ * @see <a href="https://issues.apache.org/jira/browse/SIS-358">SIS-358</a>
+ */
+ public final boolean isIndexInheritanceSupported = false;
+
+ /**
* Creates a new enumeration value for a SQL dialect for the given protocol.
*/
- private Dialect(final String protocol) {
+ private Dialect(final String protocol, final boolean isTableInheritanceSupported) {
this.protocol = protocol;
+ this.isTableInheritanceSupported = isTableInheritanceSupported;
}
/**
Modified: sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/SQLBuilder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/SQLBuilder.java?rev=1794274&r1=1794273&r2=1794274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/SQLBuilder.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/SQLBuilder.java [UTF-8] Mon May 8 00:11:14 2017
@@ -34,7 +34,7 @@ public class SQLBuilder {
/**
* The database dialect. This is used for a few database-dependent syntax.
*/
- private final Dialect dialect;
+ public final Dialect dialect;
/**
* The characters used for quoting identifiers, or an empty string if none.
Modified: sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataSource.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataSource.java?rev=1794274&r1=1794273&r2=1794274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataSource.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataSource.java [UTF-8] Mon May 8 00:11:14 2017
@@ -57,6 +57,7 @@ import org.apache.sis.internal.metadata.
import org.apache.sis.internal.system.Loggers;
import org.apache.sis.internal.util.CollectionsExt;
import org.apache.sis.internal.util.UnmodifiableArrayList;
+import org.apache.sis.util.collection.Containers;
import org.apache.sis.util.collection.CodeListSet;
import org.apache.sis.util.collection.WeakValueHashMap;
import org.apache.sis.util.logging.WarningListeners;
@@ -85,6 +86,19 @@ import org.apache.sis.util.iso.Types;
*
* where {@code id} is the primary key value for the desired record in the {@code MD_Format} table.
*
+ * <div class="section">Properties</div>
+ * The constructor expects three Java arguments (the {@linkplain MetadataStandard metadata standard},
+ * the {@linkplain DataSource data source} and the database schema) completed by an arbitrary amount
+ * of optional arguments given as a map of properties.
+ * The following keys are recognized by {@code MetadataSource} and all other entries are ignored:
+ *
+ * <table class="sis">
+ * <caption>Optional properties at construction time</caption>
+ * <tr><th>Key</th> <th>Value type</th> <th>Description</th></tr>
+ * <tr><td>{@code "classloader"}</td> <td>{@link ClassLoader}</td> <td>The class loader to use for creating {@link Proxy} instances.</td></tr>
+ * <tr><td>{@code "maxStatements"}</td> <td>{@link Integer}</td> <td>Maximal number of {@link PreparedStatement}s that can be kept simultaneously open.</td></tr>
+ * </table>
+ *
* <div class="section">Concurrency</div>
* {@code MetadataSource} is thread-safe but is not concurrent. If concurrency is desired,
* multiple instances of {@code MetadataSource} can be created for the same {@link DataSource}.
@@ -101,13 +115,13 @@ public class MetadataSource implements A
* The catalog, set to {@code null} for now. This is defined as a constant in order to make easier
* to spot the places where catalog would be used, if we want to use it in a future version.
*/
- private static final String CATALOG = null;
+ static final String CATALOG = null;
/**
* The column name used for the identifiers. We do not quote this identifier;
* we will let the database uses its own lower-case / upper-case convention.
*/
- private static final String ID_COLUMN = "ID";
+ static final String ID_COLUMN = "ID";
/**
* The timeout before to close a prepared statement, in nanoseconds. This is set to 2 seconds,
@@ -293,7 +307,7 @@ public class MetadataSource implements A
synchronized (MetadataSource.class) {
ms = instance;
if (ms == null) {
- ms = new MetadataSource(MetadataStandard.ISO_19115, dataSource, "metadata", null, null);
+ ms = new MetadataSource(MetadataStandard.ISO_19115, dataSource, "metadata", null);
ms.install();
instance = ms;
}
@@ -308,18 +322,18 @@ public class MetadataSource implements A
* the database source are mandatory information.
* All other information are optional and can be {@code null}.
*
- * @param standard the metadata standard to implement.
- * @param dataSource the source for getting a connection to the database.
- * @param schema the database schema were metadata tables are stored, or {@code null} if none.
- * @param classloader the class loader to use for creating {@link Proxy} instances, or {@code null} for the default.
- * @param maxStatements maximal number of {@link PreparedStatement}s that can be kept simultaneously open,
- * or {@code null} for a default value.
+ * @param standard the metadata standard to implement.
+ * @param dataSource the source for getting a connection to the database.
+ * @param schema the database schema were metadata tables are stored, or {@code null} if none.
+ * @param properties additional options, or {@code null} if none. See class javadoc for a description.
*/
public MetadataSource(final MetadataStandard standard, final DataSource dataSource,
- final String schema, ClassLoader classloader, Integer maxStatements)
+ final String schema, final Map<String,?> properties)
{
ArgumentChecks.ensureNonNull("standard", standard);
ArgumentChecks.ensureNonNull("dataSource", dataSource);
+ ClassLoader classloader = Containers.property(properties, "classloader", ClassLoader.class);
+ Integer maxStatements = Containers.property(properties, "maxStatements", Integer.class);
if (classloader == null) {
classloader = getClass().getClassLoader();
}
@@ -425,9 +439,16 @@ public class MetadataSource implements A
}
/**
+ * Returns the database schema where metadata are stored, or {@code null} if none.
+ */
+ final String schema() {
+ return schema;
+ }
+
+ /**
* Returns a helper class for building SQL statements.
*/
- private SQLBuilder helper() throws SQLException {
+ final SQLBuilder helper() throws SQLException {
assert Thread.holdsLock(this);
if (helper == null) {
helper = new SQLBuilder(connection().getMetaData(), quoteSchema);
@@ -503,7 +524,7 @@ public class MetadataSource implements A
* Returns the table name for the specified class.
* This is usually the ISO 19115 name.
*/
- private static String getTableName(final Class<?> type) {
+ static String getTableName(Class<?> type) {
final UML annotation = type.getAnnotation(UML.class);
if (annotation == null) {
return type.getSimpleName();
@@ -531,7 +552,7 @@ public class MetadataSource implements A
* @param metadata the metadata to test.
* @return the identifier (primary key), or {@code null} if the given metadata is not a proxy.
*/
- private String proxy(final Object metadata) {
+ final String proxy(final Object metadata) {
return (metadata instanceof MetadataProxy) ? ((MetadataProxy) metadata).identifier(this) : null;
}
@@ -545,7 +566,7 @@ public class MetadataSource implements A
* @throws ClassCastException if the metadata object does not implement a metadata interface
* of the expected package.
*/
- private Map<String,Object> asMap(final Object metadata) throws ClassCastException {
+ final Map<String,Object> asValueMap(final Object metadata) throws ClassCastException {
return standard.asValueMap(metadata, null, KeyNamePolicy.UML_IDENTIFIER, ValueExistencePolicy.ALL);
}
@@ -557,7 +578,7 @@ public class MetadataSource implements A
* @return the given value, or its first element if the value is a collection,
* or {@code null} if the given value is null or an empty collection.
*/
- private static Object extractFromCollection(Object value) {
+ static Object extractFromCollection(Object value) {
while (value instanceof Iterable<?>) {
final Iterator<?> it = ((Iterable<?>) value).iterator();
if (!it.hasNext()) {
@@ -593,7 +614,7 @@ public class MetadataSource implements A
final Map<String,Object> asMap;
try {
table = getTableName(standard.getInterface(metadata.getClass()));
- asMap = asMap(metadata);
+ asMap = asValueMap(metadata);
} catch (ClassCastException e) {
throw new MetadataStoreException(Errors.format(
Errors.Keys.IllegalArgumentClass_2, "metadata", metadata.getClass()));
@@ -602,7 +623,7 @@ public class MetadataSource implements A
try (Statement stmt = connection().createStatement()) {
identifier = search(table, null, asMap, stmt, helper());
} catch (SQLException e) {
- throw new MetadataStoreException(e);
+ throw new MetadataStoreException(e.getLocalizedMessage(), Exceptions.unwrap(e));
}
}
}
@@ -622,7 +643,7 @@ public class MetadataSource implements A
* @return the identifier of the given metadata, or {@code null} if none.
* @throws SQLException if an error occurred while searching in the database.
*/
- private String search(final String table, Set<String> columns, final Map<String,Object> metadata,
+ final String search(final String table, Set<String> columns, final Map<String,Object> metadata,
final Statement stmt, final SQLBuilder helper) throws SQLException
{
assert Thread.holdsLock(this);
@@ -659,7 +680,7 @@ public class MetadataSource implements A
final Class<?> type = value.getClass();
if (standard.isMetadata(type)) {
dependency = search(getTableName(standard.getInterface(type)),
- null, asMap(value), stmt, new SQLBuilder(helper));
+ null, asValueMap(value), stmt, new SQLBuilder(helper));
if (dependency == null) {
return null; // Dependency not found.
}
@@ -692,7 +713,7 @@ public class MetadataSource implements A
if (identifier == null) {
identifier = candidate;
} else if (!identifier.equals(candidate)) {
- warning("search", resources().getLogRecord(
+ warning(MetadataSource.class, "search", Errors.getResources((Locale) null).getLogRecord(
Level.WARNING, Errors.Keys.DuplicatedElement_1, candidate));
break;
}
@@ -714,7 +735,7 @@ public class MetadataSource implements A
* @return the set of columns, or an empty set if the table has not yet been created.
* @throws SQLException if an error occurred while querying the database.
*/
- private Set<String> getExistingColumns(final String table) throws SQLException {
+ final Set<String> getExistingColumns(final String table) throws SQLException {
assert Thread.holdsLock(this);
Set<String> columns = tableColumns.get(table);
if (columns == null) {
@@ -964,20 +985,14 @@ public class MetadataSource implements A
}
/**
- * Returns the resources for warnings and error messages.
- */
- private static Errors resources() {
- return Errors.getResources((Locale) null);
- }
-
- /**
* Reports a warning.
*
+ * @param source the source class, either {@code MetadataSource} or {@code MetadataWriter}.
* @param method the method to report as the warning emitter.
* @param record the warning to report.
*/
- private void warning(final String method, final LogRecord record) {
- record.setSourceClassName(MetadataSource.class.getCanonicalName());
+ final void warning(final Class<? extends MetadataSource> source, final String method, final LogRecord record) {
+ record.setSourceClassName(source.getCanonicalName());
record.setSourceMethodName(method);
record.setLoggerName(Loggers.SQL);
listeners.warning(record);
@@ -1112,7 +1127,7 @@ public class MetadataSource implements A
*/
final LogRecord record = new LogRecord(Level.WARNING, e.toString());
record.setThrown(e);
- warning("closeExpired", record);
+ warning(MetadataSource.class, "closeExpired", record);
}
}
@@ -1137,7 +1152,7 @@ public class MetadataSource implements A
}
helper = null;
} catch (SQLException e) {
- throw new MetadataStoreException(e);
+ throw new MetadataStoreException(e.getLocalizedMessage(), Exceptions.unwrap(e));
}
}
}
Added: sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataWriter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataWriter.java?rev=1794274&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataWriter.java (added)
+++ sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataWriter.java [UTF-8] Mon May 8 00:11:14 2017
@@ -0,0 +1,677 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.metadata.sql;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.IdentityHashMap;
+import java.util.StringTokenizer;
+import java.util.logging.Level;
+import java.sql.Statement;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import javax.sql.DataSource;
+
+import org.opengis.util.CodeList;
+import org.opengis.metadata.Identifier;
+import org.opengis.metadata.citation.Citation;
+
+import org.apache.sis.util.Exceptions;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.resources.Messages;
+import org.apache.sis.util.iso.DefaultNameSpace;
+import org.apache.sis.util.collection.Containers;
+import org.apache.sis.metadata.MetadataStandard;
+import org.apache.sis.metadata.KeyNamePolicy;
+import org.apache.sis.metadata.TypeValuePolicy;
+import org.apache.sis.metadata.ValueExistencePolicy;
+import org.apache.sis.metadata.TitleProperty;
+import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.internal.metadata.sql.SQLBuilder;
+
+
+/**
+ * A connection to a metadata database with write capabilities. The database must have a schema of the given name,
+ * which can be initially empty. Tables and columns are created as needed when the {@link #add(Object)} method is
+ * invoked.
+ *
+ * <p>No more than one instance of {@code MetadataWriter} should be used for the same database.
+ * However multiple instances of {@code MetadataSource} can be used concurrently with a single
+ * {@code MetadataWriter} instance on the same database.</p>
+ *
+ * <div class="section">Properties</div>
+ * The constructor expects three Java arguments (the {@linkplain MetadataStandard metadata standard},
+ * the {@linkplain DataSource data source} and the database schema) completed by an arbitrary amount
+ * of optional arguments given as a map of properties.
+ * The following keys are recognized by {@code MetadataSource} and all other entries are ignored:
+ *
+ * <table class="sis">
+ * <caption>Optional properties at construction time</caption>
+ * <tr>
+ * <th>Key</th>
+ * <th>Value type</th>
+ * <th>Description</th>
+ * </tr><tr>
+ * <td>{@code "classloader"}</td>
+ * <td>{@link ClassLoader}</td>
+ * <td>The class loader to use for creating {@link java.lang.reflect.Proxy} instances.</td>
+ * </tr><tr>
+ * <td>{@code "maxStatements"}</td>
+ * <td>{@link Integer}</td>
+ * <td>Maximal number of {@link java.sql.PreparedStatement}s that can be kept simultaneously open.</td>
+ * </tr><tr>
+ * <td>{@code "maximumIdentifierLength"}</td>
+ * <td>{@link Integer}</td>
+ * <td>The maximal number of characters allowed for primary keys.
+ * This is the value given to the {@code VARCHAR} type when creating new {@code "ID"} columns.</td>
+ * </tr><tr>
+ * <td>{@code "maximumValueLength"}</td>
+ * <td>{@link Integer}</td>
+ * <td>Maximal number of characters allowed in text columns. This is the parameter given to the {@code VARCHAR}
+ * type when creating new columns. Attempts to insert a text longer than this limit will typically throws
+ * a {@link SQLException}, but the exact behavior is database-dependent.</td>
+ * </tr><tr>
+ * <td>{@code "columnCreationPolicy"}</td>
+ * <td>{@link ValueExistencePolicy}</td>
+ * <td>Whether columns should be created only for non-empty attributes ({@link ValueExistencePolicy#NON_EMPTY
+ * NON-EMPTY}, the default) or for all attributes ({@link ValueExistencePolicy#ALL ALL})</td>
+ * </tr>
+ * </table>
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 0.8
+ * @since 0.8
+ * @module
+ */
+public class MetadataWriter extends MetadataSource {
+ /**
+ * The name of the column for code list.
+ */
+ private static final String CODE_COLUMN = "CODE";
+
+ /**
+ * Minimum value allowed for {@link #maximumIdentifierLength}.
+ */
+ private static final int MINIMAL_LIMIT = 5;
+
+ /**
+ * Maximal length for the identifier. This applies also to code list values.
+ */
+ private final int maximumIdentifierLength;
+
+ /**
+ * Maximal length of values.
+ */
+ private final int maximumValueLength;
+
+ /**
+ * Whether the tables should contain a column for every attribute, or only for non-null
+ * and non-empty attributes. The default is {@link ValueExistencePolicy#NON_EMPTY NON-EMPTY}.
+ */
+ private final ValueExistencePolicy columnCreationPolicy;
+
+ /**
+ * Creates a new metadata writer.
+ *
+ * @param standard the metadata standard to implement.
+ * @param dataSource the source for getting a connection to the database.
+ * @param schema the database schema were metadata tables are stored, or {@code null} if none.
+ * @param properties additional options, or {@code null} if none. See class javadoc for a description.
+ */
+ public MetadataWriter(final MetadataStandard standard, final DataSource dataSource, final String schema,
+ final Map<String,?> properties)
+ {
+ super(standard, dataSource, schema, properties);
+ Integer maximumIdentifierLength = Containers.property(properties, "maximumIdentifierLength", Integer.class);
+ Integer maximumValueLength = Containers.property(properties, "maximumValueLength", Integer.class);
+ ValueExistencePolicy columnCreationPolicy = Containers.property(properties, "columnCreationPolicy", ValueExistencePolicy.class);
+ if (maximumIdentifierLength != null) {
+ ArgumentChecks.ensureBetween("maximumIdentifierLength", MINIMAL_LIMIT, 100, maximumIdentifierLength);
+ this.maximumIdentifierLength = maximumIdentifierLength;
+ } else {
+ this.maximumIdentifierLength = 24;
+ }
+ if (maximumValueLength != null) {
+ ArgumentChecks.ensureBetween("maximumValueLength", MINIMAL_LIMIT, Short.MAX_VALUE, maximumValueLength);
+ this.maximumValueLength = maximumValueLength;
+ } else {
+ this.maximumValueLength = 1000;
+ }
+ this.columnCreationPolicy = (columnCreationPolicy != null) ? columnCreationPolicy : ValueExistencePolicy.NON_EMPTY;
+ }
+
+ /**
+ * Adds the given metadata object to the database, if it does not already exists.
+ * If the database already contains a metadata equals to the given one, then the
+ * database is left unchanged and the identifier of the existing metadata is returned.
+ *
+ * @param metadata the metadata object to add.
+ * @return the identifier (primary key) of the metadata just added,
+ * or the identifier of the existing metadata is one exists.
+ * @throws MetadataStoreException if the metadata object does not implement a metadata interface
+ * of the expected package, if an exception occurred while reading or writing the database.
+ * In such case, the database content is left unchanged
+ * (i.e. this method is a <cite>all or nothing</cite> operation).
+ */
+ public String add(final Object metadata) throws MetadataStoreException {
+ String identifier = proxy(metadata);
+ if (identifier == null) try {
+ synchronized (this) {
+ final Connection connection = connection();
+ connection.setAutoCommit(false);
+ boolean success = false;
+ try {
+ try (Statement stmt = connection.createStatement()) {
+ if (metadata instanceof CodeList<?>) {
+ identifier = addCode(stmt, (CodeList<?>) metadata);
+ } else {
+ identifier = add(stmt, metadata, new IdentityHashMap<>(), null);
+ }
+ }
+ success = true;
+ } finally {
+ if (success) {
+ connection.commit();
+ } else {
+ connection.rollback();
+ }
+ connection.setAutoCommit(true);
+ }
+ }
+ } catch (ClassCastException e) {
+ throw new MetadataStoreException(Errors.format(
+ Errors.Keys.IllegalArgumentClass_2, "metadata", metadata.getClass()));
+ } catch (SQLException e) {
+ /*
+ * Derby sometime wraps SQLException into another SQLException. For making the stack strace a
+ * little bit simpler, keep only the root cause provided that the exception type is compatible.
+ */
+ throw new MetadataStoreException(e.getLocalizedMessage(), Exceptions.unwrap(e));
+ }
+ return identifier;
+ }
+
+ /**
+ * Implementation of the {@link #add(Object)} method. This method invokes itself recursively,
+ * and maintains a map of metadata inserted up to date in order to avoid infinite recursivity.
+ *
+ * @param stmt the statement to use for inserting data.
+ * @param metadata the metadata object to add.
+ * @param done the metadata objects already added, mapped to their primary keys.
+ * @param parent the primary key of the parent, or {@code null} if there is no parent.
+ * @return the identifier (primary key) of the metadata just added.
+ * @throws SQLException if an exception occurred while reading or writing the database.
+ * @throws ClassCastException if the metadata object does not implement a metadata interface
+ * of the expected package.
+ */
+ private String add(final Statement stmt, final Object metadata, final Map<Object,String> done,
+ final String parent) throws ClassCastException, SQLException
+ {
+ final SQLBuilder helper = helper();
+ /*
+ * Take a snapshot of the metadata content. We do that in order to protect ourself against
+ * concurrent changes in the metadata object. This protection is needed because we need to
+ * perform multiple passes on the same metadata.
+ */
+ final Map<String,Object> asValueMap = asValueMap(metadata);
+ final Map<String,Object> asSingletons = new LinkedHashMap<>();
+ for (final Map.Entry<String,Object> entry : asValueMap.entrySet()) {
+ asSingletons.put(entry.getKey(), extractFromCollection(entry.getValue()));
+ }
+ /*
+ * Search the database for an existing metadata.
+ */
+ final Class<?> implementationType = metadata.getClass();
+ final Class<?> interfaceType = standard.getInterface(implementationType);
+ final String table = getTableName(interfaceType);
+ final Set<String> columns = getExistingColumns(table);
+ String identifier = search(table, columns, asSingletons, stmt, helper);
+ if (identifier != null) {
+ if (done.put(metadata, identifier) != null) {
+ throw new AssertionError(metadata);
+ }
+ return identifier;
+ }
+ /*
+ * Trim the null values or empty collections. We perform this operation only after the check
+ * for existing entries, in order to take in account null values when checking existing entries.
+ */
+ if (columnCreationPolicy != ValueExistencePolicy.ALL) {
+ for (final Iterator<Object> it = asSingletons.values().iterator(); it.hasNext();) {
+ if (it.next() == null) {
+ it.remove();
+ }
+ }
+ }
+ /*
+ * Process to the table creation if it does not already exists. If the table has parents, they will be
+ * created first. The later will work only for database supporting table inheritance, like PostgreSQL.
+ * For other kind of database engine, we can not store metadata having parent interfaces.
+ */
+ createTable(stmt, interfaceType, table, columns);
+ /*
+ * Add missing columns if there is any. If columns are added, we will keep trace of foreigner keys in
+ * this process but will not create the constraints now because the foreigner tables may not exist yet.
+ * They will be created later by recursive calls to this method a little bit below.
+ */
+ Map<String,Class<?>> colTypes = null, colTables = null;
+ final Map<String,FKey> foreigners = new LinkedHashMap<>();
+ for (final String column : asSingletons.keySet()) {
+ if (!columns.contains(column)) {
+ if (colTypes == null) {
+ colTypes = standard.asTypeMap(implementationType, KeyNamePolicy.UML_IDENTIFIER, TypeValuePolicy.ELEMENT_TYPE);
+ colTables = standard.asTypeMap(implementationType, KeyNamePolicy.UML_IDENTIFIER, TypeValuePolicy.DECLARING_INTERFACE);
+ }
+ /*
+ * We have found a column to add. Check if the column actually needs to be added to the parent table
+ * (if such parent exists). In most case, the answer is "no" and 'addTo' is equals to 'table'.
+ */
+ String addTo = table;
+ if (helper.dialect.isTableInheritanceSupported) {
+ @SuppressWarnings("null")
+ final Class<?> declaring = colTables.get(column);
+ if (!interfaceType.isAssignableFrom(declaring)) {
+ addTo = getTableName(declaring);
+ }
+ }
+ /*
+ * Determine the column data type.
+ */
+ int maxLength = maximumValueLength;
+ Class<?> rt = colTypes.get(column);
+ if (CodeList.class.isAssignableFrom(rt) || standard.isMetadata(rt)) {
+ /*
+ * Found a reference to an other metadata. Remind that
+ * column for creating a foreign key constraint later.
+ */
+ maxLength = maximumIdentifierLength;
+ if (foreigners.put(column, new FKey(addTo, rt, null)) != null) {
+ throw new AssertionError(column); // Should never happen.
+ }
+ rt = null; // For forcing VARCHAR type.
+ }
+ stmt.executeUpdate(helper.createColumn(schema(), addTo, column, rt, maxLength));
+ columns.add(column);
+ }
+ }
+ /*
+ * Get the identifier for the new metadata. If no identifier is proposed, we will try to recycle
+ * the identifier of the parent. For example in ISO 19115, Contact (which contains phone number,
+ * etc.) is associated only to Responsibility. So it make sense to use the Responsibility ID for
+ * the contact info.
+ */
+ identifier = suggestIdentifier(metadata, asValueMap);
+ if (identifier == null) {
+ identifier = parent;
+ if (identifier == null) {
+ /*
+ * Arbitrarily pickup the first non-metadata attribute.
+ * Fallback on "unknown" if none are found.
+ */
+ identifier = "unknown";
+ for (final Object value : asSingletons.values()) {
+ if (value != null && !standard.isMetadata(value.getClass())) {
+ identifier = abbreviation(value.toString());
+ break;
+ }
+ }
+ }
+ }
+ /*
+ * Check for key collision. We will add a suffix if there is one. Note that the final identifier must be
+ * found before we put its value in the map, otherwise cyclic references (if any) will use the wrong value.
+ *
+ * First, we trim the identifier (primary key) to the maximal length. Then, the loop removes at most four
+ * additional characters if the identifier is still too long. After that point, if the identifier still too
+ * long, we will let the database driver produces its own SQLException.
+ */
+ try (IdentifierGenerator idCheck = new IdentifierGenerator(this, schema(), table, ID_COLUMN, helper)) {
+ for (int i=0; i<MINIMAL_LIMIT-1; i++) {
+ final int maxLength = maximumIdentifierLength - i;
+ if (identifier.length() > maxLength) {
+ identifier = identifier.substring(0, maxLength);
+ }
+ identifier = idCheck.identifier(identifier);
+ if (identifier.length() <= maximumIdentifierLength) {
+ break;
+ }
+ }
+ }
+ if (done.put(metadata, identifier) != null) {
+ throw new AssertionError(metadata);
+ }
+ /*
+ * Process all dependencies now. This block may invoke this method recursively.
+ * Once a dependency has been added to the database, the corresponding value in
+ * the 'asMap' HashMap is replaced by the identifier of the dependency we just added.
+ */
+ Map<String,FKey> referencedTables = null;
+ for (final Map.Entry<String,Object> entry : asSingletons.entrySet()) {
+ Object value = entry.getValue();
+ final Class<?> type = value.getClass();
+ if (CodeList.class.isAssignableFrom(type)) {
+ value = addCode(stmt, (CodeList<?>) value);
+ } else if (standard.isMetadata(type)) {
+ String dependency = proxy(value);
+ if (dependency == null) {
+ dependency = done.get(value);
+ if (dependency == null) {
+ dependency = add(stmt, value, done, identifier);
+ assert done.get(value) == dependency; // Really identity comparison.
+ if (!helper.dialect.isIndexInheritanceSupported) {
+ /*
+ * In a classical object-oriented model, the foreigner key constraints declared in the
+ * parent table would take in account the records in the child table and we would have
+ * nothing special to do. However PostgreSQL 9.1 does not yet inherit index. So if we
+ * detect that a column references some records in two different tables, then we must
+ * suppress the foreigner key constraint.
+ */
+ final String column = entry.getKey();
+ final Class<?> targetType = standard.getInterface(value.getClass());
+ FKey fkey = foreigners.get(column);
+ if (fkey != null && !targetType.isAssignableFrom(fkey.tableType)) {
+ /*
+ * The foreigner key constraint does not yet exist, so we can
+ * change the target table. Set the target to the child table.
+ */
+ fkey.tableType = targetType;
+ }
+ if (fkey == null) {
+ /*
+ * The foreigner key constraint may already exist. Get a list of all foreigner keys for
+ * the current table, then verify if the existing constraint references the right table.
+ */
+ if (referencedTables == null) {
+ referencedTables = new HashMap<>();
+ try (ResultSet rs = stmt.getConnection().getMetaData().getImportedKeys(CATALOG, schema(), table)) {
+ while (rs.next()) {
+ if ((schema() == null || schema().equals(rs.getString("PKTABLE_SCHEM"))) &&
+ (CATALOG == null || CATALOG.equals(rs.getString("PKTABLE_CAT"))))
+ {
+ referencedTables.put(rs.getString("FKCOLUMN_NAME"),
+ new FKey(rs.getString("PKTABLE_NAME"), null,
+ rs.getString("FK_NAME")));
+ }
+ }
+ }
+ }
+ fkey = referencedTables.remove(column);
+ if (fkey != null && !fkey.tableName.equals(getTableName(targetType))) {
+ /*
+ * The existing foreigner key constraint doesn't reference the right table.
+ * We have no other choice than removing it...
+ */
+ stmt.executeUpdate(helper.clear().append("ALTER TABLE ")
+ .appendIdentifier(schema(), table).append(" DROP CONSTRAINT ")
+ .appendIdentifier(fkey.keyName).toString());
+ warning(MetadataWriter.class, "add", Messages.getResources(null)
+ .getLogRecord(Level.WARNING, Messages.Keys.DroppedForeignerKey_1,
+ table + '.' + column + " ⇒ " + fkey.tableName + '.' + ID_COLUMN));
+ }
+ }
+ }
+ }
+ }
+ value = dependency;
+ }
+ entry.setValue(value);
+ }
+ /*
+ * Now that all dependencies have been inserted in the database, we can setup the foreigner key constraints
+ * if there is any. Note that we deferred the foreigner key creations not because of the missing rows,
+ * but because of missing tables (since new tables may be created in the process of inserting dependencies).
+ */
+ if (!foreigners.isEmpty()) {
+ for (final Map.Entry<String,FKey> entry : foreigners.entrySet()) {
+ final FKey fkey = entry.getValue();
+ Class<?> rt = fkey.tableType;
+ final boolean isCodeList = CodeList.class.isAssignableFrom(rt);
+ final String primaryKey;
+ if (isCodeList) {
+ primaryKey = CODE_COLUMN;
+ } else {
+ primaryKey = ID_COLUMN;
+ rt = standard.getInterface(rt);
+ }
+ final String column = entry.getKey();
+ final String target = getTableName(rt);
+ stmt.executeUpdate(helper.createForeignKey(
+ schema(), fkey.tableName, column, // Source (schema.table.column)
+ target, primaryKey, // Target (table.column)
+ !isCodeList)); // CASCADE if metadata, RESTRICT if CodeList.
+ /*
+ * In a classical object-oriented model, the constraint would be inherited by child tables.
+ * However this is not yet supported as of PostgreSQL 9.6. If inheritance is not supported,
+ * then we have to repeat the constraint creation in child tables.
+ */
+ if (!helper.dialect.isIndexInheritanceSupported && !table.equals(fkey.tableName)) {
+ stmt.executeUpdate(helper.createForeignKey(schema(), table, column, target, primaryKey, !isCodeList));
+ }
+ }
+ }
+ /*
+ * Create the SQL statement which will insert the data.
+ */
+ helper.clear().append("INSERT INTO ").appendIdentifier(schema(), table).append(" (").append(ID_COLUMN);
+ for (final String column : asSingletons.keySet()) {
+ helper.append(", ").appendIdentifier(column);
+ }
+ helper.append(") VALUES (").appendValue(identifier);
+ for (final Object value : asSingletons.values()) {
+ helper.append(", ").appendValue(value);
+ }
+ final String sql = helper.append(')').toString();
+ if (stmt.executeUpdate(sql) != 1) {
+ throw new SQLException(Errors.format(Errors.Keys.DatabaseUpdateFailure_3, 0, table, identifier));
+ }
+ return identifier;
+ }
+
+ /**
+ * Information about the source and the target of a foreigner key. This class stores only the table names
+ * (indirectly in the case of {@link #tableType}, since the name is derived from the type).
+ * The column name are known by other way: either as the map key in the case of the source,
+ * or fixed to {@value MetadataWriter#ID_COLUMN} in the case of the target.
+ */
+ private static final class FKey {
+ final String tableName; // May be source or target, depending on the context.
+ Class<?> tableType; // Always the target table.
+ final String keyName;
+
+ FKey(final String tableName, final Class<?> tableType, final String keyName) {
+ this.tableName = tableName;
+ this.tableType = tableType;
+ this.keyName = keyName;
+ }
+ }
+
+ /**
+ * Creates a table for the given type, if the table does not already exists.
+ * This method may call itself recursively for creating parent tables, if they do not exist neither.
+ *
+ * @param stmt the statement to use for creating tables.
+ * @param type the interface class.
+ * @param table the name of the table (should be consistent with the type).
+ * @param columns the existing columns, as an empty set if the table does not exist yet.
+ * @throws SQLException if an error occurred while creating the table.
+ */
+ private void createTable(final Statement stmt, final Class<?> type, final String table, final Set<String> columns)
+ throws SQLException
+ {
+ if (columns.isEmpty()) {
+ StringBuilder inherits = null;
+ for (final Class<?> candidate : type.getInterfaces()) {
+ if (standard.isMetadata(candidate)) {
+ final SQLBuilder helper = helper();
+ if (helper.dialect.isTableInheritanceSupported) {
+ final String parent = getTableName(candidate);
+ createTable(stmt, candidate, parent, getExistingColumns(parent));
+ if (inherits == null) {
+ helper.clear().append("CREATE TABLE ").appendIdentifier(schema(), table);
+ if (!helper.dialect.isIndexInheritanceSupported) {
+ /*
+ * In a classical object-oriented model, the new child table would inherit the index from
+ * its parent table. However this is not yet the case as of PostgreSQL 9.6. If the index is
+ * not inherited, then we have to repeat the primary key creation in every child tables.
+ */
+ helper.append("(CONSTRAINT ").appendIdentifier(table + "_pkey")
+ .append(" PRIMARY KEY (").append(ID_COLUMN).append(")) ");
+ }
+ inherits = new StringBuilder(helper.append(" INHERITS (").toString());
+ } else {
+ inherits.append(", ");
+ }
+ inherits.append(helper.clear().appendIdentifier(schema(), parent));
+ }
+ }
+ }
+ final String sql;
+ if (inherits != null) {
+ sql = inherits.append(')').toString();
+ } else {
+ sql = createTable(table, ID_COLUMN);
+ }
+ stmt.executeUpdate(sql);
+ columns.add(ID_COLUMN);
+ }
+ }
+
+ /**
+ * Returns the SQL statement for creating the given table with the given primary key.
+ * This method returns a string of the following form:
+ *
+ * {@preformat sql
+ * CREATE TABLE "schema"."table" (primaryKey VARCHAR(20) NOT NULL PRIMARY KEY)
+ * }
+ */
+ private String createTable(final String table, final String primaryKey) throws SQLException {
+ return helper().clear().append("CREATE TABLE ").appendIdentifier(schema(), table)
+ .append(" (").append(primaryKey).append(" VARCHAR(").append(maximumIdentifierLength)
+ .append(") NOT NULL PRIMARY KEY)").toString();
+ }
+
+ /**
+ * Adds a code list if it is not already present. This is used only in order to enforce
+ * foreigner key constraints in the database. The value of CodeList tables are not used
+ * at parsing time.
+ */
+ private String addCode(final Statement stmt, final CodeList<?> code) throws SQLException {
+ assert Thread.holdsLock(this);
+ final String table = getTableName(code.getClass());
+ final Set<String> columns = getExistingColumns(table);
+ if (columns.isEmpty()) {
+ stmt.executeUpdate(createTable(table, CODE_COLUMN));
+ columns.add(CODE_COLUMN);
+ }
+ final String identifier = code.name();
+ final String query = helper().clear().append("SELECT ").append(CODE_COLUMN)
+ .append(" FROM ").appendIdentifier(schema(), table).append(" WHERE ")
+ .append(CODE_COLUMN).appendCondition(identifier).toString();
+ final boolean exists;
+ try (ResultSet rs = stmt.executeQuery(query)) {
+ exists = rs.next();
+ }
+ if (!exists) {
+ final String sql = helper().clear().append("INSERT INTO ").appendIdentifier(schema(), table)
+ .append(" (").append(CODE_COLUMN).append(") VALUES (").appendValue(identifier)
+ .append(')').toString();
+ if (stmt.executeUpdate(sql) != 1) {
+ throw new SQLException(Errors.format(Errors.Keys.DatabaseUpdateFailure_3, 0, table, identifier));
+ }
+ }
+ return identifier;
+ }
+
+ /**
+ * Suggests an identifier (primary key) to be used for the given metadata. This method is invoked automatically
+ * when a new metadata is about to be inserted in the database. The default implementation uses heuristic rules
+ * of a few "well known" metadata like {@link Identifier} and {@link Citation}. Subclasses can override this method
+ * for implementing their own heuristic.
+ *
+ * <p>This method does not need to care about key collision.
+ * The caller will adds some suffix if this is necessary for differentiating otherwise identical identifiers.</p>
+ *
+ * @param metadata the metadata instance for which to suggests an identifier.
+ * @param asValueMap a view of all metadata properties as a map.
+ * Keys are {@linkplain KeyNamePolicy#UML_IDENTIFIER UML identifiers}.
+ * @return the proposed identifier, or {@code null} if this method does not have any suggestion.
+ * @throws SQLException if an access to the database was desired but failed.
+ */
+ protected String suggestIdentifier(final Object metadata, final Map<String,Object> asValueMap) throws SQLException {
+ String identifier = null;
+ if (metadata instanceof Identifier) {
+ identifier = nonEmpty(((Identifier) metadata).getCode());
+ final String cs = nonEmpty(((Identifier) metadata).getCodeSpace());
+ if (cs != null) {
+ identifier = (identifier != null) ? (cs + DefaultNameSpace.DEFAULT_SEPARATOR + identifier) : cs;
+ }
+ }
+ if (identifier == null && metadata instanceof Citation) {
+ identifier = nonEmpty(Citations.getIdentifier((Citation) metadata));
+ }
+ if (identifier == null) {
+ final TitleProperty tp = metadata.getClass().getAnnotation(TitleProperty.class);
+ if (tp != null) {
+ final Object value = asValueMap.get(nonEmpty(tp.name()));
+ if (value != null) {
+ identifier = nonEmpty(value.toString());
+ }
+ }
+ }
+ /*
+ * At this point we got a suggested identifier, but it may be quite long.
+ * For example it may be a citation title. Try to make an abbreviation.
+ */
+ if (identifier != null && identifier.length() >= 8) { // Arbitrary threshold.
+ identifier = abbreviation(identifier);
+ }
+ return identifier;
+ }
+
+ /**
+ * Returns an abbreviation of the given identifier, if one is found.
+ */
+ private static String abbreviation(final String identifier) {
+ final StringBuilder buffer = new StringBuilder();
+ final StringTokenizer tokens = new StringTokenizer(identifier);
+ while (tokens.hasMoreTokens()) {
+ buffer.appendCodePoint(tokens.nextToken().codePointAt(0));
+ }
+ if (buffer.length() >= 3) {
+ return buffer.toString();
+ }
+ return identifier;
+ }
+
+ /**
+ * Trims leading and trailing spaces and returns the given value if non-empty, or {@code null} otherwise.
+ */
+ private static String nonEmpty(String value) {
+ if (value != null) {
+ value = value.trim();
+ if (value.isEmpty()) {
+ value = null;
+ }
+ }
+ return value;
+ }
+}
Propchange: sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataWriter.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataWriter.java
------------------------------------------------------------------------------
svn:mime-type = text/plain;charset=UTF-8
Modified: sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/internal/metadata/sql/ScriptRunnerTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/internal/metadata/sql/ScriptRunnerTest.java?rev=1794274&r1=1794273&r2=1794274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/internal/metadata/sql/ScriptRunnerTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/internal/metadata/sql/ScriptRunnerTest.java [UTF-8] Mon May 8 00:11:14 2017
@@ -42,7 +42,7 @@ public final strictfp class ScriptRunner
*/
@Test
public void testOnDerby() throws Exception {
- final DataSource ds = TestDatabase.create("temporary");
+ final DataSource ds = TestDatabase.create("ScriptRunner");
try (Connection c = ds.getConnection()) {
final ScriptRunner sr = new ScriptRunner(c, 3);
testSupportedFlags(sr);
Modified: sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/IdentifierGeneratorTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/IdentifierGeneratorTest.java?rev=1794274&r1=1794273&r2=1794274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/IdentifierGeneratorTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/IdentifierGeneratorTest.java [UTF-8] Mon May 8 00:11:14 2017
@@ -59,9 +59,9 @@ public final strictfp class IdentifierGe
*/
@Test
public void testSequence() throws Exception {
- final DataSource ds = TestDatabase.create("identifiers");
+ final DataSource ds = TestDatabase.create("IdentifierGenerator");
try {
- final MetadataSource source = new MetadataSource(MetadataStandard.ISO_19115, ds, null, null, 2);
+ final MetadataSource source = new MetadataSource(MetadataStandard.ISO_19115, ds, null, null);
synchronized (source) {
stmt = source.connection().createStatement();
stmt.executeUpdate("CREATE TABLE \"" + TABLE + "\" (ID VARCHAR(6) NOT NULL PRIMARY KEY)");
Modified: sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataSourceTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataSourceTest.java?rev=1794274&r1=1794273&r2=1794274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataSourceTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataSourceTest.java [UTF-8] Mon May 8 00:11:14 2017
@@ -52,8 +52,8 @@ public final strictfp class MetadataSour
*/
@Test
public void testOnDerby() throws Exception {
- final DataSource ds = TestDatabase.create("temporary");
- try (MetadataSource source = new MetadataSource(MetadataStandard.ISO_19115, ds, "metadata", null, null)) {
+ final DataSource ds = TestDatabase.create("MetadataSource");
+ try (MetadataSource source = new MetadataSource(MetadataStandard.ISO_19115, ds, "metadata", null)) {
source.install();
verifyFormats(source);
testSearch(source);
Added: sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataWriterTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataWriterTest.java?rev=1794274&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataWriterTest.java (added)
+++ sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataWriterTest.java [UTF-8] Mon May 8 00:11:14 2017
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.metadata.sql;
+
+import javax.sql.DataSource;
+import org.postgresql.ds.PGSimpleDataSource;
+import org.opengis.metadata.citation.Citation;
+import org.opengis.metadata.citation.Responsibility;
+import org.opengis.metadata.citation.PresentationForm;
+import org.opengis.metadata.citation.OnLineFunction;
+import org.opengis.metadata.citation.OnlineResource;
+import org.opengis.metadata.citation.Party;
+import org.opengis.metadata.citation.Role;
+import org.apache.sis.internal.metadata.sql.TestDatabase;
+import org.apache.sis.metadata.iso.citation.HardCodedCitations;
+import org.apache.sis.metadata.MetadataStandard;
+import org.apache.sis.test.TestUtilities;
+import org.apache.sis.test.TestCase;
+import org.apache.sis.test.DependsOn;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * Creates a metadata database, stores a few elements and read them back.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 0.8
+ * @since 0.8
+ * @module
+ */
+@DependsOn({
+ MetadataSourceTest.class,
+ IdentifierGeneratorTest.class
+})
+public final strictfp class MetadataWriterTest extends TestCase {
+ /**
+ * The data source providing connections to the database.
+ */
+ private MetadataWriter source;
+
+ /**
+ * Runs all tests on JavaDB in the required order.
+ *
+ * @throws Exception if an error occurred while writing or reading the database.
+ */
+ @Test
+ public void testDerby() throws Exception {
+ final DataSource ds = TestDatabase.create("MetadataWriter");
+ source = new MetadataWriter(MetadataStandard.ISO_19115, ds, null, null);
+ try {
+ write();
+ search();
+// read();
+ source.close();
+ } finally {
+ TestDatabase.drop(ds);
+ }
+ }
+
+ /**
+ * Runs all tests on PostgreSQL in the required order. This test is disabled by default
+ * because it requires manual setup of a test database.
+ *
+ * @throws Exception if an error occurred while writing or reading the database.
+ */
+ @Test
+ @Ignore("This test need to be run manually on a machine having a local PostgreSQL database.")
+ public void testPostgreSQL() throws Exception {
+ final PGSimpleDataSource ds = new PGSimpleDataSource();
+ ds.setServerName("localhost");
+ ds.setDatabaseName("SpatialMetadataTest");
+ source = new MetadataWriter(MetadataStandard.ISO_19115, ds, "metadata", null);
+ try {
+ write();
+ search();
+ read();
+ } finally {
+ source.close();
+ }
+ }
+
+ /**
+ * Creates a new temporary database and write elements in it.
+ *
+ * @throws MetadataStoreException if an error occurred while writing or reading the database.
+ */
+ private void write() throws MetadataStoreException {
+ assertEquals("ISO 19115", source.add(HardCodedCitations.ISO_19115));
+ assertEquals("EPSG", source.add(HardCodedCitations.EPSG));
+ assertEquals("SIS", source.add(HardCodedCitations.SIS));
+ }
+
+ /**
+ * Searches known entries in the database.
+ *
+ * @throws MetadataStoreException if an error occurred while reading the database.
+ */
+ private void search() throws MetadataStoreException {
+ assertNull ("ISO 19111", source.search(HardCodedCitations.ISO_19111));
+ assertEquals("ISO 19115", source.search(HardCodedCitations.ISO_19115));
+ assertEquals("EPSG", source.search(HardCodedCitations.EPSG));
+ assertEquals("SIS", source.search(HardCodedCitations.SIS));
+ assertNull ("ISO 19111", source.search(HardCodedCitations.ISO_19111));
+ assertEquals("EPSG", source.search(TestUtilities.getSingleton(
+ HardCodedCitations.EPSG.getCitedResponsibleParties())));
+ }
+
+ /**
+ * Reads known entries in the database.
+ * Expected entry is:
+ *
+ * {@preformat text
+ * Citation
+ * ├─Title………………………………………………………… EPSG Geodetic Parameter Dataset
+ * ├─Identifier
+ * │ └─Code………………………………………………… EPSG
+ * ├─Cited responsible party
+ * │ ├─Party
+ * │ │ ├─Name……………………………………… International Association of Oil & Gas Producers
+ * │ │ └─Contact info
+ * │ │ └─Online resource
+ * │ │ ├─Linkage………… http://www.epsg.org
+ * │ │ └─Function……… Information
+ * │ └─Role………………………………………………… Principal investigator
+ * └─Presentation form………………………… Table digital
+ * }
+ *
+ * @throws MetadataStoreException if an error occurred while reading the database.
+ */
+ private void read() throws MetadataStoreException {
+ final Citation c = source.lookup(Citation.class, "EPSG");
+ assertEquals("EPSG Geodetic Parameter Dataset", c.getTitle().toString());
+ assertEquals(PresentationForm.TABLE_DIGITAL, TestUtilities.getSingleton(c.getPresentationForms()));
+ /*
+ * Ask for dependencies that are known to exist.
+ */
+ final Responsibility responsible = TestUtilities.getSingleton(c.getCitedResponsibleParties());
+ assertEquals(Role.PRINCIPAL_INVESTIGATOR, responsible.getRole());
+
+ final Party party = TestUtilities.getSingleton(responsible.getParties());
+ assertEquals("International Association of Oil & Gas Producers", party.getName().toString());
+
+ OnlineResource resource = TestUtilities.getSingleton(TestUtilities.getSingleton(party.getContactInfo()).getOnlineResources());
+ assertEquals("http://www.epsg.org", resource.getLinkage().toString());
+ assertEquals(OnLineFunction.INFORMATION, resource.getFunction());
+ /*
+ * Ask columns that are known to not exist.
+ */
+ assertNull(c.getEditionDate());
+ assertTrue(c.getDates().isEmpty());
+ assertEquals(0, c.getAlternateTitles().size());
+ /*
+ * Test the cache.
+ */
+ assertSame (c, source.lookup(Citation.class, "EPSG"));
+ assertNotSame(c, source.lookup(Citation.class, "SIS"));
+ /*
+ * Should return the identifier with no search. Actually the real test is the call to "proxy",
+ * since there is no way to ensure that the call to "search" tooks the short path (except by
+ * looking at the debugger). But if "proxy" succeed, then "search" should be okay.
+ */
+ assertEquals("EPSG", source.proxy (c));
+ assertEquals("EPSG", source.search(c));
+ }
+}
Propchange: sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataWriterTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/sql/MetadataWriterTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain;charset=UTF-8
Modified: sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java?rev=1794274&r1=1794273&r2=1794274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java [UTF-8] Mon May 8 00:11:14 2017
@@ -107,7 +107,8 @@ import org.junit.BeforeClass;
org.apache.sis.internal.metadata.sql.TypeMapperTest.class,
org.apache.sis.internal.metadata.sql.ScriptRunnerTest.class,
org.apache.sis.metadata.sql.IdentifierGeneratorTest.class,
- org.apache.sis.metadata.sql.MetadataSourceTest.class
+ org.apache.sis.metadata.sql.MetadataSourceTest.class,
+ org.apache.sis.metadata.sql.MetadataWriterTest.class
})
public final strictfp class MetadataTestSuite extends TestSuite {
/**
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=1794274&r1=1794273&r2=1794274&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] Mon May 8 00:11:14 2017
@@ -27,6 +27,7 @@ import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import org.postgresql.ds.PGSimpleDataSource;
import org.opengis.util.FactoryException;
import org.opengis.referencing.crs.GeographicCRS;
import org.opengis.referencing.crs.ProjectedCRS;
@@ -129,13 +130,13 @@ public final strictfp class EPSGInstalle
@Test
public void testCreationOnDerby() throws Exception {
final InstallationScriptProvider scripts = getScripts(); // Needs to be invoked first.
- final DataSource ds = TestDatabase.create("test");
+ final DataSource ds = TestDatabase.create("EPSGInstaller");
try {
createAndTest(ds, scripts);
} finally {
TestDatabase.drop(ds);
}
- loggings.assertNextLogContains("EPSG", "jdbc:derby:memory:test");
+ loggings.assertNextLogContains("EPSG", "jdbc:derby:memory:EPSGInstaller");
loggings.assertNoUnexpectedLog();
}
@@ -149,7 +150,7 @@ public final strictfp class EPSGInstalle
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");
+ ds.getClass().getMethod("setURL", String.class).invoke(ds, "jdbc:hsqldb:mem:EPSGInstaller");
try {
createAndTest(ds, scripts);
} finally {
@@ -157,7 +158,7 @@ public final strictfp class EPSGInstalle
s.execute("SHUTDOWN");
}
}
- loggings.assertNextLogContains("EPSG", "jdbc:hsqldb:mem:test");
+ loggings.assertNextLogContains("EPSG", "jdbc:hsqldb:mem:EPSGInstaller");
loggings.assertNoUnexpectedLog();
}
@@ -176,10 +177,9 @@ public final strictfp class EPSGInstalle
@Ignore("This test need to be run manually on a machine having a local PostgreSQL database.")
public void testCreationOnPostgreSQL() throws Exception {
final InstallationScriptProvider scripts = getScripts(); // Needs to be invoked first.
- final DataSource ds = (DataSource) Class.forName("org.postgresql.ds.PGSimpleDataSource").newInstance();
- final Class<?> dsc = ds.getClass();
- dsc.getMethod("setServerName", String.class).invoke(ds, "localhost");
- dsc.getMethod("setDatabaseName", String.class).invoke(ds, "SpatialMetadataTest");
+ final PGSimpleDataSource ds = new PGSimpleDataSource();
+ ds.setServerName("localhost");
+ ds.setDatabaseName("SpatialMetadataTest");
createAndTest(ds, scripts);
loggings.assertNextLogContains("EPSG", "jdbc:postgresql://localhost/SpatialMetadataTest");
loggings.assertNoUnexpectedLog();
Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1794274&r1=1794273&r2=1794274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] Mon May 8 00:11:14 2017
@@ -186,6 +186,11 @@ public final class Errors extends Indexe
public static final short DatabaseError_2 = 21;
/**
+ * Failed to {0,choice,0#insert|1#update} record “{2}” in database table “{1}”.
+ */
+ public static final short DatabaseUpdateFailure_3 = 174;
+
+ /**
* Thread “{0}” is dead.
*/
public static final short DeadThread_1 = 22;
Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1794274&r1=1794273&r2=1794274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] Mon May 8 00:11:14 2017
@@ -48,6 +48,7 @@ ClassNotFinal_1 = Clas
CloneNotSupported_1 = Can not clone an object of type \u2018{0}\u2019.
CrossReferencesNotSupported = Cross references are not supported.
DatabaseError_2 = Database error while creating a \u2018{0}\u2019 object for the \u201c{1}\u201d identifier.
+DatabaseUpdateFailure_3 = Failed to {0,choice,0#insert|1#update} record \u201c{2}\u201d in database table \u201c{1}\u201d.
DeadThread_1 = Thread \u201c{0}\u201d is dead.
DisposedInstanceOf_1 = This instance of \u2018{0}\u2019 has been disposed.
DuplicatedElement_1 = Element \u201c{0}\u201d is duplicated.
Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1794274&r1=1794273&r2=1794274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] Mon May 8 00:11:14 2017
@@ -45,6 +45,7 @@ ClassNotFinal_1 = La c
CloneNotSupported_1 = Un objet de type \u2018{0}\u2019 ne peut pas \u00eatre clon\u00e9.
CrossReferencesNotSupported = Les r\u00e9f\u00e9rences crois\u00e9es ne sont pas support\u00e9es.
DatabaseError_2 = Erreur de base de donn\u00e9es lors de la cr\u00e9ation d\u2019un objet \u2018{0}\u2019 pour l\u2019identifiant \u00ab\u202f{1}\u202f\u00bb.
+DatabaseUpdateFailure_3 = \u00c9chec lors de {0,choice,0#l\u2019insertion|1#la mise \u00e0 jour} de l\u2019enregistrement \u00ab\u202f{2}\u202f\u00bb dans la table \u00ab\u202f{1}\u202f\u00bb de la base de donn\u00e9es.
DeadThread_1 = La t\u00e2che \u00ab\u202f{0}\u202f\u00bb est morte.
DisposedInstanceOf_1 = Cette instance de \u2018{0}\u2019 a \u00e9t\u00e9 dispos\u00e9e.
DuplicatedElement_1 = L\u2019\u00e9lement \u00ab\u202f{0}\u202f\u00bb est dupliqu\u00e9.
Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java?rev=1794274&r1=1794273&r2=1794274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java [UTF-8] Mon May 8 00:11:14 2017
@@ -154,6 +154,11 @@ public final class Messages extends Inde
public static final short DiscardedExclusiveProperty_2 = 19;
/**
+ * Dropped the “{0}” foreigner key constraint.
+ */
+ public static final short DroppedForeignerKey_1 = 32;
+
+ /**
* Ignored properties after the first occurrence of ‘{0}’.
*/
public static final short IgnoredPropertiesAfterFirst_1 = 20;
Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties?rev=1794274&r1=1794273&r2=1794274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties [ISO-8859-1] Mon May 8 00:11:14 2017
@@ -34,6 +34,7 @@ DataDirectoryNotReadable_2 = The \
DataDirectoryNotSpecified_1 = The \u201c{0}\u201d environment variable is not set.
DataDirectoryNotWritable_2 = Apache SIS can not write in the \u201c{1}\u201d directory given by the {0} environment variable.
DiscardedExclusiveProperty_2 = Property \u201c{0}\u201d has been discarded in favor of \u201c{1}\u201d, because those two properties are mutually exclusive.
+DroppedForeignerKey_1 = Dropped the \u201c{0}\u201d foreigner key constraint.
IgnoredPropertiesAfterFirst_1 = Ignored properties after the first occurrence of \u2018{0}\u2019.
IgnoredPropertyAssociatedTo_1 = Ignored property associated to \u2018{0}\u2019.
IncompleteParsing_1 = Parsing of \u201c{0}\u201d done, but some elements were ignored.
Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties?rev=1794274&r1=1794273&r2=1794274&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties [ISO-8859-1] Mon May 8 00:11:14 2017
@@ -41,6 +41,7 @@ DataDirectoryNotReadable_2 = Le r\
DataDirectoryNotSpecified_1 = La variable environnementale \u00ab\u202f{0}\u202f\u00bb n\u2019est pas d\u00e9finie.
DataDirectoryNotWritable_2 = Apache SIS ne peut pas \u00e9crire dans le r\u00e9pertoire \u00ab\u202f{1}\u202f\u00bb sp\u00e9cifi\u00e9e par la variable environnementale {0}.
DiscardedExclusiveProperty_2 = La propri\u00e9t\u00e9 \u00ab\u202f{0}\u202f\u00bb a \u00e9t\u00e9 \u00e9cart\u00e9e en faveur de \u00ab\u202f{1}\u202f\u00bb, parce que ces deux propri\u00e9t\u00e9s sont mutuellement exclusives.
+DroppedForeignerKey_1 = Suppression de la contrainte de cl\u00e9 \u00e9trang\u00e8re \u00ab\u202f{0}\u202f\u00bb.
IgnoredPropertiesAfterFirst_1 = Des propri\u00e9t\u00e9s ont \u00e9t\u00e9 ignor\u00e9es apr\u00e8s la premi\u00e8re occurrence de \u2018{0}\u2019.
IgnoredPropertyAssociatedTo_1 = Une propri\u00e9t\u00e9 associ\u00e9e \u00e0 \u2018{0}\u2019 a \u00e9t\u00e9 ignor\u00e9e.
IncompleteParsing_1 = La lecture de \u00ab\u202f{0}\u202f\u00bb a \u00e9t\u00e9 faite, mais en ignorant certains \u00e9l\u00e9ments.
Modified: sis/branches/JDK8/ide-project/NetBeans/nbproject/project.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/ide-project/NetBeans/nbproject/project.properties?rev=1794274&r1=1794273&r2=1794274&view=diff
==============================================================================
--- sis/branches/JDK8/ide-project/NetBeans/nbproject/project.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/ide-project/NetBeans/nbproject/project.properties [ISO-8859-1] Mon May 8 00:11:14 2017
@@ -106,7 +106,7 @@ junit.version = 4.12
hamcrest.version = 1.3
jaxb-ns-mapper = 2.2.4
hsqldb.version = 2.3.4
-postgresql.version = 42.0.0
+postgresql.version = 42.1.1
#
# Classpaths for compilation, execution and tests.
@@ -131,6 +131,7 @@ javac.test.classpath=\
${javac.classpath}:\
${maven.repository}/junit/junit/${junit.version}/junit-${junit.version}.jar:\
${maven.repository}/org/hamcrest/hamcrest-core/${hamcrest.version}/hamcrest-core-${hamcrest.version}.jar:\
+ ${maven.repository}/org/postgresql/postgresql/${postgresql.version}/postgresql-${postgresql.version}.jar:\
${maven.repository}/gov/nist/math/jama/${jama.version}/jama-${jama.version}.jar:\
${project.GeoAPI}/dist/geoapi-tests.jar:\
${build.classes.dir}
@@ -143,7 +144,6 @@ run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}:\
${maven.repository}/org/hsqldb/hsqldb/${hsqldb.version}/hsqldb-${hsqldb.version}.jar:\
- ${maven.repository}/org/postgresql/postgresql/${postgresql.version}/postgresql-${postgresql.version}.jar:\
${maven.repository}/org/jdom/jdom2/${jdom2.version}/jdom2-${jdom2.version}.jar:\
${maven.repository}/edu/ucar/udunits/${netcdf.version}/udunits-${netcdf.version}.jar:\
${maven.repository}/edu/ucar/httpservices/${netcdf.version}/httpservices-${netcdf.version}.jar:\
Modified: sis/branches/JDK8/pom.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/pom.xml?rev=1794274&r1=1794273&r2=1794274&view=diff
==============================================================================
--- sis/branches/JDK8/pom.xml (original)
+++ sis/branches/JDK8/pom.xml Mon May 8 00:11:14 2017
@@ -438,7 +438,7 @@ Apache SIS is a free software, Java lang
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
- <version>42.0.0</version>
+ <version>42.1.1</version>
<scope>test</scope>
</dependency>