Package org.openmhealth.reference.data.sql

Source Code of org.openmhealth.reference.data.sql.SqlRegistry

package org.openmhealth.reference.data.sql;

import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;

import org.mongojack.internal.MongoJackModule;
import org.openmhealth.reference.concordia.OmhValidationController;
import org.openmhealth.reference.data.Registry;
import org.openmhealth.reference.domain.MultiValueResult;
import org.openmhealth.reference.domain.Schema;
import org.openmhealth.reference.domain.sql.SqlMultiValueResult;
import org.openmhealth.reference.exception.OmhException;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SingleColumnRowMapper;

import com.fasterxml.jackson.databind.InjectableValues;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
* <p>
* The SQL implementation of the interface to the database-backed collection of
* the {@link Registry}.
* </p>
*
* @author John Jenkins
*/
public class SqlRegistry
  extends Registry
  implements SqlDaoInterface {
 
  /**
   * The object mapper that should be used to parse {@link Schema}s.
   */
  private static final ObjectMapper JSON_MAPPER;
  static {
    // Create the object mapper.
    ObjectMapper mapper = new ObjectMapper();
   
    // Add our custom validation controller as an injectable parameter to
    // the Schema's constructor.
    InjectableValues.Std injectableValues = new InjectableValues.Std();
    injectableValues
      .addValue(
        Schema.JSON_KEY_VALIDATION_CONTROLLER,
        OmhValidationController.VALIDATION_CONTROLLER);
    mapper.setInjectableValues(injectableValues);
   
    // Finally, we must configure the mapper to work with the MongoJack
    // configuration.
    JSON_MAPPER = MongoJackModule.configure(mapper);
  }
 
  /*
   * (non-Javadoc)
   * @see org.openmhealth.reference.data.Registry#getSchemaIds()
   */
  @Override
  public MultiValueResult<String> getSchemaIds(
    final long numToSkip,
    final long numToReturn) {
   
    // Retrieve the list of results.
    List<String> list;
    try {
      list =
        SqlDao
          .getInstance()
          .getJdbcTemplate()
          .query(
            "SELECT DISTINCT(" + Schema.JSON_KEY_ID + ") " +
              "FROM " + Registry.DB_NAME + " " +
              "ORDER BY " +
                Schema.JSON_KEY_ID + ", " +
                Schema.JSON_KEY_VERSION + " " +
              "LIMIT ?, ?",
            new Object[] { numToSkip, numToReturn },
            new SingleColumnRowMapper<String>());
    }
    // For all issues, we simply propagate the exception.
    catch(DataAccessException e) {
      throw
        new OmhException(
          "There was an error querying for the schema IDs.",
          e);
    }
   
    // Retrieve the total count of results.
    int count;
    try {
      count =
        SqlDao
          .getInstance()
          .getJdbcTemplate()
          .queryForInt(
            "SELECT COUNT(" + SqlDao.KEY_DATABASE_ID + ") " +
              "FROM " + Registry.DB_NAME);
    }
    // If the problem is that the number of results isn't what we expected,
    // we may still be alright.
    catch(IncorrectResultSizeDataAccessException e) {     
      // Otherwise, we throw an exception.
      throw
        new OmhException(
          "A count query returned more than one result.",
          e);
    }
    // For all other issues, we simply propagate the exception.
    catch(DataAccessException e) {
      throw
        new OmhException(
          "There was an error querying for the schema IDs count.",
          e);
    }
   
    // Return the result
    return new SqlMultiValueResult<String>(list, count);
  }
 
  /*
   * (non-Javadoc)
   * @see org.openmhealth.reference.data.Registry#getSchemaIds()
   */
  @Override
  public MultiValueResult<Long> getSchemaVersions(
    final String schemaId,
    final long numToSkip,
    final long numToReturn) {
   
    // Validate the schema ID.
    if(schemaId == null) {
      throw new OmhException("The schema ID is null.");
    }
   
    // Retrieve the list of results.
    List<Long> list;
    try {
      list =
        SqlDao
          .getInstance()
          .getJdbcTemplate()
          .query(
            "SELECT DISTINCT(" + Schema.JSON_KEY_VERSION + ") " +
              "FROM " + Registry.DB_NAME + " " +
              "WHERE " + Schema.JSON_KEY_ID + " = ? " +
              "ORDER BY " + Schema.JSON_KEY_VERSION + " " +
              "LIMIT ?, ?",
            new Object[] { schemaId, numToSkip, numToReturn },
            new SingleColumnRowMapper<Long>());
    }
    // For all issues, we simply propagate the exception.
    catch(DataAccessException e) {
      throw
        new OmhException(
          "There was an error querying for the schema versions.",
          e);
    }
   
    // Retrieve the total count of results.
    int count;
    try {
      count =
        SqlDao
          .getInstance()
          .getJdbcTemplate()
          .queryForInt(
            "SELECT COUNT(" + SqlDao.KEY_DATABASE_ID + ") " +
              "FROM " + Registry.DB_NAME + " " +
              "WHERE " + Schema.JSON_KEY_ID + " = ?",
            new Object[] { schemaId });
    }
    // For all issues, we simply propagate the exception.
    catch(DataAccessException e) {
      throw
        new OmhException(
          "There was an error querying for schema versions count.",
          e);
    }
   
    return new SqlMultiValueResult<Long>(list, count);
  }
 
  /*
   * (non-Javadoc)
   * @see org.openmhealth.reference.data.Registry#getSchema(java.lang.String, long)
   */
  public Schema getSchema(final String schemaId, final long schemaVersion) {
    if(schemaId == null) {
      throw new OmhException("The schema ID is null.");
    }
   
    try {
      return
        SqlDao
          .getInstance()
          .getJdbcTemplate()
          .queryForObject(
            "SELECT " +
                Schema.JSON_KEY_ID + ", " +
                Schema.JSON_KEY_VERSION + ", " +
                "`" + Schema.JSON_KEY_SCHEMA + "` " +
              "FROM " +
                Registry.DB_NAME + " " +
              "WHERE " + Schema.JSON_KEY_ID + " = ? " +
              "AND " + Schema.JSON_KEY_VERSION + " = ?",
            new Object[] { schemaId, schemaVersion },
            new RowMapper<Schema>() {
              /**
               * Maps the row to an {@link Schema} object.
               */
              @Override
              public Schema mapRow(
                final ResultSet resultSet,
                final int rowNum)
                throws SQLException {
               
                String id =
                  resultSet.getString(Schema.JSON_KEY_ID);
                long version =
                  resultSet.getLong(Schema.JSON_KEY_VERSION);
                JsonNode schema;
                try {
                  schema = JSON_MAPPER.
                    readTree(
                      resultSet
                        .getString(
                          Schema.JSON_KEY_SCHEMA));
                }
                catch(IOException e) {
                  throw
                    new SQLException(
                      "Error reading the schema.",
                      e);
                }
               
                return
                  new Schema(
                    id,
                    version,
                    schema,
                    OmhValidationController
                      .VALIDATION_CONTROLLER);
              }
            });
    }
    // If the problem is that the number of results isn't what we expected,
    // we may still be alright.
    catch(IncorrectResultSizeDataAccessException e) {
      // If there weren't any tokens with the given token value, then we
      // simply return null.
      if(e.getActualSize() == 0) {
        return null;
      }
     
      // Otherwise, we throw an exception.
      throw
        new OmhException(
          "Multiple schemas have the same ID-version pair: " +
            schemaId + ", " +
            schemaVersion,
          e);
    }
    // For all other issues, we simply propagate the exception.
    catch(DataAccessException e) {
      throw
        new OmhException(
          "There was an error querying for a schema.",
          e);
    }
  }

  /*
   * (non-Javadoc)
   * @see org.openmhealth.reference.data.Registry#getSchemas(java.lang.String, java.lang.Long, long, long)
   */
  @Override
  public MultiValueResult<? extends Schema> getSchemas(
    final String schemaId,
    final Long schemaVersion,
    final long numToSkip,
    final long numToReturn) {
   
    // The SELECT portion of the SQL that is querying for the data.
    String querySelect =
      "SELECT " +
        Schema.JSON_KEY_ID + ", " +
        Schema.JSON_KEY_VERSION + ", " +
        "`" + Schema.JSON_KEY_SCHEMA + "` ";
   
    // The FROM portion used by both the data query and the count query.
    String sqlFrom =
      "FROM " +
        Registry.DB_NAME + " ";
   
    // Create the base SQL for the query for data.
    StringBuilder queryBuilder = new StringBuilder(querySelect);
    queryBuilder.append(sqlFrom);
   
    // Create the parameters list for the data query and the count query.
    List<Object> sqlParameters = new LinkedList<Object>();
   
    // Gather the WHERE clauses.
    List<String> whereClauses = new LinkedList<String>();
   
    // Add the schema ID, if given.
    if(schemaId != null) {
      whereClauses.add(Schema.JSON_KEY_ID + " = ?");
      sqlParameters.add(schemaId);
    }
   
    // Add the schema version, if given.
    if(schemaVersion != null) {
      whereClauses.add(Schema.JSON_KEY_VERSION + " = ?");
      sqlParameters.add(schemaVersion);
    }
   
    // Build the WHERE string.
    boolean firstPass = true;
    StringBuilder sqlWhereBuilder = null;
    for(String whereClause : whereClauses) {
      if(firstPass) {
        firstPass = false;
        sqlWhereBuilder = new StringBuilder("WHERE ");
      }
      else {
        sqlWhereBuilder.append("AND ");
      }
     
      sqlWhereBuilder.append(whereClause).append(" ");
    }
    String sqlWhere = null;
    if(sqlWhereBuilder != null) {
      sqlWhere = sqlWhereBuilder.toString();
    }
   
    // Add the WHERE clause to the query for data if it is not null.
    if(sqlWhere != null) {
      queryBuilder.append(sqlWhere);
    }
   
    // Add the ordering and paging.
    queryBuilder
      .append(
        "ORDER BY " +
          Schema.JSON_KEY_ID + ", " +
          Schema.JSON_KEY_VERSION + " " +
        "LIMIT ?, ?");
   
    // Create the data-query parameter list from the SQL parameters with
    // the additional paging parameters.
    List<Object> queryParameters = new LinkedList<Object>(sqlParameters);
    queryParameters.add(numToSkip);
    queryParameters.add(numToReturn);
   
    // Retrieve the list of results.
    List<Schema> list;
    try {
      list =
        SqlDao
          .getInstance()
          .getJdbcTemplate()
          .query(
            queryBuilder.toString(),
            queryParameters.toArray(),
            new RowMapper<Schema>() {
              /**
               * Maps the row to an {@link Schema} object.
               */
              @Override
              public Schema mapRow(
                final ResultSet resultSet,
                final int rowNum)
                throws SQLException {
               
                String id =
                  resultSet.getString(Schema.JSON_KEY_ID);
                long version =
                  resultSet.getLong(Schema.JSON_KEY_VERSION);
                JsonNode schema;
                try {
                  schema =
                    JSON_MAPPER.
                      readTree(
                        resultSet
                          .getString(
                            Schema
                              .JSON_KEY_SCHEMA));
                }
                catch(IOException e) {
                  throw
                    new SQLException(
                      "Error reading the schema.",
                      e);
                }
               
                return
                  new Schema(
                    id,
                    version,
                    schema,
                    OmhValidationController
                      .VALIDATION_CONTROLLER);
              }
            });
    }
    // For all issues, we simply propagate the exception.
    catch(DataAccessException e) {
      throw
        new OmhException(
          "There was an error querying for schemas.",
          e);
    }
   
    // Create the SELECT portion of the count query.
    StringBuilder countBuilder =
      new StringBuilder("SELECT COUNT(1) ");
   
    // Add the shared FROM clause.
    countBuilder.append(sqlFrom);
   
    // Add the WHERE clause if it is not null.
    if(sqlWhere != null) {
      countBuilder.append(sqlWhere);
    }
   
    // Retrieve the total count of results.
    int count;
    try {
      count =
        SqlDao
          .getInstance()
          .getJdbcTemplate()
          .queryForInt(
            countBuilder.toString(),
            sqlParameters.toArray());
    }
    // For all issues, we simply propagate the exception.
    catch(DataAccessException e) {
      throw
        new OmhException(
          "There was an error querying for schemas count.",
          e);
    }
   
    return new SqlMultiValueResult<Schema>(list, count);
  }
 
  /*
   * (non-Javadoc)
   * @see org.openmhealth.reference.data.sql.SqlDaoInterface#getSqlTableDefinition()
   */
  @Override
  public String getSqlTableDefinition() {
    return
      // Create the table if it does not exist.
      "CREATE TABLE IF NOT EXISTS " +
        Registry.DB_NAME + "(" +
          // Add the database ID.
          SqlDao.KEY_DATABASE_ID +
            " int unsigned NOT NULL auto_increment, " +
          // Add the schema ID.
          Schema.JSON_KEY_ID + " varchar(36) NOT NULL, " +
          // Add the schema version.
          Schema.JSON_KEY_VERSION + " bigint NOT NULL, " +
          // Add the schema.
          "`" + Schema.JSON_KEY_SCHEMA + "` text NOT NULL, " +
          // Create the primary key.
          "PRIMARY KEY (" + SqlDao.KEY_DATABASE_ID + "), " +
          // Create a unique index on the ID-version pair.
          "UNIQUE INDEX " +
            "`" +
              Registry.DB_NAME +
                "_unique_index_" +
                Schema.JSON_KEY_ID +
                "_" +
                Schema.JSON_KEY_VERSION +
            "` " +
            "(" +
              Schema.JSON_KEY_ID +
                ", " +
                Schema.JSON_KEY_VERSION +
            ") " +
        ")";
  }
}
TOP

Related Classes of org.openmhealth.reference.data.sql.SqlRegistry

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.