package org.ohdsi.webapi.evidence; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Types; import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.ohdsi.webapi.GenerationStatus; import org.ohdsi.webapi.conceptset.ConceptSetGenerationInfo; import org.ohdsi.webapi.conceptset.ConceptSetGenerationInfoRepository; import org.ohdsi.webapi.conceptset.ConceptSetGenerationType; import org.ohdsi.webapi.helper.ResourceHelper; import org.ohdsi.webapi.service.EvidenceService; import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionException; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; public class NegativeControlTasklet implements Tasklet { private static final Log log = LogFactory.getLog(NegativeControlTasklet.class); private final NegativeControl task; private final JdbcTemplate evidenceJdbcTemplate; private final JdbcTemplate ohdsiJdbcTemplate; private final TransactionTemplate transactionTemplate; private final ConceptSetGenerationInfoRepository conceptSetGenerationInfoRepository; //private final CohortResultsAnalysisRunner analysisRunner; public NegativeControlTasklet(NegativeControl task, final JdbcTemplate evidenceJdbcTemplate, final JdbcTemplate ohdsiJdbcTemplate, final TransactionTemplate transactionTemplate, final ConceptSetGenerationInfoRepository repository, String sourceDialect) { this.task = task; this.evidenceJdbcTemplate = evidenceJdbcTemplate; this.ohdsiJdbcTemplate = ohdsiJdbcTemplate; this.transactionTemplate = transactionTemplate; this.conceptSetGenerationInfoRepository = repository; //this.analysisRunner = new CohortResultsAnalysisRunner(sourceDialect, visualizationDataRepository); } private ConceptSetGenerationInfo findBySourceId(Collection<ConceptSetGenerationInfo> infoList, Integer sourceId) { for (ConceptSetGenerationInfo info : infoList) { if (info.getSourceId().equals(sourceId)) return info; } return null; } @Override public RepeatStatus execute(final StepContribution contribution, final ChunkContext chunkContext) throws Exception { Date startTime = Calendar.getInstance().getTime(); Map<String, Object> jobParams = chunkContext.getStepContext().getJobParameters(); Integer conceptSetId = Integer.valueOf(jobParams.get("concept_set_id").toString()); final Integer sourceId = Integer.valueOf(jobParams.get("source_id").toString()); boolean isValid = false; DefaultTransactionDefinition initTx = new DefaultTransactionDefinition(); initTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); TransactionStatus initStatus = this.transactionTemplate.getTransactionManager().getTransaction(initTx); ConceptSetGenerationInfo info = findBySourceId(this.conceptSetGenerationInfoRepository.findAllByConceptSetId(conceptSetId), sourceId); if (info == null) { info = new ConceptSetGenerationInfo(); info.setConceptSetId(conceptSetId); info.setSourceId(sourceId); info.setGenerationType(ConceptSetGenerationType.NEGATIVE_CONTROLS); } info.setIsValid(isValid); info.setStartTime(startTime); info.setStatus(GenerationStatus.RUNNING); this.conceptSetGenerationInfoRepository.save(info); this.transactionTemplate.getTransactionManager().commit(initStatus); try { final int[] ret = this.transactionTemplate.execute(new TransactionCallback<int[]>() { @Override public int[] doInTransaction(final TransactionStatus status) { log.debug("entering tasklet"); String negativeControlSql = EvidenceService.getNegativeControlSql(task); log.debug("negative control sql to execute: " + negativeControlSql); final List<NegativeControlRecord> recs = NegativeControlTasklet.this.evidenceJdbcTemplate.query(negativeControlSql, new NegativeControlMapper()); // Remove any results that exist for the concept set String deleteSql = EvidenceService.getNegativeControlDeleteStatementSql(task); Object[] params = { task.getConceptSetId(), task.getSource().getSourceId() }; int[] types = { Types.INTEGER, Types.INTEGER }; int rows = NegativeControlTasklet.this.ohdsiJdbcTemplate.update(deleteSql, params, types); log.debug("rows deleted: " + rows); // Insert the results String insertSql = EvidenceService.getNegativeControlInsertStatementSql(task); return NegativeControlTasklet.this.ohdsiJdbcTemplate.batchUpdate(insertSql, new BatchPreparedStatementSetter() { @Override public void setValues(PreparedStatement ps, int i) throws SQLException { NegativeControlRecord ncr = recs.get(i); ps.setInt(1, ncr.getSourceId()); ps.setInt(2, ncr.getConceptSetId()); ps.setString(3, ncr.getConceptSetName()); ps.setInt(4, ncr.getConceptId()); ps.setString(5, ncr.getConceptName()); ps.setString(6, ncr.getDomainId()); ps.setDouble(7, ncr.getMedlineCt()); ps.setDouble(8, ncr.getMedlineCase()); ps.setDouble(9, ncr.getMedlineOther()); ps.setDouble(10, ncr.getSemmeddbCtT()); ps.setDouble(11, ncr.getSemmeddbCaseT()); ps.setDouble(12, ncr.getSemmeddbOtherT()); ps.setDouble(13, ncr.getSemmeddbCtF()); ps.setDouble(14, ncr.getSemmeddbCaseF()); ps.setDouble(15, ncr.getSemmeddbOtherF()); ps.setDouble(16, ncr.getEu_spc()); ps.setDouble(17, ncr.getSplADR()); ps.setDouble(18, ncr.getAers()); ps.setDouble(19, ncr.getAersPRR()); ps.setDouble(20, ncr.getMedlineCtScaled()); ps.setDouble(21, ncr.getMedlineCaseScaled()); ps.setDouble(22, ncr.getMedlineOtherScaled()); ps.setDouble(23, ncr.getSemmeddbCtTScaled()); ps.setDouble(24, ncr.getSemmeddbCaseTScaled()); ps.setDouble(25, ncr.getSemmeddbOtherTScaled()); ps.setDouble(26, ncr.getSemmeddbCtFScaled()); ps.setDouble(27, ncr.getSemmeddbCaseFScaled()); ps.setDouble(28, ncr.getSemmeddbOtherFScaled()); ps.setDouble(29, ncr.getEuSPCScaled()); ps.setDouble(30, ncr.getSplADRScaled()); ps.setDouble(31, ncr.getAersScaled()); ps.setDouble(32, ncr.getAersPRRScaled()); ps.setDouble(33, ncr.getMedlineCtBeta()); ps.setDouble(34, ncr.getMedlineCaseBeta()); ps.setDouble(35, ncr.getMedlineOtherBeta()); ps.setDouble(36, ncr.getSemmeddbCtTBeta()); ps.setDouble(37, ncr.getSemmeddbCaseTBeta()); ps.setDouble(38, ncr.getSemmeddbOtherFBeta()); ps.setDouble(39, ncr.getSemmeddbCtFBeta()); ps.setDouble(40, ncr.getSemmeddbCaseFBeta()); ps.setDouble(41, ncr.getSemmeddbOtherFBeta()); ps.setDouble(42, ncr.getEuSPCBeta()); ps.setDouble(43, ncr.getSplADRBeta()); ps.setDouble(44, ncr.getAersBeta()); ps.setDouble(45, ncr.getAersPRRBeta()); ps.setDouble(46, ncr.getRawPrediction()); ps.setDouble(47, ncr.getPrediction()); } @Override public int getBatchSize() { return recs.size(); } }); } }); log.debug("Update count: " + ret.length); isValid = true; /* log.debug("warm up visualizations"); final int count = this.analysisRunner.warmupData(evidenceJdbcTemplate, task); log.debug("warmed up " + count + " visualizations"); */ } catch (final TransactionException e) { log.error(e.getMessage(), e); throw e;//FAIL job status } finally { DefaultTransactionDefinition completeTx = new DefaultTransactionDefinition(); completeTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); TransactionStatus completeStatus = this.transactionTemplate.getTransactionManager().getTransaction(completeTx); info = findBySourceId(this.conceptSetGenerationInfoRepository.findAllByConceptSetId(conceptSetId), sourceId); Date endTime = Calendar.getInstance().getTime(); info.setExecutionDuration(new Integer((int)(endTime.getTime() - startTime.getTime()))); info.setIsValid(isValid); GenerationStatus status = isValid ? GenerationStatus.COMPLETE : GenerationStatus.ERROR; info.setStatus(status); this.conceptSetGenerationInfoRepository.save(info); this.transactionTemplate.getTransactionManager().commit(completeStatus); } return RepeatStatus.FINISHED; } }