/* * Copyright (c) 2012. The Genome Analysis Centre, Norwich, UK * MISO project contacts: Robert Davey, Mario Caccamo @ TGAC * ********************************************************************* * * This file is part of MISO. * * MISO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * MISO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MISO. If not, see <http://www.gnu.org/licenses/>. * * ********************************************************************* */ package uk.ac.bbsrc.tgac.miso.notification.consumer.service.mechanism; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.integration.Message; import org.springframework.util.Assert; import uk.ac.bbsrc.tgac.miso.core.data.*; import uk.ac.bbsrc.tgac.miso.core.data.impl.RunImpl; import uk.ac.bbsrc.tgac.miso.core.data.impl.SequencerPartitionContainerImpl; import uk.ac.bbsrc.tgac.miso.core.data.impl.solid.SolidRun; import uk.ac.bbsrc.tgac.miso.core.data.impl.solid.SolidStatus; import uk.ac.bbsrc.tgac.miso.core.data.type.HealthType; import uk.ac.bbsrc.tgac.miso.core.data.type.PlatformType; import uk.ac.bbsrc.tgac.miso.core.exception.InterrogationException; import uk.ac.bbsrc.tgac.miso.core.manager.RequestManager; import uk.ac.bbsrc.tgac.miso.core.service.integration.mechanism.NotificationMessageConsumerMechanism; import uk.ac.bbsrc.tgac.miso.tools.run.RunFolderConstants; import java.io.IOException; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * uk.ac.bbsrc.tgac.miso.core.service.integration.mechanism.impl * <p/> * Info * * @author Rob Davey * @date 03/02/12 * @since 0.1.5 */ public class SolidNotificationMessageConsumerMechanism implements NotificationMessageConsumerMechanism<Message<Map<String, List<String>>>, Set<Run>> { protected static final Logger log = LoggerFactory.getLogger(SolidNotificationMessageConsumerMechanism.class); public boolean attemptRunPopulation = true; public void setAttemptRunPopulation(boolean attemptRunPopulation) { this.attemptRunPopulation = attemptRunPopulation; } private final String runDirRegex = RunFolderConstants.SOLID_FOLDER_NAME_GROUP_CAPTURE_REGEX; private final Pattern p = Pattern.compile(runDirRegex); @Override public Set<Run> consume(Message<Map<String, List<String>>> message) throws InterrogationException { RequestManager requestManager = message.getHeaders().get("handler", RequestManager.class); Assert.notNull(requestManager, "Cannot consume MISO notification messages without a RequestManager."); Map<String, List<String>> statuses = message.getPayload(); Set<Run> output = new HashSet<Run>(); for (String key : statuses.keySet()) { HealthType ht = HealthType.valueOf(key); JSONArray runs = (JSONArray) JSONArray.fromObject(statuses.get(key)).get(0); Map<String, Run> map = processRunJSON(ht, runs, requestManager); for (Run r : map.values()) { output.add(r); } } return output; } private Map<String, Run> processRunJSON(HealthType ht, JSONArray runs, RequestManager requestManager) { Map<String, Run> updatedRuns = new HashMap<String, Run>(); List<Run> runsToSave = new ArrayList<Run>(); //2011-01-25 15:37:27.093 DateFormat logDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); DateFormat simpleLogDateFormat = new SimpleDateFormat("yyyyMMdd"); Pattern simpleDateRegex = Pattern.compile("[0-9]{8}"); StringBuilder sb = new StringBuilder(); for (JSONObject run : (Iterable<JSONObject>)runs) { String runName = run.getString("runName"); sb.append("Processing " + runName + "\n"); log.debug("Processing " + runName); if (run.has("status")) { String xml = run.getString("status"); Status is = new SolidStatus(xml); is.setHealth(ht); is.setRunName(runName); Run r = null; Matcher m = p.matcher(runName); if (m.matches()) { try { r = requestManager.getRunByAlias(runName); } catch(IOException ioe) { log.warn("Cannot find run by this alias. This usually means the run hasn't been previously imported. If attemptRunPopulation is false, processing will not take place for this run!"); } } try { if (attemptRunPopulation) { if (r == null) { log.debug("Saving new run and status: " + is.getRunName()); r = new SolidRun(xml); r.getStatus().setHealth(ht); if (run.has("fullPath")) { r.setFilePath(run.getString("fullPath")); } SequencerReference sr = null; if (run.has("sequencerName")) { sr = requestManager.getSequencerReferenceByName(run.getString("sequencerName")); r.getStatus().setInstrumentName(run.getString("sequencerName")); r.setSequencerReference(sr); } if (r.getSequencerReference() == null) { sr = requestManager.getSequencerReferenceByName(m.group(1)); r.getStatus().setInstrumentName(m.group(1)); r.setSequencerReference(sr); } if (r.getSequencerReference() == null) { sr = requestManager.getSequencerReferenceByName(r.getStatus().getInstrumentName()); r.setSequencerReference(sr); } if (r.getSequencerReference() != null) { if (run.has("startDate")) { try { log.debug("Updating start date:" + run.getString("startDate")); Matcher m2 = simpleDateRegex.matcher(run.getString("startDate")); if (m2.matches()) { r.getStatus().setStartDate(simpleLogDateFormat.parse(run.getString("startDate"))); } else { r.getStatus().setStartDate(logDateFormat.parse(run.getString("startDate"))); } } catch (ParseException e) { log.error(e.getMessage()); e.printStackTrace(); } } if (run.has("completionDate")) { try { if (run.get("completionDate") != null && !run.getString("completionDate").equals("null")) { log.debug("Updating completion date:" + run.getString("completionDate")); r.getStatus().setCompletionDate(logDateFormat.parse(run.getString("completionDate"))); } else { r.getStatus().setCompletionDate(null); } } catch (ParseException e) { log.error(e.getMessage()); e.printStackTrace(); } } } } else { log.debug("Updating existing run and status: " + is.getRunName()); r.setAlias(runName); r.setPlatformType(PlatformType.SOLID); if (r.getSequencerReference() == null) { SequencerReference sr = null; if (run.has("sequencerName")) { sr = requestManager.getSequencerReferenceByName(run.getString("sequencerName")); r.getStatus().setInstrumentName(run.getString("sequencerName")); r.setSequencerReference(sr); } if (r.getSequencerReference() == null) { sr = requestManager.getSequencerReferenceByName(m.group(1)); r.getStatus().setInstrumentName(m.group(1)); r.setSequencerReference(sr); } if (r.getSequencerReference() == null) { sr = requestManager.getSequencerReferenceByName(r.getStatus().getInstrumentName()); r.setSequencerReference(sr); } } if (r.getSequencerReference() != null) { if (run.has("startDate")) { try { log.debug("Updating start date:" + run.getString("startDate")); Matcher m2 = simpleDateRegex.matcher(run.getString("startDate")); if (m2.matches()) { r.getStatus().setStartDate(simpleLogDateFormat.parse(run.getString("startDate"))); } else { r.getStatus().setStartDate(logDateFormat.parse(run.getString("startDate"))); } } catch (ParseException e) { log.error(e.getMessage()); e.printStackTrace(); } } if (run.has("completionDate")) { try { if (run.get("completionDate") != null && !run.getString("completionDate").equals("null")) { log.debug("Updating completion date:" + run.getString("completionDate")); r.getStatus().setCompletionDate(logDateFormat.parse(run.getString("completionDate"))); } else { r.getStatus().setCompletionDate(null); } } catch (ParseException e) { log.error(e.getMessage()); e.printStackTrace(); } } //update path if changed if (run.has("fullPath") && !"".equals(run.getString("fullPath")) && r.getFilePath() != null && !"".equals(r.getFilePath())) { if (!run.getString("fullPath").equals(r.getFilePath())) { log.debug("Updating run file path:" + r.getFilePath() + " -> " + run.getString("fullPath")); r.setFilePath(run.getString("fullPath")); } } // update status if run isn't completed or failed if (!r.getStatus().getHealth().equals(HealthType.Completed) && !r.getStatus().getHealth().equals(HealthType.Failed)) { log.debug("Saving previously saved status: " + is.getRunName() + " (" + r.getStatus().getHealth().getKey() + " -> " + is.getHealth().getKey() + ")"); r.setStatus(is); } } } if (r.getSequencerReference() != null) { List<SequencerPartitionContainer<SequencerPoolPartition>> fs = ((SolidRun)r).getSequencerPartitionContainers(); if (fs.isEmpty()) { if (run.has("containerId") && !"".equals(run.getString("containerId"))) { Collection<SequencerPartitionContainer<SequencerPoolPartition>> pfs = requestManager.listSequencerPartitionContainersByBarcode(run.getString("containerId")); if (!pfs.isEmpty()) { if (pfs.size() == 1) { SequencerPartitionContainer lf = new ArrayList<SequencerPartitionContainer<SequencerPoolPartition>>(pfs).get(0); if (lf.getSecurityProfile() != null && r.getSecurityProfile() == null) { r.setSecurityProfile(lf.getSecurityProfile()); } if (lf.getPlatform() == null && r.getSequencerReference().getPlatform() != null) { lf.setPlatform(r.getSequencerReference().getPlatform()); } // else { // lf.setPlatformType(PlatformType.SOLID); // } ((RunImpl)r).addSequencerPartitionContainer(lf); } } else { log.debug("No containers linked to run " + r.getId() + ": creating..."); SequencerPartitionContainer f = new SequencerPartitionContainerImpl(); f.setSecurityProfile(r.getSecurityProfile()); f.initEmptyPartitions(); f.setIdentificationBarcode(run.getString("containerNum")); if (f.getPlatform() == null && r.getSequencerReference().getPlatform() != null) { f.setPlatform(r.getSequencerReference().getPlatform()); } // else { // f.setPlatformType(PlatformType.SOLID); // } //f.setPaired(r.getPairedEnd()); ((RunImpl)r).addSequencerPartitionContainer(f); } } } else { SequencerPartitionContainer f = fs.iterator().next(); log.debug("Got container " + f.getId()); if (f.getSecurityProfile() == null) { f.setSecurityProfile(r.getSecurityProfile()); } if (f.getPlatform() == null && r.getSequencerReference().getPlatform() != null) { f.setPlatform(r.getSequencerReference().getPlatform()); } // else { // f.setPlatformType(PlatformType.SOLID); // } if (run.has("containerId") && !"".equals(run.getString("containerId"))) { f.setIdentificationBarcode(run.getString("containerId")); } long flowId = requestManager.saveSequencerPartitionContainer(f); f.setId(flowId); } updatedRuns.put(r.getAlias(), r); runsToSave.add(r); } } } catch (IOException e) { log.error(e.getMessage()); e.printStackTrace(); } } } try { if (runsToSave.size() > 0) { int[] saved = requestManager.saveRuns(runsToSave); log.info("Batch saved " + saved.length + " / "+ runs.size() + " runs"); } } catch (IOException e) { log.error("Couldn't save run batch: " + e.getMessage()); e.printStackTrace(); } return updatedRuns; } }