Java tutorial
/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.masterdb.batch; import static com.google.common.collect.Lists.newArrayList; import static com.opengamma.util.db.HibernateDbUtils.eqOrIsNull; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import org.hibernate.Criteria; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.Order; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; 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.orm.hibernate3.HibernateCallback; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import com.opengamma.DataNotFoundException; import com.opengamma.batch.BatchMasterWriter; import com.opengamma.batch.RunCreationMode; import com.opengamma.batch.SnapshotMode; import com.opengamma.batch.domain.MarketData; import com.opengamma.batch.domain.MarketDataValue; import com.opengamma.batch.domain.RiskRun; import com.opengamma.batch.domain.RiskValueProperties; import com.opengamma.batch.rest.BatchRunSearchRequest; import com.opengamma.engine.ComputationTargetResolver; import com.opengamma.engine.target.ComputationTargetType; import com.opengamma.engine.value.ComputedValueResult; import com.opengamma.engine.value.ValueProperties; import com.opengamma.engine.value.ValueSpecification; import com.opengamma.engine.view.AggregatedExecutionLog; import com.opengamma.engine.view.ViewComputationResultModel; import com.opengamma.engine.view.ViewResultEntry; import com.opengamma.engine.view.cycle.ViewCycleMetadata; import com.opengamma.id.ObjectId; import com.opengamma.id.UniqueId; import com.opengamma.masterdb.AbstractDbMaster; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.db.DbConnector; import com.opengamma.util.db.DbMapSqlParameterSource; import com.opengamma.util.paging.Paging; import com.opengamma.util.paging.PagingRequest; import com.opengamma.util.tuple.Pair; /** * A batch master implementation using a database for persistence. * <p> * This is a full implementation of the batch master using an SQL database. * Full details of the API are in {@link BatchMasterWriter}. * <p> * The SQL is stored externally in {@code DbBatchMaster.elsql}. * Alternate databases or specific SQL requirements can be handled using database * specific overrides, such as {@code DbBatchMaster-MySpecialDB.elsql}. * <p> * This class is mutable but must be treated as immutable after configuration. */ public class DbBatchMaster extends AbstractDbMaster implements BatchMasterWriter { /** Logger. */ private static final Logger s_logger = LoggerFactory.getLogger(DbBatchMaster.class); /** * The batch writer. */ private final DbBatchWriter _dbBatchWriter; /** * Creates an instance. * * @param dbConnector the database connector, not null */ public DbBatchMaster(final DbConnector dbConnector, final ComputationTargetResolver computationTargetResolver) { super(dbConnector, BATCH_IDENTIFIER_SCHEME); _dbBatchWriter = new DbBatchWriter(dbConnector, computationTargetResolver); setElSqlBundle(_dbBatchWriter.getElSqlBundle()); } //------------------------------------------------------------------------- @Override public RiskRun getRiskRun(final ObjectId uniqueId) { ArgumentChecker.notNull(uniqueId, "uniqueId"); s_logger.info("Getting BatchDocument by unique id: ", uniqueId); final Long id = extractOid(uniqueId); return getHibernateTransactionTemplate().execute(new HibernateCallback<RiskRun>() { @Override public RiskRun doInHibernate(final Session session) throws HibernateException, SQLException { final RiskRun run = _dbBatchWriter.getRiskRunById(id); if (run != null) { return run; } else { throw new DataNotFoundException("Batch run not found: " + id); } } }); } @Override @SuppressWarnings("unchecked") public Pair<List<MarketData>, Paging> getMarketData(final PagingRequest pagingRequest) { s_logger.info("Getting markte datas: ", pagingRequest); return getTransactionTemplateRetrying(getMaxRetries()) .execute(new TransactionCallback<Pair<List<MarketData>, Paging>>() { @Override public Pair<List<MarketData>, Paging> doInTransaction(final TransactionStatus status) { final DetachedCriteria criteria = DetachedCriteria.forClass(MarketData.class); List<MarketData> results = Collections.emptyList(); if (!pagingRequest.equals(PagingRequest.NONE)) { results = getHibernateTemplate().findByCriteria(criteria, pagingRequest.getFirstItem(), pagingRequest.getPagingSize()); } // Paging paging; if (pagingRequest.equals(PagingRequest.ALL)) { paging = Paging.of(pagingRequest, results); } else { criteria.setProjection(Projections.rowCount()); final Long totalCount = (Long) getHibernateTemplate().findByCriteria(criteria).get(0); paging = Paging.of(pagingRequest, totalCount.intValue()); } // return Pair.of(results, paging); } }); } @Override public MarketData getMarketDataById(final ObjectId batchSnapshotId) { s_logger.info("Getting the batch data snapshot: {}", batchSnapshotId); final Long marketDataPK = extractOid(batchSnapshotId); return getTransactionTemplateRetrying(getMaxRetries()).execute(new TransactionCallback<MarketData>() { @Override public MarketData doInTransaction(final TransactionStatus status) { return getHibernateTemplate().get(MarketData.class, marketDataPK); } }); } @Override @SuppressWarnings("unchecked") public Pair<List<MarketDataValue>, Paging> getMarketDataValues(final ObjectId marketDataId, final PagingRequest pagingRequest) { s_logger.info("Getting the batch data snapshot: {}", marketDataId); final Long marketDataPK = extractOid(marketDataId); return getTransactionTemplateRetrying(getMaxRetries()) .execute(new TransactionCallback<Pair<List<MarketDataValue>, Paging>>() { @Override public Pair<List<MarketDataValue>, Paging> doInTransaction(final TransactionStatus status) { final DetachedCriteria criteria = DetachedCriteria.forClass(MarketDataValue.class); criteria.add(Restrictions.eq("marketDataId", marketDataPK)); // List<MarketDataValue> results = Collections.emptyList(); if (!pagingRequest.equals(PagingRequest.NONE)) { results = getHibernateTemplate().findByCriteria(criteria, pagingRequest.getFirstItem(), pagingRequest.getPagingSize()); } // Paging paging; if (pagingRequest.equals(PagingRequest.ALL)) { paging = Paging.of(pagingRequest, results); } else { criteria.setProjection(Projections.rowCount()); final Long totalCount = (Long) getHibernateTemplate().findByCriteria(criteria).get(0); paging = Paging.of(pagingRequest, totalCount.intValue()); } // return Pair.of(results, paging); } }); } @Override public void deleteMarketData(final ObjectId batchSnapshotId) { s_logger.info("Deleting market data snapshot: ", batchSnapshotId); getTransactionTemplateRetrying(getMaxRetries()).execute(new TransactionCallback<Void>() { @Override public Void doInTransaction(final TransactionStatus status) { _dbBatchWriter.deleteSnapshotInTransaction(batchSnapshotId); return null; } }); } //------------------------------------------------------------------------- @Override @SuppressWarnings("unchecked") public Pair<List<RiskRun>, Paging> searchRiskRun(final BatchRunSearchRequest request) { s_logger.info("Searching BatchDocuments: ", request); final DetachedCriteria criteria = DetachedCriteria.forClass(RiskRun.class); if (request.getValuationTime() != null) { criteria.add(Restrictions.eq("valuationTime", request.getValuationTime())); } if (request.getVersionCorrection() != null) { criteria.add(Restrictions.eq("versionCorrection", request.getVersionCorrection())); } if (request.getMarketDataUid() != null) { criteria.createCriteria("marketData") .add(Restrictions.eq("baseUidScheme", request.getMarketDataUid().getScheme())) .add(Restrictions.eq("baseUidValue", request.getMarketDataUid().getValue())) .add(eqOrIsNull("baseUidVersion", request.getMarketDataUid().getVersion())); //.addOrder(Order.asc("baseUid")); } if (request.getViewDefinitionUid() != null) { criteria.add(Restrictions.eq("viewDefinitionUidScheme", request.getViewDefinitionUid().getScheme())) .add(Restrictions.eq("viewDefinitionUidValue", request.getViewDefinitionUid().getValue())) .add(eqOrIsNull("viewDefinitionUidVersion", request.getViewDefinitionUid().getVersion())); //.addOrder(Order.asc("viewDefinitionUid")); } return getTransactionTemplateRetrying(getMaxRetries()) .execute(new TransactionCallback<Pair<List<RiskRun>, Paging>>() { @Override public Pair<List<RiskRun>, Paging> doInTransaction(final TransactionStatus status) { // final PagingRequest pagingRequest = request.getPagingRequest(); List<RiskRun> results = Collections.emptyList(); Paging paging; if (!pagingRequest.equals(PagingRequest.NONE)) { if (pagingRequest.equals(PagingRequest.ALL)) { criteria.addOrder(Order.asc("valuationTime")); results = getHibernateTemplate().findByCriteria(criteria, pagingRequest.getFirstItem(), pagingRequest.getPagingSize()); // paging = Paging.of(pagingRequest, results); } else { criteria.setProjection(Projections.rowCount()); final Long totalCount = (Long) getHibernateTemplate().findByCriteria(criteria) .get(0); paging = Paging.of(pagingRequest, totalCount.intValue()); // criteria.setProjection(null); criteria.setResultTransformer(Criteria.ROOT_ENTITY); criteria.addOrder(Order.asc("valuationTime")); results = getHibernateTemplate().findByCriteria(criteria, pagingRequest.getFirstItem(), pagingRequest.getPagingSize()); } } else { paging = Paging.of(PagingRequest.NONE, 0); } return Pair.of(results, paging); } }); } //------------------------------------------------------------------------- @Override public void addValuesToMarketData(final ObjectId marketDataId, final Set<MarketDataValue> values) { getTransactionTemplateRetrying(getMaxRetries()).execute(new TransactionCallback<Void>() { @Override public Void doInTransaction(final TransactionStatus status) { _dbBatchWriter.addValuesToMarketDataInTransaction(marketDataId, values); return null; } }); } @Override public RiskRun startRiskRun(final ViewCycleMetadata cycleMetadata, final Map<String, String> batchParameters, final RunCreationMode runCreationMode, final SnapshotMode snapshotMode) { return getTransactionTemplateRetrying(getMaxRetries()).execute(new TransactionCallback<RiskRun>() { @Override public RiskRun doInTransaction(final TransactionStatus status) { return _dbBatchWriter.startBatchInTransaction(cycleMetadata, batchParameters, runCreationMode, snapshotMode); } }); } @Override public void deleteRiskRun(final ObjectId batchUniqueId) { getTransactionTemplateRetrying(getMaxRetries()).execute(new TransactionCallback<Void>() { @Override public Void doInTransaction(final TransactionStatus status) { _dbBatchWriter.deleteBatchInTransaction(batchUniqueId); return null; } }); } /** * Searches for documents with paging. * * @param <D> the list type * @param pagingRequest the paging request, not null * @param sql the array of SQL, query and count, not null * @param args the query arguments, not null * @param extractor the extractor of results, not null * @return values with its paging descriptor */ protected <D> Pair<List<D>, Paging> searchWithPaging(final PagingRequest pagingRequest, final String[] sql, final DbMapSqlParameterSource args, final ResultSetExtractor<List<D>> extractor) { return getTransactionTemplateRetrying(getMaxRetries()) .execute(new TransactionCallback<Pair<List<D>, Paging>>() { @Override public Pair<List<D>, Paging> doInTransaction(final TransactionStatus status) { final List<D> result = newArrayList(); Paging paging; s_logger.debug("with args {}", args); final NamedParameterJdbcOperations namedJdbc = getDbConnector().getJdbcTemplate(); if (pagingRequest.equals(PagingRequest.ALL)) { result.addAll(namedJdbc.query(sql[0], args, extractor)); paging = Paging.of(pagingRequest, result); } else { s_logger.debug("executing sql {}", sql[1]); final int count = namedJdbc.queryForObject(sql[1], args, Integer.class); paging = Paging.of(pagingRequest, count); if (count > 0 && !pagingRequest.equals(PagingRequest.NONE)) { s_logger.debug("executing sql {}", sql[0]); result.addAll(namedJdbc.query(sql[0], args, extractor)); } } return Pair.of(result, paging); } }); } @Override public Pair<List<ViewResultEntry>, Paging> getBatchValues(final ObjectId batchId, final PagingRequest pagingRequest) { s_logger.info("Getting Batch values: ", pagingRequest); final Long runId = extractOid(batchId); final DbMapSqlParameterSource args = new DbMapSqlParameterSource(); args.addValue("run_id", runId); if (pagingRequest != null) { args.addValue("paging_offset", pagingRequest.getFirstItem()); args.addValue("paging_fetch", pagingRequest.getPagingSize()); } final String[] sql = { getElSqlBundle().getSql("GetBatchValues", args), getElSqlBundle().getSql("BatchValuesCount", args) }; return searchWithPaging(pagingRequest, sql, args, new BatchValuesExtractor()); } @Override public void endRiskRun(final ObjectId batchUniqueId) { getTransactionTemplateRetrying(getMaxRetries()).execute(new TransactionCallback<Void>() { @Override public Void doInTransaction(final TransactionStatus status) { _dbBatchWriter.endBatchInTransaction(batchUniqueId); return null; } }); } @Override public MarketData createMarketData(final UniqueId marketDataSnapshotUniqueId) { return getTransactionTemplateRetrying(getMaxRetries()).execute(new TransactionCallback<MarketData>() { @Override public MarketData doInTransaction(final TransactionStatus status) { return _dbBatchWriter.createOrGetMarketDataInTransaction(marketDataSnapshotUniqueId); } }); } //------------------------------------------------------------------------- @Override public void addJobResults(final ObjectId riskRunId, final ViewComputationResultModel result) { getTransactionTemplateRetrying(getMaxRetries()).execute(new TransactionCallback<Void>() { @Override public Void doInTransaction(final TransactionStatus status) { _dbBatchWriter.addJobResultsInTransaction(status, riskRunId, result); return null; } }); } /** * Mapper from SQL rows to a ViewResultEntries. */ protected final class BatchValuesExtractor implements ResultSetExtractor<List<ViewResultEntry>> { @Override public List<ViewResultEntry> extractData(final ResultSet rs) throws SQLException, DataAccessException { final List<ViewResultEntry> data = newArrayList(); while (rs.next()) { data.add(buildBatchValue(rs)); } return data; } private ViewResultEntry buildBatchValue(final ResultSet rs) throws SQLException { // final long id = rs.getLong("ID"); // final long calculationConfigurationId = rs.getLong("calculation_configuration_id"); // final long valueSpecificationId = rs.getLong("value_specification_id"); // final long functionUniqueId = rs.getLong("function_unique_id"); // final long computationTargetId = rs.getLong("computation_target_id"); // final long runId = rs.getLong("run_id"); final double value = rs.getDouble("value"); final String valueName = rs.getString("name"); // final Timestamp evalInstant = rs.getTimestamp("eval_instant"); // final long computeNodeId = rs.getLong("compute_node_id"); final ComputationTargetType computationTargetType = ComputationTargetType .parse(rs.getString("target_type")); final String valueRequirementsSyntheticForm = rs.getString("synthetic_form"); final String targetTypeIdScheme = rs.getString("target_type_id_scheme"); final String targetTypeIdValue = rs.getString("target_type_id_value"); final String targetTypeIdVersion = rs.getString("target_type_id_version"); final UniqueId targetId = UniqueId.of(targetTypeIdScheme, targetTypeIdValue, targetTypeIdVersion); final ValueProperties valueProperties = RiskValueProperties.parseJson(valueRequirementsSyntheticForm); final String configurationName = rs.getString("config_name"); final ValueSpecification valueSpecification = ValueSpecification.of(valueName, computationTargetType, targetId, valueProperties); final ComputedValueResult computedValue = new ComputedValueResult(valueSpecification, value, AggregatedExecutionLog.EMPTY); final ViewResultEntry viewResultEntry = new ViewResultEntry(configurationName, computedValue); return viewResultEntry; } } }