Class MetadataWriter

java.lang.Object
org.apache.sis.metadata.sql.MetadataSource
org.apache.sis.metadata.sql.MetadataWriter
All Implemented Interfaces:
AutoCloseable

public class MetadataWriter extends MetadataSource
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 add(Object) method is invoked.

No more than one instance of MetadataWriter should be used for the same database. However, multiple instances of MetadataSource can be used concurrently with a single MetadataWriter instance on the same database.

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 by MetadataSource and all other entries are ignored:
Optional properties at construction time
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.
"maximumIdentifierLength" Integer The maximal number of characters allowed for primary keys. This is the value given to the VARCHAR type when creating new "ID" columns.
"maximumValueLength" Integer Maximal number of characters allowed in text columns. This is the parameter given to the VARCHAR type when creating new columns. Attempts to insert a text longer than this limit will typically throws a SQLException, but the exact behavior is database-dependent.
"columnCreationPolicy" ValueExistencePolicy Whether columns should be created only for non-empty attributes (NON_EMPTY, the default) or for all attributes (ALL)
Since:
0.8
Version:
1.1
  • Field Details

    • CODE_COLUMN

      private static final String CODE_COLUMN
      The name of the column for code list.
      See Also:
    • MINIMAL_LIMIT

      private static final int MINIMAL_LIMIT
      Minimum value allowed for maximumIdentifierLength.
      See Also:
    • maximumIdentifierLength

      private final int maximumIdentifierLength
      Maximal length for the identifier. This applies also to code list values.
    • maximumValueLength

      private final int maximumValueLength
      Maximal length of values.
    • columnCreationPolicy

      private final ValueExistencePolicy columnCreationPolicy
      Whether the tables should contain a column for every attribute, or only for non-null and non-empty attributes. The default is NON-EMPTY.
  • Constructor Details

    • MetadataWriter

      public MetadataWriter(MetadataStandard standard, DataSource dataSource, String schema, Map<String,?> properties)
      Creates a new metadata writer.
      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, or null if none.
      properties - additional options, or null if none. See class javadoc for a description.
  • Method Details

    • add

      public String add(Object metadata) throws MetadataStoreException
      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.
      Parameters:
      metadata - the metadata object to add.
      Returns:
      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 all or nothing operation).
    • add

      private String add(Statement stmt, Object metadata, Map<Object,String> done, String parent) throws ClassCastException, SQLException, org.opengis.util.FactoryException
      Implementation of the add(Object) method. This method invokes itself recursively, and maintains a map of metadata inserted up to date in order to avoid infinite recursivity.
      Parameters:
      stmt - the statement to use for inserting data.
      metadata - the metadata object to add.
      done - the metadata objects already added, mapped to their primary keys.
      parent - the primary key of the parent, or null if there is no parent. This identifier shall not contain reserved characters.
      Returns:
      the identifier (primary key) of the metadata just added.
      Throws:
      SQLException - if an exception occurred while reading or writing the database.
      ClassCastException - if the metadata object does not implement a metadata interface of the expected package.
      org.opengis.util.FactoryException
    • getParentTypes

      private static Class<?>[] getParentTypes(Class<?> type)
      Returns the parent of the given type. Normally, type is an interface, in which case the parent types are other interfaces that the given type extends. But in some cases (e.g. when Apache SIS implements a new ISO 19115 type not yet defined in GeoAPI), the given type is a class. In such cases we ignore its interface (it usually do not implement any) and look for its parent class.
    • isChildTable

      private Boolean isChildTable(Class<?> type)
      Returns true if the given metadata type is a subtype of another metadata. If true, then we will need to prefix the identifier by the metadata subtype.
      Returns:
      whether the given metadata is a subtype of another metadata. This method never return null, but the result is nevertheless given as a Boolean wrapper for consistency with createTable(…).
    • createTable

      private Boolean createTable(Statement stmt, Class<?> type, String table, Set<String> columns) throws SQLException
      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. This method opportunistically computes the same return value than isChildTable(Class).
      Parameters:
      stmt - the statement to use for creating tables.
      type - the interface class.
      table - the name of the table (should be consistent with the type).
      columns - the existing columns, as an empty set if the table does not exist yet.
      Returns:
      the value that isChildTable(type) would return, or null if undetermined.
      Throws:
      SQLException - if an error occurred while creating the table.
    • createTable

      private String createTable(String table, String primaryKey) throws SQLException
      Returns the SQL statement for creating the given table with the given primary key. This method returns a string of the following form:
      Throws:
      SQLException
    • addCode

      private String addCode(Statement stmt, org.opengis.util.CodeList<?> code) throws SQLException
      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.
      Throws:
      SQLException
    • suggestIdentifier

      protected String suggestIdentifier(Object metadata, Map<String,Object> asValueMap) throws SQLException
      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 for a few "well known" metadata like Identifier and Citation. Subclasses can override this method for implementing their own heuristic.

      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.

      Parameters:
      metadata - the metadata instance for which to suggests an identifier.
      asValueMap - a view of all metadata properties as a map. Keys are UML identifiers.
      Returns:
      the proposed identifier, or null if this method does not have any suggestion.
      Throws:
      SQLException - if an access to the database was desired but failed.
    • abbreviation

      private static String abbreviation(String identifier)
      Returns an abbreviation of the given identifier, if one is found. The returned identifier is guaranteed to not contain reserved characters.
    • removeReservedChars

      private static String removeReservedChars(String identifier, StringBuilder buffer)
      Removes the reserved characters in the given identifier. If the given buffer is non-null, then it shall contain a copy of identifier.
    • isReservedChar

      private static boolean isReservedChar(int c)
      Returns true if the given code point is a reserved character.