Class MetadataSource
- All Implemented Interfaces:
AutoCloseable
- Direct Known Subclasses:
MetadataFallback,MetadataWriter
id is the primary key value for the desired record in the Format table.
Properties
The constructor expects three Java arguments (the metadata standard, the 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 byMetadataSource and all other entries are ignored:
| Key | Value type | Description |
|---|---|---|
"catalog" | String | The database catalog where the metadata schema is stored. |
"classloader" | ClassLoader | The class loader to use for creating Proxy instances. |
"maxStatements" | Integer | Maximal number of PreparedStatements that can be kept simultaneously open. |
Concurrency
MetadataSource is thread-safe but is not concurrent. If concurrency is desired,
multiple instances of MetadataSource can be created for the same DataSource.
The MetadataSource(MetadataSource) convenience constructor can be used for this purpose.- Since:
- 0.8
- Version:
- 1.2
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate final classA task to be executed later for closing all expiredCachedStatement. -
Field Summary
FieldsModifier and TypeFieldDescription(package private) final StringThe catalog, ornullif none.private final ClassLoaderThe class loader to use for creatingProxyinstances.private ConnectionThe connection to the database, ornullif not yet created or if closed.private final DataSourceThe data source object for fetching the connection to the database.private static final intAn extra delay to add to theTIMEOUTin order to increase the chances to close many statements at once.private SQLBuilderA helper class used for constructing SQL statements.(package private) static final StringThe column name used for the identifiers.private static MetadataSourceThe instance connected to the"jdbc/SpatialMetadata"database, created when first needed and cleared when the classpath change.private booleanWhether at least oneMetadataSource.CloseTaskis scheduled for execution.private final ThreadLocal<LookupInfo>Some information about last used objects.private FilterWhere to report the warnings before to eventually log them.(package private) static final KeyNamePolicyThe policy for column names.private final WeakValueHashMap<CacheKey,Object> The objects which have been created by a previous call tolookup(Class, String).private booleanWhether thehelpershould quote schemas in SQL statements.private StringThe database schema where metadata are stored, ornullif none.protected final MetadataStandardThe metadata standard to be used for constructing the database schema.private final CachedStatement[]A pool of prepared statements with a maximal capacity equals to the array length.All columns found in tables that have been queried or created up to date.private static final longThe timeout before to close a prepared statement, in nanoseconds. -
Constructor Summary
ConstructorsConstructorDescriptionForMetadataFallbackconstructor only.MetadataSource(MetadataStandard standard, DataSource dataSource, String schema, Map<String, ?> properties) Creates a new metadata source.MetadataSource(MetadataSource source) Creates a new metadata source with the same configuration than the given source. -
Method Summary
Modifier and TypeMethodDescriptionasValueMap(Object metadata) Returns a view of the given metadata as a map.voidclose()Closes the database connection used by this object.(package private) final voidExecuted in a background thread for closing statements after their expiration time.private voidcloseQuietly(AutoCloseable resource) Closes the given resource without throwing exception.(package private) final ConnectionReturns the connection to the database, creating a new one if needed.(package private) static ObjectextractFromCollection(Object value) If the given value is a collection, returns the first element in that collection ornullif empty.(package private) static org.opengis.util.CodeList<?>getCodeList(Class<?> type, String name) Returns the code of the given type and name.getExistingColumns(String table) Returns the set of all columns in a table, or an empty set if none (nevernull).(package private) final LookupInfogetLookupInfo(Class<?> type) Gets theLookupInfoinstance for call to thereadColumn(LookupInfo, Method, Dispatcher)method.static MetadataSourceReturns the metadata source connected to the"jdbc/SpatialMetadata"database.(package private) static StringgetTableName(Class<?> type) Returns the table name for the specified class.Returns the current warning filter.(package private) final SQLBuilderhelper()Returns a helper class for building SQL statements.(package private) final voidinstall()If the metadata schema does not exist in the database, creates it and inserts the predefined metadata values.private ObjectImplementation of publiclookup(Class, String)method.<T> TReturns an implementation of the specified metadata interface filled with the data referenced by the specified identifier.private CachedStatementprepareStatement(Class<?> type, String tableName, int preferredIndex) Returns a statement that can be reused for performing queries on the table for the specified interface.(package private) final StringIf the given metadata is a proxy generated by thisMetadataSource, returns the identifier of that proxy.(package private) final ObjectreadColumn(LookupInfo info, Method method, Dispatcher toSearch) Invoked byMetadataProxyfor fetching an attribute value from a table.private intrecycle(CachedStatement statement, int preferredIndex) Flags the givenCachedStatementas available for reuse.private voidSchedules a task for closing the statements and the connection, if no such task is scheduled.(package private) final Stringschema()Returns the database schema where metadata are stored, ornullif none.Searches for the given metadata in the database.(package private) final Stringsearch(String table, Set<String> columns, Map<String, Object> metadata, Statement stmt, SQLBuilder helper) Searches for the given metadata in the database.setWarningFilter(Filter filter) Sets a filter to be notified when a warning occurred while reading from or writing metadata.private static <E> Collection<?>specialize(Collection<?> collection, Class<?> returnType, Class<E> elementType) Copies the given collection into the bestSetimplementation if possible, or returns the given collection unchanged otherwise.(package private) static ObjecttoStorableValue(Object value) Converts the given object to a value that can be stored in the database.(package private) final voidwarning(Class<? extends MetadataSource> source, String method, LogRecord record) Reports a warning.
-
Field Details
-
NAME_POLICY
The policy for column names. We use UML identifiers (e.g."title") as defined by the metadata standard (typically ISO 19115). -
ID_COLUMN
The column name used for the identifiers.- See Also:
-
TIMEOUT
private static final long TIMEOUTThe timeout before to close a prepared statement, in nanoseconds. This is set to 2 seconds, which is a bit short but should be okay if theDataSourcecreates pooled connections. In case there is no connection pool, then the mechanism defined in this package will hopefully keeps the performance at a reasonable level.- See Also:
-
EXTRA_DELAY
private static final int EXTRA_DELAYAn extra delay to add to theTIMEOUTin order to increase the chances to close many statements at once.- See Also:
-
standard
The metadata standard to be used for constructing the database schema. -
dataSource
The data source object for fetching the connection to the database. This is specified at construction time. -
connection
The connection to the database, ornullif not yet created or if closed. This field is set to a non-null value whenconnection()is invoked, then closed and set tonullafter all cached statements have been closed.- See Also:
-
statements
A pool of prepared statements with a maximal capacity equals to the array length. The array length should be reasonably small. The array may contain null element anywhere. Inactive statements are closed after some timeout.Note: this array duplicates the work done by statement pools in modern JDBC drivers. Nevertheless it still useful in our case since we retain some additional JDBC resources together with theEvery access to this array must be synchronized onPreparedStatement, for example theResultSetcreated from that statement.MetadataSource.this. Execution of a prepared statement may also need to be done inside the synchronized block, because a single JDBC connection cannot be assumed thread-safe.Usage example:
-
catalog
The catalog, ornullif none. -
schema
The database schema where metadata are stored, ornullif none. In the metadata source provided by SIS, this is"metadata"or"METADATA", depending on the database convention regarding lower case / upper case identifiers.Consider this field as final. This field is modified only by
install()for taking in account the lower case or upper case convention of the database engine. -
quoteSchema
private boolean quoteSchemaWhether thehelpershould quote schemas in SQL statements. A value offalselet the database engine chooses its own lower case / upper case policy. This flag istrueif the schema was specified by the user, orfalseif using the metadata provided by SIS.Consider this field as final. This field is modified only by
install().- See Also:
-
helper
A helper class used for constructing SQL statements. This helper is created when first needed, then kept until the connection is closed.- See Also:
-
tableColumns
All columns found in tables that have been queried or created up to date. Keys are table names and values are the columns defined for that table.- See Also:
-
classloader
The class loader to use for creatingProxyinstances.- See Also:
-
pool
The objects which have been created by a previous call tolookup(Class, String). Used in order to share existing instances for the same interface and primary key.- See Also:
-
lastUsed
Some information about last used objects. Cached on assumption that the same information will be used more than once before to move to another metadata object. -
logFilter
Where to report the warnings before to eventually log them. -
isCloseScheduled
private boolean isCloseScheduledWhether at least oneMetadataSource.CloseTaskis scheduled for execution.- See Also:
-
instance
The instance connected to the"jdbc/SpatialMetadata"database, created when first needed and cleared when the classpath change. May beMetadataFallback.INSTANCEif we failed to establish a connection to the database for a non-transient reason.
-
-
Constructor Details
-
MetadataSource
public MetadataSource(MetadataStandard standard, DataSource dataSource, String schema, Map<String, ?> properties) Creates a new metadata source. The metadata standard to implement (typically ISO 19115, but not necessarily) and the database source are mandatory information. All other information are optional and can benull.- Parameters:
standard- the metadata standard to implement.dataSource- the source for getting a connection to the database.schema- the database schema were metadata tables are stored, ornullif none.properties- additional options, ornullif none. See class javadoc for a description.
-
MetadataSource
Creates a new metadata source with the same configuration than the given source. The twoMetadataSourceinstances will share the sameDataSourcebut will use their ownConnection. This constructor is useful when concurrency is desired.The new
MetadataSourceinitially contains the warning filter declared in the givensource.- Parameters:
source- the source from which to copy the configuration.
-
MetadataSource
MetadataSource()ForMetadataFallbackconstructor only.
-
-
Method Details
-
getProvided
Returns the metadata source connected to the"jdbc/SpatialMetadata"database. In a default Apache SIS installation, this metadata source contains predefined records for some commonly used citations and formats among others.If connection to the metadata database cannot be established, then this method returns a fallback with a few hard-coded values.
- Returns:
- source of predefined metadata records from the
"jdbc/SpatialMetadata"database.
-
install
If the metadata schema does not exist in the database, creates it and inserts the predefined metadata values. The current implementation has the following restrictions:- Metadata standard must be
MetadataStandard.ISO_19115or compatible. - The schema name must be
"metadata", as this is the name used unquoted in SQL scripts.
non-free:sis-embedded-datamodule. If we make this method public in a future Apache SIS version, then we can remove the reflection code.- Throws:
SQLException- if an error occurred while inserting the metadata.IOException
- Metadata standard must be
-
connection
Returns the connection to the database, creating a new one if needed. This method shall be invoked inside a synchronized block wider than just the scope of this method in order to ensure that the connection is used by only one thread at time. This is also necessary for preventing the background thread to close the connection too early.Callers shall not close the connection returned by this method. The connection will be closed by
closeExpired()after an arbitrary timeout.- Returns:
- the connection to the database.
- Throws:
SQLException- if an error occurred while fetching the connection.
-
schema
Returns the database schema where metadata are stored, ornullif none. -
helper
Returns a helper class for building SQL statements.- Throws:
SQLException
-
prepareStatement
private CachedStatement prepareStatement(Class<?> type, String tableName, int preferredIndex) throws SQLException Returns a statement that can be reused for performing queries on the table for the specified interface. Callers must invoke this method in a block synchronized onthis.- Parameters:
type- the interface for which to reuse a prepared statement.tableName- value ofgetTableName(type), ornullfor computing by this method.preferredIndex- index in the cache array where to search first. This is only a hint for increasing the chances to find quickly aCachedStatementinstance for the right type and identifier.- Throws:
SQLException
-
recycle
Flags the givenCachedStatementas available for reuse.- Parameters:
statement- the prepared statement to cache.preferredIndex- index in the cache array to use if the corresponding slot is available.- Returns:
- index in the cache array where the result has been actually stored.
- Throws:
SQLException
-
getTableName
Returns the table name for the specified class. This is usually the ISO 19115 name, but we fallback on the simple class name if the ISO name is not available. The package prefix is omitted (e.g."CI_"in"CI_Citation"since newer ISO standards tend to drop it. -
proxy
If the given metadata is a proxy generated by thisMetadataSource, returns the identifier of that proxy. Such metadata do not need to be inserted again in the database.- Parameters:
metadata- the metadata to test.- Returns:
- the identifier (primary key), or
nullif the given metadata is not a proxy.
-
asValueMap
Returns a view of the given metadata as a map. This method returns always a map using UML identifier and containing all entries including the null ones because theMetadataSourceimplementation assumes so.- Parameters:
metadata- the metadata object to view as a map.- Returns:
- a map view over the metadata object.
- Throws:
ClassCastException- if the metadata object does not implement a metadata interface of the expected package.
-
extractFromCollection
If the given value is a collection, returns the first element in that collection ornullif empty.- Parameters:
value- the value to inspect (can benull).- Returns:
- the given value, or its first element if the value is a collection,
or
nullif the given value is null or an empty collection.
-
search
Searches for the given metadata in the database. If such metadata is found, then its identifier (primary key) is returned. Otherwise this method returnsnull.- Parameters:
metadata- the metadata to search for.- Returns:
- the identifier of the given metadata, or
nullif none. - Throws:
MetadataStoreException- if the metadata object does not implement a metadata interface of the expected package, or if an error occurred while searching in the database.
-
search
final String search(String table, Set<String> columns, Map<String, Object> metadata, Statement stmt, SQLBuilder helper) throws SQLException, org.opengis.util.FactoryExceptionSearches for the given metadata in the database. If such metadata is found, then its identifier (primary key) is returned. Otherwise this method returnsnull.- Parameters:
table- the table where to search.columns- the table columns as given bygetExistingColumns(String), ornull.metadata- a map view of the metadata to search for.stmt- the statement to use for executing the query.helper- an helper class for creating the SQL query.- Returns:
- the identifier of the given metadata, or
nullif none. - Throws:
SQLException- if an error occurred while searching in the database.org.opengis.util.FactoryException
-
toStorableValue
Converts the given object to a value that can be stored in the database.- Throws:
org.opengis.util.FactoryException- if an error occurred while using the geodetic database.
-
getExistingColumns
Returns the set of all columns in a table, or an empty set if none (nevernull). Because each table should have at least the "ID" column, an empty set of columns will be understood as meaning that the table does not exist.This method returns a direct reference to the cached set. The returned set shall be modified in-place if new columns are added in the database table.
- Parameters:
table- the name of the table for which to get the columns.- Returns:
- 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.
-
lookup
Returns an implementation of the specified metadata interface filled with the data referenced by the specified identifier. Alternatively, this method can also return aCodeListorEnumelement.- Type Parameters:
T- the parameterized type of thetypeargument.- Parameters:
type- the interface to implement (e.g.Citation), or theControlledVocabularytype (CodeListor someEnum).identifier- the identifier of the record for the metadata entity to be created. This is usually the primary key of the record to search for.- Returns:
- an implementation of the required interface, or the code list element.
- Throws:
MetadataStoreException- if a SQL query failed or if the metadata has not been found.
-
lookup
private Object lookup(Class<?> type, String identifier, boolean verify) throws MetadataStoreException Implementation of publiclookup(Class, String)method.Deferred database access
This method may or may not query the database immediately, at implementation choice. It the database is not queried immediately, invalid identifiers may not be detected during this method invocation. Instead, an invalid identifier may be detected only when a getter method is invoked on the returned metadata object. In such case, anBackingStoreExceptionwill be thrown at getter method invocation time.- Parameters:
type- the interface to implement or theControlledVocabularytype.identifier- the identifier of the record for the metadata entity to be created.verify- whether to check for record existence.- Returns:
- an implementation of the required interface, or the code list element.
- Throws:
MetadataStoreException- if a SQL query failed or if the metadata has not been found.
-
getLookupInfo
Gets theLookupInfoinstance for call to thereadColumn(LookupInfo, Method, Dispatcher)method. The call to those two methods must be in the same thread, and no other metadata object shall be queried between the two calls (unlessLookupInfo.setMetadataType(Class)is invoked again).- Parameters:
type- the interface class. This is mapped to the table name in the database.
-
readColumn
final Object readColumn(LookupInfo info, Method method, Dispatcher toSearch) throws SQLException, MetadataStoreException Invoked byMetadataProxyfor fetching an attribute value from a table. It the database table does not contains a column for the property, this method returnsnull. Anullvalue may also mean that the column exists but contains an SQLNULLvalue.- Parameters:
info- the interface type (together with cached information). This is mapped to the table name in the database.method- the method invoked. This is mapped to the column name in the database.toSearch- contains the identifier and preferred index of the record to search.- Returns:
- the value of the requested attribute, or
nullif none. - Throws:
SQLException- if the SQL query failed.MetadataStoreException- if a value was not found or cannot be converted to the expected type.
-
getCodeList
Returns the code of the given type and name. This method is defined for avoiding the compiler warning message when the actual class is unknown (it must have been checked dynamically by the caller however). -
specialize
private static <E> Collection<?> specialize(Collection<?> collection, Class<?> returnType, Class<E> elementType) Copies the given collection into the bestSetimplementation if possible, or returns the given collection unchanged otherwise.- Parameters:
collection- the collection to copy.returnType- the desired collection type.elementType- the type of elements in the collection.- Returns:
- the collection of a specialized type if relevant.
-
warning
Reports a warning.- Parameters:
source- the source class, eitherMetadataSourceorMetadataWriter.method- the method to report as the warning emitter.record- the warning to report.
-
setWarningFilter
Sets a filter to be notified when a warning occurred while reading from or writing metadata. When a warning occurs, there is a choice:- If this metadata source has no warning filter, or if the filter returns
true, then the warning is logged atLevel.WARNING. - Otherwise the warning is not logged by this metadata source instance. The filter implementation is free to keep a reference to the given record, for example in order to display it in a graphical user interface.
- Parameters:
filter- the filter to set, ornullfor removing the filter.- Returns:
- the previous filter, or
nullif none. - Since:
- 1.1
- If this metadata source has no warning filter, or if the filter returns
-
getWarningFilter
Returns the current warning filter.- Returns:
- the current filter, or
nullif none. - Since:
- 1.1
-
scheduleCloseTask
private void scheduleCloseTask()Schedules a task for closing the statements and the connection, if no such task is scheduled. -
closeExpired
final void closeExpired()Executed in a background thread for closing statements after their expiration time. This task will be given to the executor every time the first statement is recycled. -
closeQuietly
Closes the given resource without throwing exception. In case of failure while closing the resource, the message is logged but the process continue since we are not supposed to use the resource anymore. This method is invoked from methods that cannot throw a SQL exception. -
close
Closes the database connection used by this object.- Specified by:
closein interfaceAutoCloseable- Throws:
MetadataStoreException- if an error occurred while closing the connection.
-