package edu.ualberta.med.biobank.tools.heartproblem; import jargs.gnu.CmdLineParser; import jargs.gnu.CmdLineParser.Option; import jargs.gnu.CmdLineParser.OptionException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import edu.ualberta.med.biobank.client.util.ServiceConnection; import edu.ualberta.med.biobank.common.wrappers.CollectionEventWrapper; import edu.ualberta.med.biobank.common.wrappers.OriginInfoWrapper; import edu.ualberta.med.biobank.common.wrappers.PatientWrapper; import edu.ualberta.med.biobank.common.wrappers.ProcessingEventWrapper; import edu.ualberta.med.biobank.common.wrappers.SiteWrapper; import edu.ualberta.med.biobank.common.wrappers.SpecimenTypeWrapper; import edu.ualberta.med.biobank.common.wrappers.SpecimenWrapper; import edu.ualberta.med.biobank.common.wrappers.StudyWrapper; import edu.ualberta.med.biobank.common.wrappers.helpers.SiteQuery; import edu.ualberta.med.biobank.common.wrappers.util.WrapperUtil; import edu.ualberta.med.biobank.model.CollectionEvent; import edu.ualberta.med.biobank.server.applicationservice.BiobankApplicationService; import gov.nih.nci.system.query.hibernate.HQLCriteria; /** * Fixes Issue #1487 - the HEART study problem where the tech's in Calgary * entered processing information into the cbsr-training server instead of the * production server. * * See the PNUMBERS array below for the patient numbers who's information must * be copied over. * */ @Deprecated public class ProblemFixer { private static String USAGE = "Usage: heartprobfix [options]\n\n" + "Options\n" + " -v, --verbose Shows verbose output"; private static final Logger LOGGER = Logger.getLogger(ProblemFixer.class .getName()); private static class AppArgs { @SuppressWarnings("unused") public boolean verbose = false; public String username = null; public String password = null; } public static final String[] PNUMBERS = { "DB0026", "DB0074", "DB0093", "DB0094", "DB0095", "DB0102" }; public static final String CEVENTS_HQL_QUERY = "select cevents" + " from " + CollectionEvent.class.getName() + " cevents" + " inner join cevents.patient patients " + " inner join fetch cevents.allSpecimens as spcs" + " left outer join fetch spcs.processingEvent pevents " + " left outer join fetch spcs.childSpecimens childSpcs " + " inner join fetch spcs.specimenType " + " where spcs.createdAt > '2011-06-18' and patients.pnumber=?"; private Map<String, SpecimenTypeWrapper> specimenTypes; private BiobankApplicationService tsAppService; private BiobankApplicationService appService; private StudyWrapper heartStudy; private SiteWrapper calgarySiteOnProduction; private String heartEventAttrLabel; public ProblemFixer(AppArgs appArgs) throws Exception { LOGGER.debug("username: " + appArgs.username); specimenTypes = new HashMap<String, SpecimenTypeWrapper>(); tsAppService = ServiceConnection.getAppService( "https://cbsr-training.med.ualberta.ca/biobank", appArgs.username, appArgs.password); appService = ServiceConnection.getAppService( "https://10.8.31.50/biobank", appArgs.username, appArgs.password); // appService = ServiceConnection // .getAppService("http://localhost:8080/biobank", appArgs.username, // appArgs.password); calgarySiteOnProduction = null; for (SiteWrapper site : SiteQuery.getSites(appService)) { if (site.getName().equals("Calgary Foothills")) { calgarySiteOnProduction = site; } } if (calgarySiteOnProduction == null) { throw new Exception("could not find calgary site on main server"); } heartStudy = null; for (StudyWrapper study : calgarySiteOnProduction.getStudyCollection()) { if (study.getNameShort().equals("HEART")) { heartStudy = study; } } if (heartStudy == null) { throw new Exception("could not find HEART study on main server"); } if (heartStudy.getStudyEventAttrLabels().length != 1) { throw new Exception( "unexpected number of event attrs in HEART study"); } for (SpecimenTypeWrapper spcType : SpecimenTypeWrapper .getAllSpecimenTypes(appService, true)) { specimenTypes.put(spcType.getName(), spcType); } heartEventAttrLabel = heartStudy.getStudyEventAttrLabels()[0]; processPatients(); } private void processPatients() throws Exception { for (String pnumber : PNUMBERS) { HQLCriteria c = new HQLCriteria(CEVENTS_HQL_QUERY, Arrays.asList(new Object[] { pnumber })); List<PatientWrapper> patients = new ArrayList<PatientWrapper>(); LOGGER.info("processing patient " + pnumber); for (Object raw : tsAppService.query(c)) { CollectionEventWrapper ceventOnTraining = new CollectionEventWrapper( tsAppService, (CollectionEvent) raw); String firstSourceSpecimenInvId = ceventOnTraining .getOriginalSpecimenCollection(false).get(0) .getInventoryId(); CollectionEventWrapper ceventOnProduction = collectionEventExists( appService, firstSourceSpecimenInvId); if (ceventOnProduction == null) { PatientWrapper patient = PatientWrapper.getPatient( appService, pnumber); if (patient == null) { LOGGER.info("creating patient " + pnumber); patient = new PatientWrapper(appService); patient.setPnumber(pnumber); patient.setCreatedAt(ceventOnTraining.getPatient() .getCreatedAt()); patient.setStudy(heartStudy); patient.persist(); patient.reload(); } else { LOGGER.info("patient " + pnumber + " already exists"); } patients.add(ceventOnTraining.getPatient()); ceventOnProduction = new CollectionEventWrapper(appService); ceventOnProduction.setPatient(patient); ceventOnProduction.setVisitNumber(PatientWrapper .getNextVisitNumber(appService, patient)); // ceventOnProduction // .setCommentCollection(ceventOnTraining // .getCommentCollection(false)); ceventOnProduction .setEventAttrValue(heartEventAttrLabel, ceventOnTraining .getEventAttrValue(heartEventAttrLabel)); ceventOnProduction.setActivityStatus(ceventOnTraining .getActivityStatus()); ceventOnProduction.persist(); ceventOnProduction.reload(); LOGGER.info("collection event created: patient/" + pnumber + " visit number/" + ceventOnTraining.getVisitNumber()); } else { LOGGER.info("collection event for " + firstSourceSpecimenInvId + " already in database"); } for (SpecimenWrapper spc : ceventOnTraining .getOriginalSpecimenCollection(false)) { if (!spc.getCurrentCenter().getNameShort() .equals("Calgary-F")) { throw new Exception("invalid center for specimen: " + spc.getCurrentCenter().getNameShort()); } if (spc.getSpecimenPosition() != null) { throw new Exception("specimen already has a position: " + spc.getInventoryId()); } if (!spc.getDispatchSpecimenCollection().isEmpty()) { throw new Exception( "specimen has dispatch information: " + spc.getInventoryId()); } processSourceSpecimen(spc, ceventOnProduction); } } } } private void processSourceSpecimen(SpecimenWrapper spcOnTraining, CollectionEventWrapper ceventOnProduction) throws Exception { // ensure specimen is not present on production server SpecimenWrapper spcOnProduction = SpecimenWrapper.getSpecimen( appService, spcOnTraining.getInventoryId()); if (spcOnProduction == null) { OriginInfoWrapper oi = new OriginInfoWrapper(appService); oi.setCenter(calgarySiteOnProduction); oi.persist(); spcOnProduction = new SpecimenWrapper(appService); spcOnProduction.setInventoryId(spcOnTraining.getInventoryId()); // spcOnProduction.setComment(spcOnTraining // .getCommentCollection(false)); spcOnProduction.setQuantity(spcOnTraining.getQuantity()); spcOnProduction.setCreatedAt(spcOnTraining.getCreatedAt()); spcOnProduction.setCollectionEvent(ceventOnProduction); spcOnProduction.setOriginalCollectionEvent(ceventOnProduction); spcOnProduction.setCurrentCenter(calgarySiteOnProduction); spcOnProduction .setActivityStatus(spcOnTraining.getActivityStatus()); spcOnProduction.setSpecimenType(specimenTypes.get(spcOnTraining .getSpecimenType().getName())); spcOnProduction.setOriginInfo(oi); spcOnProduction.persist(); spcOnProduction.reload(); LOGGER.info(" created source specimen: inventory_id/" + spcOnTraining.getInventoryId() + " created_at/" + spcOnTraining.getCreatedAt()); } else { LOGGER.info(" source specimen exists: inventory_id/" + spcOnTraining.getInventoryId() + " created_at/" + spcOnTraining.getCreatedAt()); } ProcessingEventWrapper peventOnTraining = spcOnTraining .getProcessingEvent(); if (peventOnTraining != null) { if (!peventOnTraining.getCenter().getNameShort() .equals("Calgary-F")) { throw new Exception("invalid center for processing event: " + peventOnTraining.getCenter().getNameShort()); } ProcessingEventWrapper peventOnProduction; List<ProcessingEventWrapper> peventsOnProduction = ProcessingEventWrapper .getProcessingEventsWithDateForCenter(appService, peventOnTraining.getCreatedAt(), calgarySiteOnProduction); if (peventsOnProduction.isEmpty()) { peventOnProduction = new ProcessingEventWrapper(appService); peventOnProduction .setWorksheet(peventOnTraining.getWorksheet()); peventOnProduction .setCreatedAt(peventOnTraining.getCreatedAt()); // peventOnProduction.setComment(peventOnTraining.getCommentCollection(false)); peventOnProduction.setCenter(calgarySiteOnProduction); peventOnProduction.setActivityStatus(peventOnTraining .getActivityStatus()); peventOnProduction.persist(); peventOnProduction.reload(); LOGGER.info(" created processing event: createdAt/" + peventOnTraining.getCreatedAt() + " worksheet/" + peventOnTraining.getWorksheet()); } else { if (peventsOnProduction.size() > 1) { throw new Exception( "more than one processing event with date " + peventOnTraining.getCreatedAt()); } peventOnProduction = peventsOnProduction.get(0); LOGGER.info(" found processing event: createdAt/" + peventOnTraining.getCreatedAt() + " worksheet/" + peventOnTraining.getWorksheet()); } if (spcOnProduction.getProcessingEvent() == null) { spcOnProduction.setProcessingEvent(peventOnProduction); spcOnProduction.persist(); spcOnProduction.reload(); } else if (!spcOnProduction.getProcessingEvent().getCreatedAt() .equals(peventOnTraining.getCreatedAt())) { throw new Exception("specimen has an invalid processing event" + spcOnProduction.getProcessingEvent().getCreatedAt()); } for (SpecimenWrapper childSpcOnTraining : spcOnTraining .getChildSpecimenCollection(false)) { if (!childSpcOnTraining.getCurrentCenter().getNameShort() .equals("Calgary-F")) { throw new Exception("invalid center for specimen: " + childSpcOnTraining.getCurrentCenter().getNameShort()); } processAliquotedSpecimen(childSpcOnTraining, spcOnProduction, ceventOnProduction); } } } private void processAliquotedSpecimen(SpecimenWrapper spcOnTraining, SpecimenWrapper parentSpc, CollectionEventWrapper ceventOnProduction) throws Exception { SpecimenWrapper spcOnProduction = SpecimenWrapper.getSpecimen( appService, spcOnTraining.getInventoryId()); if (spcOnProduction != null) { if (!spcOnProduction.getParentSpecimen().getInventoryId() .equals(parentSpc.getInventoryId())) { throw new Exception("parent specimen mismatch: " + spcOnProduction.getInventoryId()); } if (!spcOnProduction.getCollectionEvent().getVisitNumber() .equals(ceventOnProduction.getVisitNumber())) { throw new Exception("parent specimen cevent mismatch: " + spcOnProduction.getInventoryId()); } LOGGER.info(" aliquoted specimen exists: inventory_id/" + spcOnTraining.getInventoryId() + " created_at/" + spcOnTraining.getCreatedAt()); return; } OriginInfoWrapper oi = new OriginInfoWrapper(appService); oi.setCenter(calgarySiteOnProduction); oi.persist(); spcOnProduction = new SpecimenWrapper(appService); spcOnProduction.setInventoryId(spcOnTraining.getInventoryId()); // spcOnProduction.setComment(spcOnTraining.getCommentCollection(false)); spcOnProduction.setQuantity(spcOnTraining.getQuantity()); spcOnProduction.setCreatedAt(spcOnTraining.getCreatedAt()); spcOnProduction.setCollectionEvent(ceventOnProduction); spcOnProduction.setCollectionEvent(ceventOnProduction); // TODO just to be sure, check that the spcOnTraining current center is // calgary spcOnProduction.setCurrentCenter(calgarySiteOnProduction); spcOnProduction.setParentSpecimen(parentSpc); spcOnProduction.setActivityStatus(spcOnTraining.getActivityStatus()); spcOnProduction.setSpecimenType(specimenTypes.get(spcOnTraining .getSpecimenType().getName())); spcOnProduction.setOriginInfo(oi); spcOnProduction.persist(); spcOnProduction.reload(); LOGGER.info(" created aliquoted specimen: inventory_id/" + spcOnTraining.getInventoryId() + " created_at/" + spcOnTraining.getCreatedAt()); } public static final String CEVENT_HQL_QUERY = "select cevents" + " from edu.ualberta.med.biobank.model.CollectionEvent cevents" + " inner join cevents.allSpecimens as spcs" + " where spcs.inventoryId=?"; private CollectionEventWrapper collectionEventExists( BiobankApplicationService appService, String inventoryId) throws Exception { List<CollectionEvent> rawList = appService.query(new HQLCriteria( CEVENT_HQL_QUERY, Arrays.asList(new Object[] { inventoryId }))); if ((rawList == null) || rawList.isEmpty()) { return null; } if (rawList.size() > 1) { throw new Exception( "more than one collection event with inventory id " + inventoryId); } return WrapperUtil.wrapModel(appService, rawList.get(0), CollectionEventWrapper.class); } /* * Parses the command line arguments and returns them in an AppArgs object. */ private static AppArgs parseCommandLine(String argv[]) { AppArgs appArgs = new AppArgs(); CmdLineParser parser = new CmdLineParser(); Option verboseOpt = parser.addBooleanOption('v', "verbose"); try { parser.parse(argv); } catch (OptionException e) { LOGGER.info(e.getMessage()); System.exit(-1); } Boolean verbose = (Boolean) parser.getOptionValue(verboseOpt); if (verbose != null) { appArgs.verbose = verbose.booleanValue(); } String[] args = parser.getRemainingArgs(); if (args.length != 2) { LOGGER.info("Error: invalid arguments\n" + USAGE); System.exit(-1); } appArgs.username = args[0]; appArgs.password = args[1]; return appArgs; } public static void main(String[] args) { try { new ProblemFixer(parseCommandLine(args)); } catch (Exception e) { e.printStackTrace(); } } }