Package com.opengamma.masterdb.config

Source Code of com.opengamma.masterdb.config.DbConfigWorker

/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.masterdb.config;

import java.io.ByteArrayInputStream;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;

import org.fudgemsg.FudgeContext;
import org.fudgemsg.FudgeMsg;
import org.fudgemsg.MutableFudgeMsg;
import org.fudgemsg.mapping.FudgeDeserializer;
import org.fudgemsg.mapping.FudgeObjectReader;
import org.fudgemsg.mapping.FudgeSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.core.support.SqlLobValue;
import org.springframework.jdbc.support.lob.LobHandler;

import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import com.opengamma.core.config.impl.ConfigItem;
import com.opengamma.elsql.ElSqlBundle;
import com.opengamma.id.IdUtils;
import com.opengamma.id.MutableUniqueIdentifiable;
import com.opengamma.id.ObjectId;
import com.opengamma.id.ObjectIdentifiable;
import com.opengamma.id.UniqueId;
import com.opengamma.id.VersionCorrection;
import com.opengamma.master.AbstractHistoryRequest;
import com.opengamma.master.AbstractHistoryResult;
import com.opengamma.master.config.ConfigDocument;
import com.opengamma.master.config.ConfigHistoryRequest;
import com.opengamma.master.config.ConfigHistoryResult;
import com.opengamma.master.config.ConfigMetaDataRequest;
import com.opengamma.master.config.ConfigMetaDataResult;
import com.opengamma.master.config.ConfigSearchRequest;
import com.opengamma.master.config.ConfigSearchResult;
import com.opengamma.master.config.ConfigSearchSortOrder;
import com.opengamma.masterdb.AbstractDocumentDbMaster;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.ClassUtils;
import com.opengamma.util.db.DbConnector;
import com.opengamma.util.db.DbDateUtils;
import com.opengamma.util.db.DbMapSqlParameterSource;
import com.opengamma.util.fudgemsg.OpenGammaFudgeContext;
import com.opengamma.util.paging.Paging;
import com.opengamma.util.paging.PagingRequest;

/**
*
*/
/*package*/class DbConfigWorker extends AbstractDocumentDbMaster<ConfigDocument> {

  /** Logger. */
  private static final Logger s_logger = LoggerFactory.getLogger(DbConfigWorker.class);

  /**
   * The Fudge context.
   */
  protected static final FudgeContext s_fudgeContext = OpenGammaFudgeContext.getInstance();

  // -----------------------------------------------------------------
  // TIMERS FOR METRICS GATHERING
  // By default these do nothing. Registration will replace them
  // so that they actually do something.
  // -----------------------------------------------------------------
  private Timer _searchTimer = new Timer();
  private Timer _metaDataTimer = new Timer();
  private Timer _insertTimer = new Timer();

  /**
   * SQL order by.
   */
  protected static final EnumMap<ConfigSearchSortOrder, String> ORDER_BY_MAP = new EnumMap<ConfigSearchSortOrder, String>(ConfigSearchSortOrder.class);
  static {
    ORDER_BY_MAP.put(ConfigSearchSortOrder.OBJECT_ID_ASC, "oid ASC");
    ORDER_BY_MAP.put(ConfigSearchSortOrder.OBJECT_ID_DESC, "oid DESC");
    ORDER_BY_MAP.put(ConfigSearchSortOrder.VERSION_FROM_INSTANT_ASC, "ver_from_instant ASC");
    ORDER_BY_MAP.put(ConfigSearchSortOrder.VERSION_FROM_INSTANT_DESC, "ver_from_instant DESC");
    ORDER_BY_MAP.put(ConfigSearchSortOrder.NAME_ASC, "name ASC");
    ORDER_BY_MAP.put(ConfigSearchSortOrder.NAME_DESC, "name DESC");
  }

  /**
   * Creates an instance.
   *
   * @param dbConnector the database connector, not null
   * @param defaultScheme the default scheme, not null
   */
  public DbConfigWorker(DbConnector dbConnector, String defaultScheme) {
    super(dbConnector, defaultScheme);
    setElSqlBundle(ElSqlBundle.of(dbConnector.getDialect().getElSqlConfig(), DbConfigMaster.class));
  }

  @Override
  public void registerMetrics(MetricRegistry summaryRegistry, MetricRegistry detailedRegistry, String namePrefix) {
    super.registerMetrics(summaryRegistry, detailedRegistry, namePrefix);
    _insertTimer = summaryRegistry.timer(namePrefix + ".insert");
    _metaDataTimer = summaryRegistry.timer(namePrefix + ".metaData");
    _searchTimer = summaryRegistry.timer(namePrefix + ".search");
  }

  //-------------------------------------------------------------------------
  @Override
  public ConfigDocument get(UniqueId uniqueId) {
    return doGet(uniqueId, new ConfigDocumentExtractor(), "Config");
  }

  @Override
  public ConfigDocument get(ObjectIdentifiable objectId, VersionCorrection versionCorrection) {
    return doGetByOidInstants(objectId, versionCorrection, new ConfigDocumentExtractor(), "Config");
  }

  @Override
  protected void mergeNonUpdatedFields(ConfigDocument newDocument, ConfigDocument oldDocument) {
    if (newDocument.getConfig() == null) {
      ConfigDocument hackGenerics = newDocument;
      hackGenerics.setConfig(oldDocument.getConfig());
    }
  }

  @Override
  protected ConfigDocument insert(ConfigDocument document) {
    ArgumentChecker.notNull(document.getName(), "document.name");
    ArgumentChecker.notNull(document.getConfig(), "document.value");
    ArgumentChecker.notNull(document.getType(), "document.type");
   
    Timer.Context context = _insertTimer.time();
    try {
      final Object value = document.getConfig().getValue();
      final long docId = nextId("cfg_config_seq");
      final long docOid = (document.getUniqueId() != null ? extractOid(document.getUniqueId()) : docId);
      // set the uniqueId
      final UniqueId uniqueId = createUniqueId(docOid, docId);
      document.setUniqueId(uniqueId);
      if (value instanceof MutableUniqueIdentifiable) {
        ((MutableUniqueIdentifiable) value).setUniqueId(uniqueId);
      }

      byte[] bytes = serializeToFudge(value);

      // the arguments for inserting into the config table
      final DbMapSqlParameterSource docArgs = new DbMapSqlParameterSource()
          .addValue("doc_id", docId)
          .addValue("doc_oid", docOid)
          .addTimestamp("ver_from_instant", document.getVersionFromInstant())
          .addTimestampNullFuture("ver_to_instant", document.getVersionToInstant())
          .addTimestamp("corr_from_instant", document.getCorrectionFromInstant())
          .addTimestampNullFuture("corr_to_instant", document.getCorrectionToInstant())
          .addValue("name", document.getName())
          .addValue("config_type", document.getType().getName())
          .addValue("config", new SqlLobValue(bytes, getDialect().getLobHandler()), Types.BLOB);
      final String sqlDoc = getElSqlBundle().getSql("Insert", docArgs);
      getJdbcTemplate().update(sqlDoc, docArgs);
      return document;
    } finally {
      context.stop();
    }
  }

  private byte[] serializeToFudge(final Object configObj) {
    // serialize the configuration value
    FudgeSerializer serializer = new FudgeSerializer(s_fudgeContext);
    MutableFudgeMsg objectToFudgeMsg = serializer.objectToFudgeMsg(configObj);
    return s_fudgeContext.toByteArray(objectToFudgeMsg);
  }

  //-------------------------------------------------------------------------
  public ConfigMetaDataResult metaData(ConfigMetaDataRequest request) {
    ArgumentChecker.notNull(request, "request");
   
    Timer.Context context = _metaDataTimer.time();
    try {
      ConfigMetaDataResult result = new ConfigMetaDataResult();
      if (request.isConfigTypes()) {
        final String sql = getElSqlBundle().getSql("SelectTypes");
        List<String> configTypes = getJdbcTemplate().getJdbcOperations().queryForList(sql, String.class);
        for (String configType : configTypes) {
          try {
            result.getConfigTypes().add(ClassUtils.loadClass(configType));
          } catch (ClassNotFoundException ex) {
            s_logger.warn("Unable to load class", ex);
          }
        }
      }
      return result;
    } finally {
      context.stop();
    }
  }

  //-------------------------------------------------------------------------
  public <T> ConfigSearchResult<T> search(ConfigSearchRequest<T> request) {
    ArgumentChecker.notNull(request, "request");
    ArgumentChecker.notNull(request.getType(), "request.type");
    ArgumentChecker.notNull(request.getPagingRequest(), "request.pagingRequest");
    ArgumentChecker.notNull(request.getVersionCorrection(), "request.versionCorrection");
    s_logger.debug("search {}", request);
   
    Timer.Context context = _searchTimer.time();
    try {
      final VersionCorrection vc = request.getVersionCorrection().withLatestFixed(now());
      final ConfigSearchResult<T> result = new ConfigSearchResult<T>(vc);

      final List<ObjectId> objectIds = request.getConfigIds();
      if (objectIds != null && objectIds.size() == 0) {
        result.setPaging(Paging.of(request.getPagingRequest(), 0));
        return result;
      }

      final DbMapSqlParameterSource args = new DbMapSqlParameterSource()
          .addTimestamp("version_as_of_instant", vc.getVersionAsOf())
          .addTimestamp("corrected_to_instant", vc.getCorrectedTo())
          .addValueNullIgnored("name", getDialect().sqlWildcardAdjustValue(request.getName()));

      if (!request.getType().isInstance(Object.class)) {
        args.addValue("config_type", request.getType().getName());
      }
      if (objectIds != null) {
        StringBuilder buf = new StringBuilder(objectIds.size() * 10);
        for (ObjectId objectId : objectIds) {
          checkScheme(objectId);
          buf.append(extractOid(objectId)).append(", ");
        }
        buf.setLength(buf.length() - 2);
        args.addValue("sql_search_object_ids", buf.toString());
      }
      args.addValue("sort_order", ORDER_BY_MAP.get(request.getSortOrder()));
      args.addValue("paging_offset", request.getPagingRequest().getFirstItem());
      args.addValue("paging_fetch", request.getPagingRequest().getPagingSize());

      String[] sql = {getElSqlBundle().getSql("Search", args), getElSqlBundle().getSql("SearchCount", args) };

      final NamedParameterJdbcOperations namedJdbc = getDbConnector().getJdbcTemplate();
      ConfigDocumentExtractor configDocumentExtractor = new ConfigDocumentExtractor();
      if (request.equals(PagingRequest.ALL)) {
        List<ConfigDocument> queryResult = namedJdbc.query(sql[0], args, configDocumentExtractor);
        for (ConfigDocument configDocument : queryResult) {
          if (request.getType().isInstance(configDocument.getConfig().getValue())) {
            result.getDocuments().add(configDocument);
          }
        }
        result.setPaging(Paging.of(request.getPagingRequest(), result.getDocuments()));
      } else {
        final int count = namedJdbc.queryForObject(sql[1], args, Integer.class);
        result.setPaging(Paging.of(request.getPagingRequest(), count));
        if (count > 0 && request.getPagingRequest().equals(PagingRequest.NONE) == false) {
          List<ConfigDocument> queryResult = namedJdbc.query(sql[0], args, configDocumentExtractor);
          for (ConfigDocument configDocument : queryResult) {
            if (request.getType().isInstance(configDocument.getConfig().getValue())) {
              result.getDocuments().add(configDocument);
            }
          }
        }
      }
      return result;
    } finally {
      context.stop();
    }
  }

  //-------------------------------------------------------------------------
  public <T> ConfigHistoryResult<T> history(ConfigHistoryRequest<T> request) {
    ArgumentChecker.notNull(request, "request");
    //ArgumentChecker.notNull(request.getType(), "request.type");
    ArgumentChecker.notNull(request.getObjectId(), "request.objectId");
    checkScheme(request.getObjectId());
    s_logger.debug("history {}", request);

    ConfigHistoryResult<T> result = new ConfigHistoryResult<T>();
    ConfigDocumentExtractor extractor = new ConfigDocumentExtractor();
    final DbMapSqlParameterSource args = argsHistory(request);
    final String[] sql = {getElSqlBundle().getSql("History", args), getElSqlBundle().getSql("HistoryCount", args) };

    final NamedParameterJdbcOperations namedJdbc = getDbConnector().getJdbcTemplate();
    if (request.getPagingRequest().equals(PagingRequest.ALL)) {
      List<ConfigDocument> queryResult = namedJdbc.query(sql[0], args, extractor);
      for (ConfigDocument configDocument : queryResult) {
        if (request.getType() == null || request.getType().isInstance(configDocument.getConfig().getValue())) {
          result.getDocuments().add(configDocument);
        }
      }
      result.setPaging(Paging.of(request.getPagingRequest(), result.getDocuments()));
    } else {
      final int count = namedJdbc.queryForObject(sql[1], args, Integer.class);
      result.setPaging(Paging.of(request.getPagingRequest(), count));
      if (count > 0 && request.getPagingRequest().equals(PagingRequest.NONE) == false) {
        List<ConfigDocument> queryResult = namedJdbc.query(sql[0], args, extractor);
        for (ConfigDocument configDocument : queryResult) {
          if (request.getType() == null || request.getType().isInstance(configDocument.getConfig().getValue())) {
            result.getDocuments().add(configDocument);
          }
        }
      }
    }
    return result;
  }

  //-------------------------------------------------------------------------
  /**
   * Mapper from SQL rows to a ConfigDocument.
   */
  private final class ConfigDocumentExtractor implements ResultSetExtractor<List<ConfigDocument>> {

    private long _lastDocId = -1;
    private List<ConfigDocument> _documents = new ArrayList<ConfigDocument>();

    @Override
    public List<ConfigDocument> extractData(ResultSet rs) throws SQLException, DataAccessException {
      while (rs.next()) {
        final long docId = rs.getLong("DOC_ID");
        if (_lastDocId != docId) {
          _lastDocId = docId;
          buildConfig(rs, docId);
        }
      }
      return _documents;
    }

    private void buildConfig(final ResultSet rs, final long docId) throws SQLException {
      final long docOid = rs.getLong("DOC_OID");
      final Timestamp versionFrom = rs.getTimestamp("VER_FROM_INSTANT");
      final Timestamp versionTo = rs.getTimestamp("VER_TO_INSTANT");
      final Timestamp correctionFrom = rs.getTimestamp("CORR_FROM_INSTANT");
      final Timestamp correctionTo = rs.getTimestamp("CORR_TO_INSTANT");
      final String name = rs.getString("NAME");
      final String configType = rs.getString("CONFIG_TYPE");
      LobHandler lob = getDialect().getLobHandler();
      byte[] bytes = lob.getBlobAsBytes(rs, "CONFIG");
      Class<?> reifiedType = null;
      try {
        reifiedType = ClassUtils.loadClass(configType);
      } catch (ClassNotFoundException ex) {
        s_logger.warn("ConfigType: {} class can not be found for docOid: {}", configType, docOid);
        return;
      }

      FudgeObjectReader objReader = s_fudgeContext.createObjectReader(new ByteArrayInputStream(bytes));
      FudgeMsg fudgeMsg = objReader.getMessageReader().nextMessage();
      try {

        FudgeDeserializer deserializer = new FudgeDeserializer(s_fudgeContext);
        Object configObj = deserializer.fudgeMsgToObject(reifiedType, fudgeMsg);
        ConfigItem<?> item = ConfigItem.of(configObj);
        item.setName(name);
        item.setType(reifiedType);
        ConfigDocument doc = new ConfigDocument(item);
        UniqueId uniqueId = createUniqueId(docOid, docId);
        doc.setUniqueId(uniqueId);
        IdUtils.setInto(configObj, uniqueId);
        doc.setVersionFromInstant(DbDateUtils.fromSqlTimestamp(versionFrom));
        doc.setVersionToInstant(DbDateUtils.fromSqlTimestampNullFarFuture(versionTo));
        doc.setCorrectionFromInstant(DbDateUtils.fromSqlTimestamp(correctionFrom));
        doc.setCorrectionToInstant(DbDateUtils.fromSqlTimestampNullFarFuture(correctionTo));
        _documents.add(doc);

      } catch (Exception ex) {
        s_logger.warn("Bad fudge message in database, unable to deserialise docOid:" + docOid + " " + fudgeMsg +
                          " to " + configType, ex);
      }
    }
  }

  @SuppressWarnings({"rawtypes", "unchecked" })
  @Override
  protected AbstractHistoryResult<ConfigDocument> historyByVersionsCorrections(AbstractHistoryRequest request) {
    ConfigHistoryRequest historyRequest = new ConfigHistoryRequest();
    historyRequest.setCorrectionsFromInstant(request.getCorrectionsFromInstant());
    historyRequest.setCorrectionsToInstant(request.getCorrectionsToInstant());
    historyRequest.setVersionsFromInstant(request.getVersionsFromInstant());
    historyRequest.setVersionsToInstant(request.getVersionsToInstant());
    historyRequest.setObjectId(request.getObjectId());
    return (AbstractHistoryResult) history(historyRequest);
  }

}
TOP

Related Classes of com.opengamma.masterdb.config.DbConfigWorker

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.