Class FeatureAdapter

java.lang.Object
org.apache.sis.internal.sql.feature.FeatureAdapter

final class FeatureAdapter extends Object
Converter of ResultSet rows to Feature instances. Each FeatureAdapter instance is specific to the set of rows given by a SQL query, ignoring DISTINCT, ORDER BY and filter conditions in the WHERE clause. This class does not hold JDBC resources; ResultSet must be provided by the caller. This object can be prepared once and reused every time the query needs to be executed.

Multi-threading

This class is immutable (except for the cache) and safe for concurrent use by many threads. The content of arrays in this class shall not be modified in order to preserve immutability.
Since:
1.1
Version:
1.2
  • Field Details

    • EMPTY

      private static final FeatureAdapter[] EMPTY
      An empty array of adapters, used when there is no dependency.
    • featureType

      private final DefaultFeatureType featureType
      The type of features to create.
      See Also:
    • attributes

      private final Column[] attributes
      Attributes in feature instances, excluding operations and associations to other tables. Elements are in the order of columns declared in the SELECT <columns> statement. This array is a shared instance and shall not be modified.
      See Also:
    • associationNames

      final String[] associationNames
      Name of the properties where are stored associations in feature instances. The length of this array shall be equal to the dependencies array length. Imported or exported features read by dependencies[i] will be stored in the association named associationNames[i].
    • deferredAssociation

      final String deferredAssociation
      Name of the property where to store the association that we cannot handle with other dependencies. This deferred association may exist because of circular dependency.
    • dependencies

      final FeatureAdapter[] dependencies
      The feature sets referenced through foreigner keys, or EMPTY if none. This includes the associations inferred from both the imported and exported keys. The first importCount iterators are for imported keys, and the remaining iterators are for the exported keys.
    • importCount

      final int importCount
      Number of entries in dependencies for Relation.Direction.IMPORT. The entries immediately following the first importCount entries are for Relation.Direction.EXPORT.
    • foreignerKeyIndices

      private final int[][] foreignerKeyIndices
      One-based indices of the columns to query for each dependencies entry.
    • instances

      final WeakValueHashMap<?,Object> instances
      Feature instances already created, or null if the features created by this iterator are not cached. This map is used when requesting a feature by identifier, not when iterating over all features (note: we could perform an opportunistic check in a future SIS version). The same map may be shared by all iterators on the same Table, but WeakValueHashMap already provides the required synchronizations.

      The FeatureIterator class does not require the identifiers to be built from primary key columns. However if this map has been provided by Table.instanceForPrimaryKeys(), then the identifiers need to be primary keys with columns in the exact same order for allowing the same map to be shared.

    • keyComponentClass

      private final Class<?> keyComponentClass
      The component class of the keys in the instances map, or null if the keys are not array. For example if a primary key is made of two columns of type String, then this field may be set to String.
    • sql

      final String sql
      The SQL statement to execute for creating features, without DISTINCT or ORDER BY clauses. May contain a WHERE clause for fetching a dependency, but not for user-specified filtering.
  • Constructor Details

  • Method Details

    • appendColumn

      private static int appendColumn(SQLBuilder sql, String column, Map<String,Integer> columnIndices) throws InternalDataStoreException
      Appends a columns in the given builder and remember the column indices. An exception is thrown if the column has already been added (should never happen).
      Parameters:
      sql - the SQL statement where to add column identifiers after the SELECT clause.
      column - name of the column to add.
      columnIndices - map where to add the mapping from column name to 1-based column index.
      Throws:
      InternalDataStoreException
    • getColumnIndices

      private static int[] getColumnIndices(SQLBuilder sql, Relation dependency, Map<String,Integer> columnIndices) throws InternalDataStoreException
      Computes the 1-based indices of columns of foreigner keys of given dependency. This method also ensure that the SQL statement contains all required columns, adding missing columns in the given SQL builder if necessary.
      Parameters:
      sql - the SQL statement to complete if there is missing columns.
      dependency - the dependency for which to get column indices of foreigner keys.
      columnIndices - the map containing existing column indices, or where to add missing column indices.
      Returns:
      indices of columns of foreigner keys of given dependency. Numbering starts at 1.
      Throws:
      InternalDataStoreException
    • createFeature

      final AbstractFeature createFeature(InfoStatements stmts, ResultSet result) throws Exception
      Creates a feature with attribute values initialized to values fetched from the given result set. This method does not follow associations.
      Parameters:
      stmts - prepared statements for fetching CRS from SRID, or null if none.
      result - the result set from which to get attribute values.
      Returns:
      the feature with attribute values initialized.
      Throws:
      Exception - if an error occurred while reading the database or converting values.
    • getCacheKey

      final Object getCacheKey(ResultSet result, int dependency) throws SQLException
      Returns the key to use for caching the feature of a dependency. If the foreigner key uses only one column, we will use the foreigner key value without creating array. But if the foreigner key uses more than one column, then we need to create an array holding all values.
      Parameters:
      result - the result set over rows expected by this feature adapter.
      dependency - index of the dependency for which to create a cache key.
      Returns:
      key to use for accesses in the instances map, or null if any component of the key is null.
      Throws:
      SQLException
    • setForeignerKeys

      final void setForeignerKeys(ResultSet source, PreparedStatement target, int dependency) throws SQLException
      Sets the statement parameters for searching a dependency.
      Parameters:
      result - the result set over rows expected by this feature adapter.
      target - the statement on which to set parameters.
      dependency - index of the dependency for which to set the parameters.
      Throws:
      SQLException