/* * 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.spring.ajax; import com.eaglegenomics.simlims.core.User; import com.eaglegenomics.simlims.core.manager.SecurityManager; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import net.sourceforge.fluxion.ajax.Ajaxified; import net.sourceforge.fluxion.ajax.util.JSONUtils; import org.apache.commons.codec.binary.Base64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.util.AutoPopulatingList; import uk.ac.bbsrc.tgac.miso.core.data.*; import uk.ac.bbsrc.tgac.miso.core.data.impl.PartitionImpl; import uk.ac.bbsrc.tgac.miso.core.data.type.PlatformType; import uk.ac.bbsrc.tgac.miso.core.exception.MalformedExperimentException; import uk.ac.bbsrc.tgac.miso.core.factory.DataObjectFactory; import uk.ac.bbsrc.tgac.miso.core.manager.RequestManager; import uk.ac.bbsrc.tgac.miso.core.util.LimsUtils; import javax.servlet.http.HttpSession; import java.io.IOException; import java.net.URLDecoder; import java.util.*; /** * Created by IntelliJ IDEA. * User: davey * Date: 25-May-2010 * Time: 16:39:52 */ @Ajaxified public class ContainerControllerHelperService { protected static final Logger log = LoggerFactory.getLogger(ContainerControllerHelperService.class); @Autowired private SecurityManager securityManager; @Autowired private RequestManager requestManager; @Autowired private DataObjectFactory dataObjectFactory; public JSONObject getPlatformTypes(HttpSession session, JSONObject json) throws IOException { StringBuilder b = new StringBuilder(); List<String> platformTypes = PlatformType.getKeys(); for (String p : platformTypes) { b.append("<input type='radio' name='platformTypes' id='platformTypes" + p + "' value='" + p + "' onchange='Container.ui.changeContainerPlatformType(this);'/>"); b.append("<label for='platformTypes" + p + "'>" + p + "</label>"); } return JSONUtils.JSONObjectResponse("html", b.toString()); } public JSONObject changePlatformType(HttpSession session, JSONObject json) { String newContainerType = json.getString("platformtype"); PlatformType pt = PlatformType.get(newContainerType); //String cId = json.getString("container_cId"); try { //User user = securityManager.getUserByLoginName(SecurityContextHolder.getContext().getAuthentication().getName()); Map<String, Object> responseMap = new HashMap<String, Object>(); if (pt != null) { // don't create a new container - one should already be available in the session, either presaved or not //SequencerPartitionContainer<SequencerPoolPartition> lf = dataObjectFactory.getSequencerPartitionContainer(user); //session.setAttribute("container_" + cId, lf); StringBuilder srb = new StringBuilder(); srb.append("<select name='sequencer' id='sequencerReference' onchange='Container.ui.populateContainerOptions(this);'>"); srb.append("<option value='0' selected='selected'>Please select...</option>"); for (SequencerReference sr : requestManager.listSequencerReferencesByPlatformType(pt)) { srb.append("<option value='" + sr.getId() + "'>" + sr.getName() + " (" + sr.getPlatform().getInstrumentModel() + ")</option>"); } srb.append("</select>"); responseMap.put("sequencers", srb.toString()); } else { return JSONUtils.SimpleJSONError("Unrecognised PlatformType"); } return JSONUtils.JSONObjectResponse(responseMap); } catch (IOException e) { log.debug("Failed to change PlatformType", e); return JSONUtils.SimpleJSONError("Failed to change PlatformType"); } } public JSONObject populateContainerOptions(HttpSession session, JSONObject json) { Long sequencerReferenceId = json.getLong("sequencerReference"); try { SequencerPartitionContainer<SequencerPoolPartition> lf = (SequencerPartitionContainer<SequencerPoolPartition>) session.getAttribute("container_" + json.getString("container_cId")); if (lf.getPlatform() == null) { if(lf.getId() == AbstractSequencerPartitionContainer.UNSAVED_ID) { SequencerReference sr = requestManager.getSequencerReferenceById(sequencerReferenceId); Map<String, Object> responseMap = new HashMap<>(); responseMap.put("partitions", getContainerOptions(sr)); responseMap.put("platformId", sr.getPlatform().getPlatformId()); return JSONUtils.JSONObjectResponse(responseMap); } else { SequencerReference sr = requestManager.getSequencerReferenceById(sequencerReferenceId); lf.setPlatform(sr.getPlatform()); Map<String, Object> responseMap = new HashMap<>(); responseMap.put("platformId", sr.getPlatform().getPlatformId()); return JSONUtils.JSONObjectResponse(responseMap); } } else { Map<String, Object> responseMap = new HashMap<>(); SequencerReference sr = requestManager.getSequencerReferenceById(sequencerReferenceId); responseMap.put("platformId", sr.getPlatform().getPlatformId()); return JSONUtils.JSONObjectResponse(responseMap); } } catch (IOException e) { e.printStackTrace(); return JSONUtils.SimpleJSONError("Failed to get Container options"); } } private String getContainerOptions(SequencerReference sr) throws IOException { StringBuilder b = new StringBuilder(); b.append("<span id='containerspan'>Containers: "); PlatformType pt = sr.getPlatform().getPlatformType(); for (int i = 0; i < sr.getPlatform().getNumContainers(); i++) { b.append("<input id='container" + (i + 1) + "' name='containerselect' onchange='Container.ui.changeContainer(" + sr.getPlatform().getNumContainers() + ", \"" + pt.getKey() + "\", " + sr.getId() + ");' type='radio' value='" + (i + 1) + "'/>" + (i + 1)); } b.append("</span><br/>"); b.append("<div id='containerdiv' class='note ui-corner-all'> </div>"); return b.toString(); } public JSONObject changeContainer(HttpSession session, JSONObject json) { if (json.has("platform")) { String platform = json.getString("platform"); PlatformType pt = PlatformType.get(platform); if (pt != null) { if (pt.equals(PlatformType.ILLUMINA)) { return changeIlluminaContainer(session, json); } else if (pt.equals(PlatformType.LS454)) { return changeLS454Container(session, json); } else if (pt.equals(PlatformType.SOLID)) { return changeSolidContainer(session, json); } /* else if (pt.equals(PlatformType.IONTORRENT)) { return null; } */ else if (pt.equals(PlatformType.PACBIO)) { return changePacBioContainer(session, json); } else { return JSONUtils.SimpleJSONError("Unsupported platform type: " + platform); } } } return JSONUtils.SimpleJSONError("No platform specified"); } public JSONObject changeIlluminaContainer(HttpSession session, JSONObject json) { long seqRefId = json.getLong("sequencerReferenceId"); StringBuilder b = new StringBuilder(); b.append("<h2>Container</h2>"); b.append("<table class='in'>"); b.append("<tr><td>ID:</td><td><button onclick='Container.lookupContainer(this);' type='button' class='right-button ui-state-default ui-corner-all'>Lookup</button><div style='overflow:hidden'><input type='text' id='identificationBarcode' name='identificationBarcode'/><input type='hidden' value='on' name='_identificationBarcode'></div></td></tr>"); b.append("<tr><td>Location:</td><td><input type='text' id='locationBarcode' name='locationBarcode'/><input type='hidden' value='on' name='_locationBarcode'></td></tr>"); b.append("<tr><td>Validation:</td><td><input type='text' id='validationBarcode' name='validationBarcode'/><input type='hidden' value='on' name='_validationBarcode'></td></tr>"); b.append("<tr><td>Paired:</td><td><input type='checkbox' id='paired' name='paired' value='false'/><input type='hidden' value='on' name='_paired'></td></tr>"); b.append("</table>"); b.append("<div id='partitionErrorDiv'> </div>"); b.append("<div id='partitionDiv'>"); try { SequencerReference sr = requestManager.getSequencerReferenceById(seqRefId); String instrumentModel = sr.getPlatform().getInstrumentModel(); if ("Illumina MiSeq".equals(instrumentModel) || "Illumina NextSeq 500".equals(instrumentModel)) { b.append("<i class='italicInfo'>Click in a partition box to beep/type in barcodes, or double click a pool on the right to sequentially add pools to the container</i>"); b.append("<table class='in'>"); b.append("<th>Lane No.</th>"); b.append("<th>Pool</th>"); b.append("<tr><td>1 </td><td width='90%'><div id='p_div-0'><ul class='runPartitionDroppable' bind='partitions[0].pool' partition='0' ondblclick='Container.partition.populatePartition(this);'></ul></div></td></tr>"); b.append("</table>"); b.append("</div>"); SequencerPartitionContainer<SequencerPoolPartition> lf = (SequencerPartitionContainer<SequencerPoolPartition>) session.getAttribute("container_" + json.getString("container_cId")); lf.setPlatform(sr.getPlatform()); lf.setPartitionLimit(1); lf.initEmptyPartitions(); } else if ("Illumina HiSeq 2500".equals(sr.getPlatform().getInstrumentModel())) { SequencerPartitionContainer<SequencerPoolPartition> lf = (SequencerPartitionContainer<SequencerPoolPartition>) session.getAttribute("container_" + json.getString("container_cId")); lf.setPlatform(sr.getPlatform()); b.append("<input id='lane2' name='container0Select' onchange='Container.ui.changeContainerIlluminaLane(this, 0);' type='radio' value='2'/>2 "); b.append("<input id='lane8' name='container0Select' onchange='Container.ui.changeContainerIlluminaLane(this, 0);' type='radio' value='8'/>8 "); b.append("<div id='containerdiv0'> </div>"); } else { b.append("<i class='italicInfo'>Click in a partition box to beep/type in barcodes, or double click a pool on the right to sequentially add pools to the container</i>"); b.append("<table class='in'>"); b.append("<th>Lane No.</th>"); b.append("<th>Pool</th>"); b.append("<tr><td>1 </td><td width='90%'><div id='p_div-0'><ul class='runPartitionDroppable' bind='partitions[0].pool' partition='0' ondblclick='Container.partition.populatePartition(this);'></ul></div></td></tr>"); b.append("<tr><td>2 </td><td width='90%'><div id='p_div-1'><ul class='runPartitionDroppable' bind='partitions[1].pool' partition='1' ondblclick='Container.partition.populatePartition(this);'></ul></div></td></tr>"); b.append("<tr><td>3 </td><td width='90%'><div id='p_div-2'><ul class='runPartitionDroppable' bind='partitions[2].pool' partition='2' ondblclick='Container.partition.populatePartition(this);'></ul></div></td></tr>"); b.append("<tr><td>4 </td><td width='90%'><div id='p_div-3'><ul class='runPartitionDroppable' bind='partitions[3].pool' partition='3' ondblclick='Container.partition.populatePartition(this);'></ul></div></td></tr>"); b.append("<tr><td>5 </td><td width='90%'><div id='p_div-4'><ul class='runPartitionDroppable' bind='partitions[4].pool' partition='4' ondblclick='Container.partition.populatePartition(this);'></ul></div></td></tr>"); b.append("<tr><td>6 </td><td width='90%'><div id='p_div-5'><ul class='runPartitionDroppable' bind='partitions[5].pool' partition='5' ondblclick='Container.partition.populatePartition(this);'></ul></div></td></tr>"); b.append("<tr><td>7 </td><td width='90%'><div id='p_div-6'><ul class='runPartitionDroppable' bind='partitions[6].pool' partition='6' ondblclick='Container.partition.populatePartition(this);'></ul></div></td></tr>"); b.append("<tr><td>8 </td><td width='90%'><div id='p_div-7'><ul class='runPartitionDroppable' bind='partitions[7].pool' partition='7' ondblclick='Container.partition.populatePartition(this);'></ul></div></td></tr>"); b.append("</table>"); b.append("</div>"); SequencerPartitionContainer<SequencerPoolPartition> lf = (SequencerPartitionContainer<SequencerPoolPartition>) session.getAttribute("container_" + json.getString("container_cId")); lf.setPlatform(sr.getPlatform()); lf.setPartitionLimit(8); lf.initEmptyPartitions(); } b.append("<div id='containerdiv0'> </div>"); b.append("</div>"); return JSONUtils.SimpleJSONResponse(b.toString()); } catch (IOException e) { e.printStackTrace(); return JSONUtils.SimpleJSONError("No sequencer reference defined"); } } public JSONObject changeLS454Container(HttpSession session, JSONObject json) { StringBuilder b = new StringBuilder(); b.append("<h2>Container</h2>"); b.append("<table class='in'>"); b.append("<tr><td>ID:</td><td><input type='text' id='identificationBarcode' name='identificationBarcode'/><input type='hidden' value='on' name='_identificationBarcode'><button onclick='Container.lookupContainer(this);' type='button' class='right-button ui-state-default ui-corner-all'>Lookup</button></td></tr>"); b.append("<tr><td>Location:</td><td><input type='text' id='locationBarcode' name='locationBarcode'/><input type='hidden' value='on' name='_locationBarcode'></td></tr>"); b.append("<tr><td>Validation:</td><td><input type='text' id='validationBarcode' name='validationBarcode'/><input type='hidden' value='on' name='_validationBarcode'></td></tr>"); b.append("<tr><td>Paired:</td><td><input type='checkbox' id='paired' name='paired'/><input type='hidden' value='on' name='_paired'></td></tr>"); b.append("</table>"); b.append("<div id='partitionErrorDiv'> </div>"); b.append("<div id='partitionDiv'>"); b.append("<input id='chamber1' name='container0Select' onchange='Container.ui.changeContainerLS454Chamber(this, 0);' type='radio' value='1'/>1 "); b.append("<input id='chamber2' name='container0Select' onchange='Container.ui.changeContainerLS454Chamber(this, 0);' type='radio' value='2'/>2 "); b.append("<input id='chamber4' name='container0Select' onchange='Container.ui.changeContainerLS454Chamber(this, 0);' type='radio' value='4'/>4 "); b.append("<input id='chamber8' name='container0Select' onchange='Container.ui.changeContainerLS454Chamber(this, 0);' type='radio' value='8'/>8 "); b.append("<input id='chamber16' name='container0Select' onchange='Container.ui.changeContainerLS454Chamber(this, 0);' type='radio' value='16'/>16<br/>"); b.append("<div id='containerdiv0'> </div>"); b.append("</div>"); return JSONUtils.SimpleJSONResponse(b.toString()); } public JSONObject changeSolidContainer(HttpSession session, JSONObject json) { long seqRefId = json.getLong("sequencerReferenceId"); StringBuilder b = new StringBuilder(); try { SequencerReference sr = requestManager.getSequencerReferenceById(seqRefId); b.append("<h2>Container</h2>"); b.append("<table class='in'>"); b.append("<tr><td>ID:</td><td><button onclick='Container.lookupContainer(this);' type='button' class='right-button ui-state-default ui-corner-all'>Lookup</button><div style='overflow:hidden'><input type='text' id='identificationBarcode' name='identificationBarcode'/><input type='hidden' value='on' name='_identificationBarcode'></div></td></tr>"); b.append("<tr><td>Location:</td><td><input type='text' id='locationBarcode' name='locationBarcode'/><input type='hidden' value='on' name='_locationBarcode'></td></tr>"); b.append("<tr><td>Validation:</td><td><input type='text' id='validationBarcode' name='validationBarcode'/><input type='hidden' value='on' name='_validationBarcode'></td></tr>"); b.append("<tr><td>Paired:</td><td><input type='checkbox' id='paired' name='paired'/><input type='hidden' value='on' name='_paired'></td></tr>"); b.append("</table>"); b.append("<div id='partitionErrorDiv'> </div>"); b.append("<div id='partitionDiv'>"); if ("AB SOLiD 5500xl".equals(sr.getPlatform().getInstrumentModel())) { b.append("<table class='in'>"); b.append("<th>Chamber No.</th>"); b.append("<th>Pool</th>"); b.append("<tr><td>1 </td><td width='90%'><div id='p_div_0-0' class='barcodeEntryDiv'><ul class='runPartitionDroppable' bind='partitions[0].pool' partition='0' ondblclick='Container.partition.populatePartition(this);'></ul></div></td></tr>"); b.append("<tr><td>2 </td><td width='90%'><div id='p_div_0-1' class='barcodeEntryDiv'><ul class='runPartitionDroppable' bind='partitions[1].pool' partition='1' ondblclick='Container.partition.populatePartition(this);'></ul></div></td></tr>"); b.append("<tr><td>3 </td><td width='90%'><div id='p_div_0-2' class='barcodeEntryDiv'><ul class='runPartitionDroppable' bind='partitions[2].pool' partition='2' ondblclick='Container.partition.populatePartition(this);'></ul></div></td></tr>"); b.append("<tr><td>4 </td><td width='90%'><div id='p_div_0-3' class='barcodeEntryDiv'><ul class='runPartitionDroppable' bind='partitions[3].pool' partition='3' ondblclick='Container.partition.populatePartition(this);'></ul></div></td></tr>"); b.append("<tr><td>5 </td><td width='90%'><div id='p_div_0-4' class='barcodeEntryDiv'><ul class='runPartitionDroppable' bind='partitions[4].pool' partition='4' ondblclick='Container.partition.populatePartition(this);'></ul></div></td></tr>"); b.append("<tr><td>6 </td><td width='90%'><div id='p_div_0-5' class='barcodeEntryDiv'><ul class='runPartitionDroppable' bind='partitions[5].pool' partition='5' ondblclick='Container.partition.populatePartition(this);'></ul></div></td></tr>"); b.append("</table>"); SequencerPartitionContainer<SequencerPoolPartition> lf = (SequencerPartitionContainer<SequencerPoolPartition>) session.getAttribute("container_" + json.getString("container_cId")); lf.setPartitionLimit(6); lf.initEmptyPartitions(); session.setAttribute("container_" + json.getString("container_cId"), lf); } else { b.append("<input id='chamber1' name='container0Select' onchange='Container.ui.changeContainerSolidChamber(this, 0);' type='radio' value='1'/>1 "); b.append("<input id='chamber4' name='container0Select' onchange='Container.ui.changeContainerSolidChamber(this, 0);' type='radio' value='4'/>4 "); b.append("<input id='chamber8' name='container0Select' onchange='Container.ui.changeContainerSolidChamber(this, 0);' type='radio' value='8'/>8 "); b.append("<input id='chamber16' name='container0Select' onchange='Container.ui.changeContainerSolidChamber(this, 0);' type='radio' value='16'/>16<br/>"); } b.append("<div id='containerdiv0'> </div>"); b.append("</div>"); return JSONUtils.SimpleJSONResponse(b.toString()); } catch (IOException e) { e.printStackTrace(); return JSONUtils.SimpleJSONError("No sequencer reference defined"); } } public JSONObject changePacBioContainer(HttpSession session, JSONObject json) { StringBuilder b = new StringBuilder(); b.append("<h2>Container</h2>"); b.append("<table class='in'>"); b.append("<tr><td>ID:</td><td><input type='text' id='identificationBarcode' name='identificationBarcode'/><input type='hidden' value='on' name='_identificationBarcode'><button onclick='Container.lookupContainer(this);' type='button' class='right-button ui-state-default ui-corner-all'>Lookup</button></td></tr>"); b.append("<tr><td>Location:</td><td><input type='text' id='locationBarcode' name='locationBarcode'/><input type='hidden' value='on' name='_locationBarcode'></td></tr>"); b.append("<tr><td>Validation:</td><td><input type='text' id='validationBarcode' name='validationBarcode'/><input type='hidden' value='on' name='_validationBarcode'></td></tr>"); b.append("<tr><td>Paired:</td><td><input type='checkbox' id='paired' name='paired'/><input type='hidden' value='on' name='_paired'></td></tr>"); b.append("</table>"); b.append("<div id='partitionErrorDiv'> </div>"); b.append("<div id='partitionDiv'>"); b.append("<input id='chamber1' name='container0Select' onchange='Container.ui.changeContainerPacBioChamber(this, 0);' type='radio' value='1'/>1 "); b.append("<input id='chamber2' name='container0Select' onchange='Container.ui.changeContainerPacBioChamber(this, 0);' type='radio' value='2'/>2 "); b.append("<input id='chamber3' name='container0Select' onchange='Container.ui.changeContainerPacBioChamber(this, 0);' type='radio' value='3'/>3 "); b.append("<input id='chamber4' name='container0Select' onchange='Container.ui.changeContainerPacBioChamber(this, 0);' type='radio' value='4'/>4 "); b.append("<input id='chamber5' name='container0Select' onchange='Container.ui.changeContainerPacBioChamber(this, 0);' type='radio' value='5'/>5 "); b.append("<input id='chamber6' name='container0Select' onchange='Container.ui.changeContainerPacBioChamber(this, 0);' type='radio' value='6'/>6 "); b.append("<input id='chamber7' name='container0Select' onchange='Container.ui.changeContainerPacBioChamber(this, 0);' type='radio' value='7'/>7 "); b.append("<input id='chamber8' name='container0Select' onchange='Container.ui.changeContainerPacBioChamber(this, 0);' type='radio' value='8'/>8<br/>"); b.append("<div id='containerdiv0'> </div>"); b.append("</div>"); return JSONUtils.SimpleJSONResponse(b.toString()); } public JSONObject changeChamber(HttpSession session, JSONObject json) { if (json.has("platform")) { String platform = json.getString("platform"); PlatformType pt = PlatformType.get(platform); if (pt != null) { if (pt.equals(PlatformType.LS454)) { return changeLS454Chamber(session, json); } else if (pt.equals(PlatformType.SOLID)) { return changeSolidChamber(session, json); } else if (pt.equals(PlatformType.PACBIO)) { return changePacBioChamber(session, json); } else { return JSONUtils.SimpleJSONError("Unrecognised platform type: " + platform); } } } return JSONUtils.SimpleJSONError("No platform specified"); } public JSONObject changeIlluminaLane(HttpSession session, JSONObject json) { int numLanes = json.getInt("numLanes"); int container = json.getInt("container"); StringBuilder b = new StringBuilder(); b.append("<i class='italicInfo'>Click in a partition box to beep/type in barcodes, or double click a pool on the right to sequentially add pools to the container</i>"); b.append("<table class='in'>"); b.append("<th>Lane No.</th>"); b.append("<th>Pool</th>"); SequencerPartitionContainer<SequencerPoolPartition> lf = (SequencerPartitionContainer<SequencerPoolPartition>) session.getAttribute("container_" + json.getString("container_cId")); lf.setPartitionLimit(numLanes); lf.initEmptyPartitions(); session.setAttribute("container_" + json.getString("container_cId"), lf); for (int i = 0; i < numLanes; i++) { b.append("<tr><td>" + (i + 1) + "</td>"); b.append("<td width='90%'><div id='p_div_" + container + "-" + i + "' class='elementListDroppableDiv'><ul class='runPartitionDroppable' bind='partitions[" + i + "].pool' partition='" + i + "' ondblclick='Container.partition.populatePartition(this);'>"); b.append("</ul></div></td>"); b.append("</tr>"); } b.append("</table>"); return JSONUtils.SimpleJSONResponse(b.toString()); } public JSONObject changeLS454Chamber(HttpSession session, JSONObject json) { int numChambers = json.getInt("numChambers"); int container = json.getInt("container"); StringBuilder b = new StringBuilder(); b.append("<i class='italicInfo'>Click in a partition box to beep/type in barcodes, or double click a pool on the right to sequentially add pools to the container</i>"); b.append("<table class='in'>"); b.append("<th>Chamber No.</th>"); b.append("<th>Pool</th>"); SequencerPartitionContainer<SequencerPoolPartition> lf = (SequencerPartitionContainer<SequencerPoolPartition>) session.getAttribute("container_" + json.getString("container_cId")); lf.setPartitionLimit(numChambers); lf.initEmptyPartitions(); session.setAttribute("container_" + json.getString("container_cId"), lf); for (int i = 0; i < numChambers; i++) { b.append("<tr><td>" + (i + 1) + "</td>"); b.append("<td width='90%'><div id='p_div_" + container + "-" + i + "' class='elementListDroppableDiv'><ul class='runPartitionDroppable' bind='partitions[" + i + "].pool' partition='" + i + "' ondblclick='Container.partition.populatePartition(this);'>"); b.append("</ul></div></td>"); b.append("</tr>"); } b.append("</table>"); return JSONUtils.SimpleJSONResponse(b.toString()); } public JSONObject changeSolidChamber(HttpSession session, JSONObject json) { int numChambers = json.getInt("numChambers"); int container = json.getInt("container"); StringBuilder b = new StringBuilder(); b.append("<i class='italicInfo'>Click in a partition box to beep/type in barcodes, or double click a pool on the right to sequentially add pools to the container</i>"); b.append("<table class='in'>"); b.append("<th>Chamber No.</th>"); b.append("<th>Pool</th>"); SequencerPartitionContainer<SequencerPoolPartition> lf = (SequencerPartitionContainer<SequencerPoolPartition>) session.getAttribute("container_" + json.getString("container_cId")); lf.setPartitionLimit(numChambers); lf.initEmptyPartitions(); session.setAttribute("container_" + json.getString("container_cId"), lf); for (int i = 0; i < numChambers; i++) { b.append("<tr><td>" + (i + 1) + "</td>"); b.append("<td width='90%'><div id='p_div_" + container + "-" + i + "' class='elementListDroppableDiv'><ul class='runPartitionDroppable' bind='partitions[" + i + "].pool' partition='" + i + "' ondblclick='Container.partition.populatePartition(this);'>"); b.append("</ul></div></td>"); b.append("</tr>"); } b.append("</table>"); return JSONUtils.SimpleJSONResponse(b.toString()); } public JSONObject changePacBioChamber(HttpSession session, JSONObject json) { int numChambers = json.getInt("numChambers"); int container = json.getInt("container"); StringBuilder b = new StringBuilder(); b.append("<i class='italicInfo'>Click in a partition box to beep/type in barcodes, or double click a pool on the right to sequentially add pools to the container</i>"); b.append("<table class='in'>"); b.append("<th>Chamber No.</th>"); b.append("<th>Pool</th>"); SequencerPartitionContainer<SequencerPoolPartition> lf = (SequencerPartitionContainer<SequencerPoolPartition>) session.getAttribute("container_" + json.getString("container_cId")); lf.setPartitionLimit(numChambers); lf.initEmptyPartitions(); session.setAttribute("container_" + json.getString("container_cId"), lf); for (int i = 0; i < numChambers; i++) { b.append("<tr><td>" + (i + 1) + "</td>"); b.append("<td width='90%'><div id='p_div_" + container + "-" + i + "' class='elementListDroppableDiv'><ul class='runPartitionDroppable' bind='partitions[" + i + "].pool' partition='" + i + "' ondblclick='Container.partition.populatePartition(this);'>"); b.append("</tr>"); } b.append("</table>"); return JSONUtils.SimpleJSONResponse(b.toString()); } public JSONObject getPoolByBarcode(HttpSession session, JSONObject json) { String barcode = json.getString("barcode"); int partition = json.getInt("partition"); try { if (barcode != null && !"".equals(barcode)) { if (LimsUtils.isBase64String(barcode)) { //Base64-encoded string, most likely a barcode image beeped in. decode and search barcode = new String(Base64.decodeBase64(barcode)); } } Pool p = requestManager.getPoolByBarcode(barcode); SequencerPartitionContainer<SequencerPoolPartition> lf = (SequencerPartitionContainer<SequencerPoolPartition>) session.getAttribute("container_" + json.getString("container_cId")); //if (lf.getPlatformType().equals(p.getPlatformType())) { if (lf.getPlatform().getPlatformType().equals(p.getPlatformType())) { return JSONUtils.JSONObjectResponse("html", poolHtml(p, partition)); } else { return JSONUtils.JSONObjectResponse("err", "Error: pool platform does not match container platform"); } } catch (IOException e) { e.printStackTrace(); return JSONUtils.JSONObjectResponse("err", "Error: no such pool"); } } public JSONObject checkPoolExperiment(HttpSession session, JSONObject json) { try { String partition = json.getString("partition"); Long poolId = json.getLong("poolId"); Pool<? extends Poolable> p = requestManager.getPoolById(poolId); StringBuilder sb = new StringBuilder(); Set<Project> pooledProjects = new HashSet<Project>(); if (p.getExperiments().size() != 0) { //check if each poolable has been in a study for this pool already Collection<? extends Poolable> ds = p.getPoolableElements(); for (Poolable d : ds) { if (d instanceof Dilution) { Collection<Study> studies = requestManager.listAllStudiesByLibraryId(((Dilution)d).getLibrary().getId()); if (studies.isEmpty()) { pooledProjects.add(((Dilution)d).getLibrary().getSample().getProject()); } else { for (Study stu : studies) { pooledProjects.add(stu.getProject()); } } } else if (d instanceof Plate) { Plate plate = (Plate)d; if (!plate.getElements().isEmpty()) { if (plate.getElementType().equals(Library.class)) { Library l = (Library)plate.getElements().get(0); Collection<Study> studies = requestManager.listAllStudiesByLibraryId(l.getId()); if (studies.isEmpty()) { pooledProjects.add(l.getSample().getProject()); } else { for (Study stu : studies) { pooledProjects.add(stu.getProject()); } } } } } } for (Experiment poolExp : p.getExperiments()) { Project expProject = poolExp.getStudy().getProject(); if (pooledProjects.contains(expProject)) { pooledProjects.remove(expProject); } } } else { Collection<? extends Poolable> ds = p.getPoolableElements(); for (Poolable d : ds) { if (d instanceof Dilution) { pooledProjects.add(((Dilution)d).getLibrary().getSample().getProject()); } else if (d instanceof Plate) { Plate plate = (Plate)d; if (!plate.getElements().isEmpty()) { if (plate.getElementType().equals(Library.class)) { Library l = (Library)plate.getElements().get(0); pooledProjects.add(l.getSample().getProject()); } } } } } sb.append("<div style='float:left; clear:both'>"); for (Project project : pooledProjects) { sb.append("<div id='studySelectDiv" + partition + "_" + project.getProjectId() + "'>"); sb.append(project.getAlias() + ": <select name='poolStudies" + partition + "_" + project.getProjectId() + "' id='poolStudies" + partition + "_" + project.getProjectId() + "'>"); Collection<Study> studies = requestManager.listAllStudiesByProjectId(project.getProjectId()); if (studies.isEmpty()) { //throw new Exception("No studies available on project " + project.getName() + ". At least one study must be available for each project associated with this Pool."); return JSONUtils.SimpleJSONError("No studies available on project " + project.getName() + ". At least one study must be available for each project associated with this Pool."); } else { for (Study s : studies) { sb.append("<option value='" + s.getId() + "'>" + s.getName() + " - " + s.getStudyType() + "</option>"); } } sb.append("</select>"); sb.append("<input id='studySelectButton-" + partition + "_" + p.getId() + "' type='button' onclick=\"Container.partition.selectContainerStudy('" + partition + "', " + p.getId() + "," + project.getProjectId() + ");\" class=\"ui-state-default ui-corner-all\" value='Select Study'/>"); sb.append("</div><br/>"); } sb.append("</div>"); //} return JSONUtils.JSONObjectResponse("html", sb.toString()); } catch (Exception e) { e.printStackTrace(); return JSONUtils.SimpleJSONError(e.getMessage()); } } private String poolHtml(Pool<? extends Poolable> p, int partition) { StringBuilder b = new StringBuilder(); try { b.append("<div style='position:relative' onMouseOver='this.className=\"dashboardhighlight\"' onMouseOut='this.className=\"dashboard\"' class='dashboard'>"); if (LimsUtils.isStringEmptyOrNull(p.getAlias())) { b.append("<div style=\"float:left\"><b>" + p.getName() + " : "+p.getCreationDate()+"</b><br/>"); } else { b.append("<div style=\"float:left\"><b>" + p.getName() + " (" + p.getAlias() + ") : "+p.getCreationDate()+"</b><br/>"); } Collection<? extends Poolable> ds = p.getPoolableElements(); Set<Project> pooledProjects = new HashSet<Project>(); for (Poolable d : ds) { if (d instanceof Dilution) { pooledProjects.add(((Dilution)d).getLibrary().getSample().getProject()); b.append("<span>" + d.getName() + " (" + ((Dilution)d).getLibrary().getSample().getProject().getAlias() + ") : "+((Dilution) d).getConcentration()+" "+((Dilution) d).getUnits()+"</span><br/>"); } else if (d instanceof Plate) { Plate<LinkedList<Plateable>, Plateable> plate = (Plate<LinkedList<Plateable>, Plateable>)d; if (!plate.getElements().isEmpty()) { //TODO - should we look through all plate elements to get all projects? Plateable element = plate.getElements().getFirst(); if (element instanceof Library) { Library l = (Library)element; pooledProjects.add(l.getSample().getProject()); b.append("<span>" + d.getName() + " ["+plate.getSize()+"-well] (" + l.getSample().getProject().getAlias() + ")</span><br/>"); } else if (element instanceof Dilution) { Dilution dl = (Dilution)element; b.append("<span>" + dl.getName() + " ["+plate.getSize()+"-well] (" + dl.getLibrary().getSample().getProject().getAlias() + ")</span><br/>"); } else if (element instanceof Sample) { Sample s = (Sample)element; b.append("<span>" + s.getName() + " ["+plate.getSize()+"-well] (" + s.getProject().getAlias() + ")</span><br/>"); } } } else { b.append("<span>" + d.getName() + "</span><br/>"); } } b.append("<br/><i>"); Collection<Experiment> exprs = p.getExperiments(); for (Experiment e : exprs) { b.append("<span>" + e.getStudy().getProject().getAlias() + "(" + e.getName() + ": " + p.getDilutions().size() + " dilutions)</span><br/>"); } b.append("</i>"); if (p.getExperiments().size() == 0) { b.append("<div style='float:left; clear:both'>"); for (Project project : pooledProjects) { b.append("<div id='studySelectDiv" + partition + "_" + project.getProjectId() + "'>"); b.append(project.getAlias() + ": <select name='poolStudies" + partition + "_" + project.getProjectId() + "' id='poolStudies" + partition + "_" + project.getProjectId() + "'>"); Collection<Study> studies = requestManager.listAllStudiesByProjectId(project.getProjectId()); if (studies.isEmpty()) { throw new Exception("No studies available on project " + project.getName() + ". At least one study must be available for each project associated with this Pool."); } else { for (Study s : studies) { b.append("<option value='" + s.getId() + "'>" + s.getAlias() + " (" + s.getName() + " - " + s.getStudyType() + ")</option>"); } } b.append("</select>"); b.append("<input id='studySelectButton-" + partition + "_" + p.getId() + "' type='button' onclick=\"Container.partition.selectContainerStudy('" + partition + "', " + p.getId() + "," + project.getProjectId() + ");\" class=\"ui-state-default ui-corner-all\" value='Select Study'/>"); b.append("</div><br/>"); } b.append("</div>"); } b.append("<input type='hidden' name='partitions[" + partition + "].pool' id='pId" + p.getId() + "' value='" + p.getId() + "'/></div>"); b.append("<div style='position: absolute; bottom: 0; right: 0; font-size: 24px; font-weight: bold; color:#BBBBBB'>" + p.getPlatformType().getKey() + "</div>"); b.append("<span style='position: absolute; top: 0; right: 0;' onclick='Container.pool.confirmPoolRemove(this);' class='float-right ui-icon ui-icon-circle-close'></span>"); b.append("</div>"); } catch (IOException e) { e.printStackTrace(); return "Cannot get studies for pool: " + e.getMessage(); } catch (Exception e) { e.printStackTrace(); return "Cannot get studies for pool: " + e.getMessage(); } return b.toString(); } public JSONObject selectStudyForPool(HttpSession session, JSONObject json) { try { Long poolId = json.getLong("poolId"); Pool p = requestManager.getPoolById(poolId); if (p == null) { throw new Exception("Could not retrieve pool: " + poolId); }; Long studyId = json.getLong("studyId"); Study s = requestManager.getStudyById(studyId); if (s == null) { throw new Exception("Could not retrieve study: " + studyId); }; //Long sequencerReferenceId = json.getLong("sequencerReferenceId"); //SequencerReference sr = requestManager.getSequencerReferenceById(sequencerReferenceId); //if (sr == null) { throw new Exception("Could not retrieve sequencer: " + sequencerReferenceId); }; Long platformId = json.getLong("platformId"); Platform platform = requestManager.getPlatformById(platformId); if (platform == null) { throw new Exception("Could not retrieve Platform:" + platformId); }; StringBuilder sb = new StringBuilder(); Experiment e = dataObjectFactory.getExperiment(); e.setAlias("EXP_AUTOGEN_" + s.getName() + "_" + s.getStudyType() + "_" + (s.getExperiments().size() + 1)); e.setTitle(s.getProject().getName() + " " + platform.getPlatformType().getKey() + " " + s.getStudyType() + " experiment (Auto-gen)"); e.setDescription(s.getProject().getAlias()); e.setPlatform(platform); e.setStudy(s); e.setSecurityProfile(s.getSecurityProfile()); try { p.addExperiment(e); requestManager.saveExperiment(e); } catch (MalformedExperimentException e1) { e1.printStackTrace(); return JSONUtils.SimpleJSONError("Failed to save experiment: " + e1.getMessage()); } sb.append("<i>"); sb.append("<span>" + s.getProject().getAlias() + " (" + e.getName() + ": " + p.getDilutions().size() + " dilutions)</span><br/>"); sb.append("</i>"); return JSONUtils.JSONObjectResponse("html", sb.toString()); } catch (Exception e) { e.printStackTrace(); return JSONUtils.SimpleJSONError("Failed " + e.getMessage()); } } public JSONObject lookupContainer(HttpSession session, JSONObject json) { if (json.has("barcode") && !"".equals(json.getString("barcode"))) { try { String barcode = json.getString("barcode"); Collection<SequencerPartitionContainer<SequencerPoolPartition>> fs = requestManager.listSequencerPartitionContainersByBarcode(barcode); if (!fs.isEmpty()) { JSONObject confirm = new JSONObject(); StringBuilder sb = new StringBuilder(); if (fs.size() == 1) { //replace container div SequencerPartitionContainer<SequencerPoolPartition> f = new ArrayList<>(fs).get(0); sb.append("<table class='in'>"); sb.append("<th>Partition No.</th>"); sb.append("<th>Pool</th>"); if (f.getPartitions().isEmpty()) { //something went wrong previously. a saved container shouldn't have empty partitions - recreate json.put("platform", f.getPlatform().getPlatformType().getKey()); session.setAttribute("container_" + json.getString("container_cId"), f); //reset container changeContainer(session, json); } else if (f.getPartitions() == null) { //something went wrong previously. a saved container shouldn't have null partition set - recreate f.setPartitions(new AutoPopulatingList<SequencerPoolPartition>(PartitionImpl.class)); json.put("platform", f.getPlatform().getPlatformType().getKey()); session.setAttribute("container_" + json.getString("container_cId"), f); //reset container changeContainer(session, json); } for (SequencerPoolPartition p : f.getPartitions()) { sb.append("<tr>"); sb.append("<td>" + p.getPartitionNumber() + "</td>"); sb.append("<td width='90%'>"); if (p.getPool() != null) { confirm.put(p.getPartitionNumber(), p.getPool().getName()); sb.append("<ul partition='" + (p.getPartitionNumber() - 1) + "' bind='partitions[" + (p.getPartitionNumber() - 1) + "].pool' class='runPartitionDroppable'>"); sb.append("<div class='dashboard'>"); sb.append(p.getPool().getName()); sb.append("(" + p.getPool().getCreationDate() + ")<br/>"); sb.append("<span style='font-size:8pt'>"); if (!p.getPool().getExperiments().isEmpty()) { sb.append("<i>"); for (Experiment e : p.getPool().getExperiments()) { sb.append(e.getStudy().getProject().getAlias() + " (" + e.getName() + ": " + p.getPool().getDilutions().size() + " dilutions)<br/>"); } sb.append("</i>"); sb.append("<input type='hidden' name='partitions[" + (p.getPartitionNumber() - 1) + "].pool' id='pId" + (p.getPartitionNumber() - 1) + "' value='" + p.getPool().getId() + "'/>"); } else { sb.append("<i>No experiment linked to this pool</i>"); } sb.append("</span>"); sb.append("</div>"); sb.append("</ul>"); } else { confirm.put(p.getPartitionNumber(), "Empty"); sb.append("<div id='p_div-" + (p.getPartitionNumber() - 1) + "' class='elementListDroppableDiv'>"); sb.append("<ul class='runPartitionDroppable' bind='partitions[" + (p.getPartitionNumber() - 1) + "].pool' partition='" + (p.getPartitionNumber() - 1) + "' ondblclick='Container.partition.populatePartition(this);'></ul>"); sb.append("</div>"); } sb.append("</td>"); sb.append("</tr>"); } sb.append("</table>"); Map<String, Object> responseMap = new HashMap<String, Object>(); responseMap.put("html", sb.toString()); responseMap.put("barcode", f.getIdentificationBarcode()); responseMap.put("containerId", f.getId()); responseMap.put("verify", confirm); return JSONUtils.JSONObjectResponse(responseMap); } else { //choose container //return JSONUtils.JSONObjectResponse("error", "Multiple containers found with barcode "+ barcode); return JSONUtils.SimpleJSONError("Multiple containers found with barcode " + barcode); } } else { return JSONUtils.JSONObjectResponse("error", "No containers with this barcode."); } } catch (IOException e) { e.printStackTrace(); return JSONUtils.JSONObjectResponse("error", "Unable to lookup barcode."); } } else { return JSONUtils.SimpleJSONError("Please supply a barcode to lookup."); } } public JSONObject listSequencePartitionContainersDataTable(HttpSession session, JSONObject json) { try { JSONObject j = new JSONObject(); JSONArray jsonArray = new JSONArray(); for (SequencerPartitionContainer<SequencerPoolPartition> sequencePartitionContainer : requestManager.listAllSequencerPartitionContainers()) { String run = ""; String sequencer = ""; if (sequencePartitionContainer.getRun() != null) { run = "<a href=\"/miso/run/" + sequencePartitionContainer.getRun().getId() + "\">" + sequencePartitionContainer.getRun().getAlias() + "</a>"; if (sequencePartitionContainer.getRun().getSequencerReference() != null) { sequencer = "<a href=\"/miso/sequencer/" + sequencePartitionContainer.getRun().getSequencerReference().getId() + "\">" + sequencePartitionContainer.getRun().getSequencerReference().getPlatform().getNameAndModel() + "</a>"; } } jsonArray.add("['" + (sequencePartitionContainer.getIdentificationBarcode() != null ? sequencePartitionContainer.getIdentificationBarcode() : "") + "','" + (sequencePartitionContainer.getPlatform() != null && sequencePartitionContainer.getPlatform().getPlatformType() != null ? sequencePartitionContainer.getPlatform().getPlatformType().getKey() : "") + "','" + run + "','" + sequencer + "','" + "<a href=\"/miso/container/" + sequencePartitionContainer.getId() + "\"><span class=\"ui-icon ui-icon-pencil\"></span></a>" + "']"); } j.put("array", jsonArray); return j; } catch (IOException e) { log.debug("Failed", e); return JSONUtils.SimpleJSONError("Failed: " + e.getMessage()); } } public JSONObject removePoolFromPartition(HttpSession session, JSONObject json) { if (json.has("container_cId") && json.has("partitionNum")) { Integer partitionNum = json.getInt("partitionNum"); SequencerPartitionContainer<SequencerPoolPartition> lf = (SequencerPartitionContainer<SequencerPoolPartition>) session.getAttribute("container_" + json.getString("container_cId")); SequencerPoolPartition spp = lf.getPartitionAt(partitionNum); spp.setPool(null); session.setAttribute("container_" + json.getString("container_cId"), lf); return JSONUtils.SimpleJSONResponse("OK"); } else { return JSONUtils.SimpleJSONError("No partitionId specified"); } } public JSONObject checkContainer(HttpSession session, JSONObject json) { try { if (json.has("containerId")) { Long containerId = json.getLong("containerId"); SequencerPartitionContainer container = requestManager.getSequencerPartitionContainerById(containerId); if (container.getRun() != null && "Completed".equals(container.getRun().getStatus().getHealth().getKey())) { return JSONUtils.SimpleJSONResponse("yes"); } else { return JSONUtils.SimpleJSONResponse("no"); } } else { return JSONUtils.SimpleJSONError("No Sequencer Partition Container specified"); } } catch (IOException e) { e.printStackTrace(); return JSONUtils.SimpleJSONError("Error getting currently logged in user."); } } public JSONObject deleteContainer(HttpSession session, JSONObject json) { User user; try { user = securityManager.getUserByLoginName(SecurityContextHolder.getContext().getAuthentication().getName()); } catch (IOException e) { e.printStackTrace(); return JSONUtils.SimpleJSONError("Error getting currently logged in user."); } if (user != null && user.isAdmin()) { if (json.has("containerId")) { Long containerId = json.getLong("containerId"); try { SequencerPartitionContainer container = requestManager.getSequencerPartitionContainerById(containerId); requestManager.deleteContainer(container); return JSONUtils.SimpleJSONResponse("Sequencer Partition Container deleted"); } catch (IOException e) { e.printStackTrace(); return JSONUtils.SimpleJSONError("Cannot delete Sequencer Partition Container: " + e.getMessage()); } } else { return JSONUtils.SimpleJSONError("No Sequencer Partition Container specified to delete."); } } else { return JSONUtils.SimpleJSONError("Only admins can delete objects."); } } public void setSecurityManager(SecurityManager securityManager) { this.securityManager = securityManager; } public void setRequestManager(RequestManager requestManager) { this.requestManager = requestManager; } public void setDataObjectFactory(DataObjectFactory dataObjectFactory) { this.dataObjectFactory = dataObjectFactory; } }