/*
* 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.Note;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import uk.ac.bbsrc.tgac.miso.core.data.*;
import uk.ac.bbsrc.tgac.miso.core.data.impl.*;
import uk.ac.bbsrc.tgac.miso.core.data.type.LibrarySelectionType;
import uk.ac.bbsrc.tgac.miso.core.data.type.LibraryStrategyType;
import uk.ac.bbsrc.tgac.miso.core.data.type.LibraryType;
import uk.ac.bbsrc.tgac.miso.core.data.type.PlatformType;
import uk.ac.bbsrc.tgac.miso.core.exception.InputFormException;
import uk.ac.bbsrc.tgac.miso.core.manager.MisoFilesManager;
import uk.ac.bbsrc.tgac.miso.core.manager.RequestManager;
import uk.ac.bbsrc.tgac.miso.core.service.tagbarcode.TagBarcodeStrategy;
import uk.ac.bbsrc.tgac.miso.core.service.tagbarcode.TagBarcodeStrategyResolverService;
import uk.ac.bbsrc.tgac.miso.core.util.FormUtils;
import uk.ac.bbsrc.tgac.miso.core.util.LimsUtils;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* uk.ac.bbsrc.tgac.miso.spring.ajax
* <p/>
* Info
*
* @author Rob Davey
* @since 0.1.2
*/
@Ajaxified
public class ImportExportControllerHelperService {
protected static final Logger log = LoggerFactory.getLogger(ImportExportControllerHelperService.class);
@Autowired
private RequestManager requestManager;
@Autowired
private MisoFilesManager misoFileManager;
@Autowired
private SecurityManager securityManager;
@Autowired
private TagBarcodeStrategyResolverService tagBarcodeStrategyResolverService;
private static final Pattern digitPattern = Pattern.compile("(^[0-9]+)[\\.0-9]*");
public JSONObject searchSamples(HttpSession session, JSONObject json) {
String searchStr = json.getString("str");
try {
List<Sample> samples;
StringBuilder b = new StringBuilder();
if (!"".equals(searchStr)) {
samples = new ArrayList<Sample>(requestManager.listAllSamplesBySearch(searchStr));
}
else {
samples = new ArrayList<Sample>(requestManager.listAllSamplesWithLimit(250));
}
if (samples.size() > 0) {
Collections.sort(samples);
for (Sample s : samples) {
String dnaOrRNA = "O";
if ("GENOMIC".equals(s.getSampleType())
|| "METAGENOMIC".equals(s.getSampleType())) {
dnaOrRNA = "D";
}
else if ("NON GENOMIC".equals(s.getSampleType())
|| "VIRAL RNA".equals(s.getSampleType())
|| "TRANSCRIPTOMIC".equals(s.getSampleType())
|| "METATRANSCRIPTOMIC".equals(s.getSampleType())) {
dnaOrRNA = "R";
}
b.append("<div id=\"sample" + s.getId() + "\" onMouseOver=\"this.className='dashboardhighlight'\" onMouseOut=\"this.className='dashboard'\" "
+ " " + "class=\"dashboard\">");
b.append("<input type=\"hidden\" id=\"" + s.getId() + "\" name=\"" + s.getName() + "\" projectname=\"" + s.getProject().getName() + "\" projectalias=\"" + s.getProject().getAlias() + "\" samplealias=\"" + s.getAlias() + "\" dnaOrRNA=\"" + dnaOrRNA + "\"/>");
b.append("Name: <b>" + s.getName() + "</b><br/>");
b.append("Alias: <b>" + s.getAlias() + "</b><br/>");
b.append("From Project: <b>" + s.getProject().getName() + "</b><br/>");
b.append("<button type=\"button\" class=\"fg-button ui-state-default ui-corner-all\" onclick=\"ImportExport.insertSampleNextAvailable(jQuery('#sample" + s.getId() + "'));\">Add</button>");
b.append("</div>");
}
}
else {
b.append("No matches");
}
return JSONUtils.JSONObjectResponse("html", b.toString());
}
catch (IOException e) {
log.debug("Failed", e);
return JSONUtils.SimpleJSONError("Failed: " + e.getMessage());
}
}
public JSONObject exportSampleForm(HttpSession session, JSONObject json) {
try {
JSONArray a = JSONArray.fromObject(json.getString("form"));
File f = misoFileManager.getNewFile(
Sample.class,
"forms",
"SampleExportForm-" + LimsUtils.getCurrentDateAsString(new SimpleDateFormat("yyyyMMdd-hhmmss")) + ".xlsx");
FormUtils.createSampleExportForm(f, a);
return JSONUtils.SimpleJSONResponse("" + f.getName().hashCode());
}
catch (Exception e) {
e.printStackTrace();
return JSONUtils.SimpleJSONError("Failed to get plate input form: " + e.getMessage());
}
}
public JSONObject generateCSVBAC(HttpSession session, JSONObject json) {
try {
JSONArray a = JSONArray.fromObject(json.getString("form"));
File f = misoFileManager.getNewFile(
Plate.class,
"csv",
"Illumina-Nextera-6x-384-barcode-" + LimsUtils.getCurrentDateAsString(new SimpleDateFormat("yyyyMMdd-hhmmss")) + ".csv");
FormUtils.generateCSVBAC(f, a);
return JSONUtils.SimpleJSONResponse("" + f.getName().hashCode());
}
catch (Exception e) {
e.printStackTrace();
return JSONUtils.SimpleJSONError("Failed to get plate input form: " + e.getMessage());
}
}
public JSONObject exportLibraryPoolForm(HttpSession session, JSONObject json) {
try {
String barcodekit = json.getString("barcodekit");
JSONArray a = JSONArray.fromObject(json.getString("form"));
File f = misoFileManager.getNewFile(
Library.class,
"forms",
"LibraryPoolExportForm-" + LimsUtils.getCurrentDateAsString(new SimpleDateFormat("yyyyMMdd-hhmmss")) + ".xlsx");
FormUtils.createLibraryPoolExportFormFromWeb(f, a, barcodekit);
return JSONUtils.SimpleJSONResponse("" + f.getName().hashCode());
}
catch (Exception e) {
e.printStackTrace();
return JSONUtils.SimpleJSONError("Failed to get plate input form: " + e.getMessage());
}
}
public JSONObject confirmSamplesUpload(HttpSession session, JSONObject json) throws Exception {
JSONArray jsonArray = JSONArray.fromObject(json.get("table"));
// add samples
for (JSONArray jsonArrayElement : (Iterable<JSONArray>) jsonArray) {
Sample s = null;
if (jsonArrayElement.get(3) != null && !"".equals(jsonArrayElement.getString(3))) {
String salias = jsonArrayElement.getString(3);
Collection<Sample> ss = requestManager.listSamplesByAlias(salias);
if (!ss.isEmpty()) {
if (ss.size() == 1) {
s = ss.iterator().next();
log.info("Got sample: " + s.getAlias());
}
else {
throw new InputFormException("Multiple samples retrieved with this alias: '" + salias + "'. Cannot process.");
}
}
else {
throw new InputFormException("No such sample '" + salias + "'in database. Samples need to be created before using the form input functionality");
}
}
else {
log.info("Blank sample row found. Ending import.");
break;
}
Date date = new Date();
User user = securityManager.getUserByLoginName(SecurityContextHolder.getContext().getAuthentication().getName());
//sample OK - good to go
try {
if (s != null) {
if (jsonArrayElement.get(6) != null) {
SampleQC sqc = new SampleQCImpl();
sqc.setSample(s);
sqc.setResults(jsonArrayElement.getDouble(6));
sqc.setQcCreator(user.getLoginName());
sqc.setQcDate(date);
if (requestManager.getSampleQcTypeByName("Picogreen") != null) {
sqc.setQcType(requestManager.getSampleQcTypeByName("Picogreen"));
}
else {
sqc.setQcType(requestManager.getSampleQcTypeByName("QuBit"));
}
if (!s.getSampleQCs().contains(sqc)) {
s.addQc(sqc);
requestManager.saveSampleQC(sqc);
requestManager.saveSample(s);
log.info("Added sample QC: " + sqc.toString());
}
if (jsonArrayElement.get(7) != null && !"".equals(jsonArrayElement.getString(7))) {
s.setQcPassed(Boolean.parseBoolean(jsonArrayElement.getString(7)));
requestManager.saveSample(s);
}
if (jsonArrayElement.get(8) != null && !"".equals(jsonArrayElement.getString(8))) {
List<String> notesList = Arrays.asList((jsonArrayElement.getString(8)).split(";"));
for (String notetext : notesList) {
Note note = new Note();
note.setCreationDate(date);
note.setOwner(user);
note.setText(notetext);
if (!s.getNotes().contains(note)) {
s.addNote(note);
requestManager.saveSampleNote(s, note);
requestManager.saveSample(s);
log.info("Added sample Note for Well: " + note.toString());
}
}
}
}
}
}
catch (Exception e) {
throw new Exception(e);
}
}
// create library & pool sheet
// File file = misoFileManager.getNewFile(
// Library.class,
// "forms",
// "LibraryPoolExportForm-" + LimsUtils.getCurrentDateAsString(new SimpleDateFormat("yyyyMMdd-hhmmss")) + ".xlsx");
// FormUtils.createLibraryPoolExportForm(file, jsonArray);
return JSONUtils.SimpleJSONResponse("ok");
}
public JSONObject confirmLibrariesPoolsUpload(HttpSession session, JSONObject json) throws Exception {
Date date = new Date();
User user = securityManager.getUserByLoginName(SecurityContextHolder.getContext().getAuthentication().getName());
JSONObject jsonObject = JSONObject.fromObject(json.get("sheet"));
Map<String, Pool> pools = new HashMap<String, Pool>();
Boolean paired = Boolean.parseBoolean(jsonObject.getString("paired"));
PlatformType pt = null;
if (jsonObject.getString("platform") != null) {
pt = PlatformType.get(jsonObject.getString("platform"));
}
LibraryType lt = null;
if (jsonObject.getString("type") != null) {
lt = requestManager.getLibraryTypeByDescriptionAndPlatform(jsonObject.getString("type"), pt);
}
LibrarySelectionType ls = null;
if (jsonObject.getString("selection") != null) {
ls = requestManager.getLibrarySelectionTypeByName(jsonObject.getString("selection"));
}
LibraryStrategyType lst = null;
if (jsonObject.getString("strategy") != null) {
lst = requestManager.getLibraryStrategyTypeByName(jsonObject.getString("strategy"));
}
if (jsonObject.get("rows") != null) {
for (JSONArray jsonArrayElement : (Iterable<JSONArray>) JSONArray.fromObject(jsonObject.get("rows").toString().replace("\\\"", "'"))) {
Sample s = null;
if (jsonArrayElement.get(1) != null && !"".equals(jsonArrayElement.getString(1))) {
String salias = jsonArrayElement.getString(1);
Collection<Sample> ss = requestManager.listSamplesByAlias(salias);
if (!ss.isEmpty()) {
if (ss.size() == 1) {
s = ss.iterator().next();
log.info("Got sample: " + s.getAlias());
}
else {
throw new InputFormException("Multiple samples retrieved with this alias: '" + salias + "'. Cannot process.");
}
}
else {
throw new InputFormException("No such sample '" + salias + "'in database. Samples need to be created before using the form input functionality");
}
}
else {
log.info("Blank sample row found. Ending import.");
break;
}
try {
//sample OK - good to go
if (s != null) {
String proceedKey = jsonArrayElement.getString(14);
Library library = new LibraryImpl();
if ("A".equals(proceedKey) || "L".equals(proceedKey)) {
library.setAlias(jsonArrayElement.getString(3));
}
else if ("U".equals(proceedKey) || "P".equals(proceedKey)) {
library = requestManager.getLibraryByAlias(jsonArrayElement.getString(3));
}
if ("A".equals(proceedKey) || "L".equals(proceedKey) || "U".equals(proceedKey)) {
library.setSample(s);
library.setSecurityProfile(s.getSecurityProfile());
library.setDescription(jsonArrayElement.getString(4));
library.setCreationDate(new Date());
library.setPlatformName(pt.getKey());
library.setLibraryType(lt);
library.setLibrarySelectionType(ls);
library.setLibraryStrategyType(lst);
library.setPaired(paired);
int insertSize = 0;
try {
String bp = jsonArrayElement.getString(6);
Matcher m = digitPattern.matcher(bp);
if (m.matches()) {
insertSize = Integer.valueOf(m.group(1));
}
else {
throw new InputFormException("Supplied Library insert size for library '" + jsonArrayElement.getString(3) + "' (" + s.getAlias() + ") is invalid");
}
}
catch (NumberFormatException nfe) {
throw new InputFormException("Supplied Library insert size for library '" + jsonArrayElement.getString(3) + "' (" + s.getAlias() + ") is invalid", nfe);
}
log.info("Added library: " + library.toString());
requestManager.saveLibrary(library);
if (jsonArrayElement.getString(5) != null && !"".equals(jsonArrayElement.getString(5))) {
try {
LibraryQC lqc = new LibraryQCImpl();
lqc.setLibrary(library);
lqc.setInsertSize(insertSize);
lqc.setResults(Double.valueOf(jsonArrayElement.getString(5)));
lqc.setQcCreator(user.getLoginName());
lqc.setQcDate(new Date());
lqc.setQcType(requestManager.getLibraryQcTypeByName("Qubit"));
if (!library.getLibraryQCs().contains(lqc)) {
library.addQc(lqc);
requestManager.saveLibraryQC(lqc);
log.info("Added library QC: " + lqc.toString());
}
if (insertSize == 0 && lqc.getResults() == 0) {
library.setQcPassed(false);
}
else {
if (jsonArrayElement.getString(8) != null && !"".equals(jsonArrayElement.getString(8))) {
library.setQcPassed(Boolean.parseBoolean(jsonArrayElement.getString(8)));
}
}
}
catch (NumberFormatException nfe) {
throw new InputFormException("Supplied Library QC concentration for library '" + jsonArrayElement.getString(3) + "' (" + s.getAlias() + ") is invalid", nfe);
}
}
if (jsonArrayElement.getString(7) != null && !"".equals(jsonArrayElement.getString(7))) {
try {
LibraryQC lqc = new LibraryQCImpl();
lqc.setLibrary(library);
lqc.setInsertSize(insertSize);
lqc.setResults(Double.valueOf(jsonArrayElement.getString(7)));
lqc.setQcCreator(user.getLoginName());
lqc.setQcDate(new Date());
lqc.setQcType(requestManager.getLibraryQcTypeByName("Bioanalyzer"));
if (!library.getLibraryQCs().contains(lqc)) {
library.addQc(lqc);
requestManager.saveLibraryQC(lqc);
log.info("Added library QC: " + lqc.toString());
}
if (insertSize == 0 && lqc.getResults() == 0) {
library.setQcPassed(false);
}
else {
if (jsonArrayElement.getString(8) != null && !"".equals(jsonArrayElement.getString(8))) {
library.setQcPassed(Boolean.parseBoolean(jsonArrayElement.getString(8)));
}
}
}
catch (NumberFormatException nfe) {
throw new InputFormException("Supplied Library QC concentration for library '" + jsonArrayElement.getString(3) + "' (" + s.getAlias() + ") is invalid", nfe);
}
}
if (jsonArrayElement.getString(9) != null && !"".equals(jsonArrayElement.getString(9)) && (library.getQcPassed() || library.getQcPassed() == null) ) {
Collection<TagBarcode> bcs = requestManager.listAllTagBarcodesByStrategyName(jsonArrayElement.getString(9));
if (!bcs.isEmpty()) {
String tags = jsonArrayElement.getString(10);
if (!"".equals(tags)) {
HashMap<Integer, TagBarcode> tbs = new HashMap<Integer, TagBarcode>();
if (tags.contains("-")) {
String[] splits = tags.split("-");
int count = 1;
for (String tag : splits) {
for (TagBarcode tb : bcs) {
if (tb.getName().equals(tag)) {
//set tag barcodes
tbs.put(count, tb);
count++;
}
}
}
}
else {
for (TagBarcode tb : bcs) {
if (tb.getName().equals(tags) || tb.getSequence().equals(tags)) {
//set tag barcode
tbs.put(1, tb);
log.info("Got tag barcode: " + tb.getName());
break;
}
}
}
library.setTagBarcodes(tbs);
}
else {
throw new InputFormException("Barcode Kit specified but no tag barcodes entered for library '" + jsonArrayElement.getString(3) + "'.");
}
}
else {
throw new InputFormException("No tag barcodes associated with the kit definition '" + jsonArrayElement.getString(9) + "' library '" + jsonArrayElement.getString(3) + "'.");
}
}
log.info("Added library: " + library.toString());
requestManager.saveLibrary(library);
}
if ((library.getQcPassed() || library.getQcPassed() == null) && ("A".equals(proceedKey) || "P".equals(proceedKey))) {
LibraryDilution ldi = new LibraryDilution();
if (jsonArrayElement.getString(11) != null && !"".equals(jsonArrayElement.getString(11))) {
try {
ldi.setLibrary(library);
ldi.setSecurityProfile(library.getSecurityProfile());
ldi.setConcentration(Double.valueOf(jsonArrayElement.getString(11)));
ldi.setCreationDate(new Date());
ldi.setDilutionCreator(user.getLoginName());
if (!library.getLibraryDilutions().contains(ldi)) {
library.addDilution(ldi);
log.info("Added library dilution: " + ldi.toString());
}
requestManager.saveLibraryDilution(ldi);
}
catch (NumberFormatException nfe) {
throw new InputFormException("Supplied LibraryDilution concentration for library '" + jsonArrayElement.getString(3) + "' (" + s.getAlias() + ") is invalid", nfe);
}
}
log.info("Added library: " + library.toString());
requestManager.saveLibrary(library);
Pattern poolPattern = Pattern.compile("^[IiUu][Pp][Oo]([0-9]*)");
if (jsonArrayElement.getString(12) != null && !"".equals(jsonArrayElement.getString(12))) {
String poolName = jsonArrayElement.getString(12);
Matcher m = poolPattern.matcher(poolName);
if (m.matches()) {
Pool existedPool = requestManager.getPoolById(Integer.valueOf(m.group(1)));
pools.put(poolName, existedPool);
if (jsonArrayElement.getString(13) != null && !"".equals(jsonArrayElement.getString(13))) {
existedPool.setConcentration(Double.valueOf(jsonArrayElement.getString(13)));
}
if (ldi != null) {
existedPool.addPoolableElement(ldi);
}
requestManager.savePool(existedPool);
}
else {
Pool pool = new PoolImpl();
if (!pools.containsKey(poolName)) {
pool.setAlias(poolName);
pool.setPlatformType(pt);
pool.setReadyToRun(true);
pool.setCreationDate(new Date());
if (jsonArrayElement.getString(13) != null && !"".equals(jsonArrayElement.getString(13))) {
pool.setConcentration(Double.valueOf(jsonArrayElement.getString(13)));
}
else {
pool.setConcentration(0.0);
}
pools.put(poolName, pool);
log.info("Added pool: " + poolName);
if (ldi != null) {
pool.addPoolableElement(ldi);
}
requestManager.savePool(pool);
}
else {
pool = pools.get(poolName);
if (ldi != null) {
pool.addPoolableElement(ldi);
requestManager.savePool(pool);
}
}
}
}
log.info("Added library: " + library.toString());
requestManager.saveLibrary(library);
}
}
}
catch (Exception e) {
throw new Exception(e);
}
}
}
return JSONUtils.SimpleJSONResponse("ok");
}
public JSONObject platformsOptions(HttpSession session, JSONObject json) {
try {
StringBuilder b = new StringBuilder();
List<String> pn = new ArrayList<String>(populatePlatformNames());
for (String name : pn) {
b.append("<option>" + name + "</option>");
}
return JSONUtils.JSONObjectResponse("html", b.toString());
}
catch (IOException e) {
log.debug("Failed", e);
return JSONUtils.SimpleJSONError("Failed: " + e.getMessage());
}
}
public Collection<String> populatePlatformNames() throws IOException {
List<String> types = new ArrayList<String>(requestManager.listDistinctPlatformNames());
Collections.sort(types);
return types;
}
public Collection<LibraryStrategyType> populateLibraryStrategyTypes() throws IOException {
List<LibraryStrategyType> types = new ArrayList<LibraryStrategyType>(requestManager.listAllLibraryStrategyTypes());
Collections.sort(types);
return types;
}
public JSONObject libraryStrategyTypesString(HttpSession session, JSONObject json) throws IOException {
StringBuilder b = new StringBuilder();
for (LibraryStrategyType t : populateLibraryStrategyTypes()) {
b.append("<option>" + t.getName() + "</option>");
}
return JSONUtils.JSONObjectResponse("html", b.toString());
}
public Collection<LibrarySelectionType> populateLibrarySelectionTypes() throws IOException {
List<LibrarySelectionType> types = new ArrayList<LibrarySelectionType>(requestManager.listAllLibrarySelectionTypes());
Collections.sort(types);
return types;
}
public JSONObject librarySelectionTypesString(HttpSession session, JSONObject json) throws IOException {
StringBuilder b = new StringBuilder();
for (LibrarySelectionType t : populateLibrarySelectionTypes()) {
b.append("<option>" + t.getName() + "</option>");
}
return JSONUtils.JSONObjectResponse("html", b.toString());
}
public JSONObject changePlatformName(HttpSession session, JSONObject json) {
try {
if (json.has("platform") && !json.get("platform").equals("")) {
String platform = json.getString("platform");
Map<String, Object> map = new HashMap<String, Object>();
StringBuilder libsb = new StringBuilder();
List<LibraryType> types = new ArrayList<LibraryType>(requestManager.listLibraryTypesByPlatform(platform));
Collections.sort(types);
for (LibraryType s : types) {
libsb.append("<option>" + platform + "-" + s.getDescription() + "</option>");
}
StringBuilder tagsb = new StringBuilder();
List<TagBarcodeStrategy> strategies = new ArrayList<TagBarcodeStrategy>(tagBarcodeStrategyResolverService.getTagBarcodeStrategiesByPlatform(PlatformType.get(platform)));
tagsb.append("<option >No Barcode Strategy</option>");
for (TagBarcodeStrategy tb : strategies) {
tagsb.append("<option>" + tb.getName() + "</option>");
}
map.put("libraryTypes", libsb.toString());
map.put("tagBarcodeStrategies", tagsb.toString());
return JSONUtils.JSONObjectResponse(map);
}
}
catch (IOException e) {
e.printStackTrace();
log.error("Failed to retrieve library types given platform type: ", e);
return JSONUtils.SimpleJSONError("Failed to retrieve library types given platform type: " + e.getMessage());
}
return JSONUtils.SimpleJSONError("Cannot resolve LibraryType from selected Platform");
}
public void setRequestManager(RequestManager requestManager) {
this.requestManager = requestManager;
}
public void setMisoFileManager(MisoFilesManager misoFileManager) {
this.misoFileManager = misoFileManager;
}
public void setSecurityManager(SecurityManager securityManager) {
this.securityManager = securityManager;
}
public void setTagBarcodeStrategyResolverService(TagBarcodeStrategyResolverService tagBarcodeStrategyResolverService) {
this.tagBarcodeStrategyResolverService = tagBarcodeStrategyResolverService;
}
}