extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/servlet/ExternalSpecimenServlet.java

Code
Comments
Other
Rev Date Author Line
6178 23 Mar 21 nicklas 1 package net.sf.basedb.reggie.servlet;
6178 23 Mar 21 nicklas 2
6965 10 Jan 23 nicklas 3 import java.io.ByteArrayInputStream;
6998 20 Jan 23 nicklas 4 import java.io.ByteArrayOutputStream;
6178 23 Mar 21 nicklas 5 import java.io.IOException;
6199 08 Apr 21 nicklas 6 import java.util.ArrayList;
6896 28 Nov 22 nicklas 7 import java.util.Arrays;
6199 08 Apr 21 nicklas 8 import java.util.Collections;
6929 02 Dec 22 nicklas 9 import java.util.Date;
6582 11 Feb 22 nicklas 10 import java.util.HashSet;
6965 10 Jan 23 nicklas 11 import java.util.LinkedHashMap;
7173 17 May 23 nicklas 12 import java.util.LinkedHashSet;
6178 23 Mar 21 nicklas 13 import java.util.List;
6965 10 Jan 23 nicklas 14 import java.util.Map;
6582 11 Feb 22 nicklas 15 import java.util.Set;
6965 10 Jan 23 nicklas 16 import java.util.TreeMap;
7184 22 May 23 nicklas 17 import java.util.regex.Matcher;
7184 22 May 23 nicklas 18 import java.util.regex.Pattern;
6178 23 Mar 21 nicklas 19
6178 23 Mar 21 nicklas 20 import javax.servlet.ServletException;
6178 23 Mar 21 nicklas 21 import javax.servlet.http.HttpServlet;
6178 23 Mar 21 nicklas 22 import javax.servlet.http.HttpServletRequest;
6178 23 Mar 21 nicklas 23 import javax.servlet.http.HttpServletResponse;
6178 23 Mar 21 nicklas 24
7025 08 Feb 23 nicklas 25 import org.apache.commons.lang3.time.FastDateFormat;
6178 23 Mar 21 nicklas 26 import org.json.simple.JSONArray;
6178 23 Mar 21 nicklas 27 import org.json.simple.JSONObject;
6965 10 Jan 23 nicklas 28 import org.json.simple.parser.JSONParser;
6178 23 Mar 21 nicklas 29
6734 09 May 22 nicklas 30 import net.sf.basedb.clients.web.util.HTML;
7173 17 May 23 nicklas 31 import net.sf.basedb.core.BioPlate;
7173 17 May 23 nicklas 32 import net.sf.basedb.core.BioWell;
6178 23 Mar 21 nicklas 33 import net.sf.basedb.core.DbControl;
6960 13 Dec 22 nicklas 34 import net.sf.basedb.core.File;
6178 23 Mar 21 nicklas 35 import net.sf.basedb.core.FileServer;
7189 22 May 23 nicklas 36 import net.sf.basedb.core.Hardware;
6736 10 May 22 nicklas 37 import net.sf.basedb.core.ItemList;
6178 23 Mar 21 nicklas 38 import net.sf.basedb.core.ItemNotFoundException;
6582 11 Feb 22 nicklas 39 import net.sf.basedb.core.ItemQuery;
6583 11 Feb 22 nicklas 40 import net.sf.basedb.core.ItemSubtype;
6211 14 Apr 21 nicklas 41 import net.sf.basedb.core.Job;
7173 17 May 23 nicklas 42 import net.sf.basedb.core.MeasuredBioMaterial;
6960 13 Dec 22 nicklas 43 import net.sf.basedb.core.Path;
6211 14 Apr 21 nicklas 44 import net.sf.basedb.core.Protocol;
6582 11 Feb 22 nicklas 45 import net.sf.basedb.core.Sample;
6178 23 Mar 21 nicklas 46 import net.sf.basedb.core.SessionControl;
6898 29 Nov 22 nicklas 47 import net.sf.basedb.core.SimpleProgressReporter;
6211 14 Apr 21 nicklas 48 import net.sf.basedb.core.Software;
6734 09 May 22 nicklas 49 import net.sf.basedb.core.Subtypable;
6582 11 Feb 22 nicklas 50 import net.sf.basedb.core.Type;
6582 11 Feb 22 nicklas 51 import net.sf.basedb.core.query.Annotations;
6582 11 Feb 22 nicklas 52 import net.sf.basedb.core.query.Expressions;
6582 11 Feb 22 nicklas 53 import net.sf.basedb.core.query.Hql;
7173 17 May 23 nicklas 54 import net.sf.basedb.core.query.Orders;
6582 11 Feb 22 nicklas 55 import net.sf.basedb.core.query.Restrictions;
6211 14 Apr 21 nicklas 56 import net.sf.basedb.opengrid.JobDefinition;
6178 23 Mar 21 nicklas 57 import net.sf.basedb.opengrid.OpenGrid;
6178 23 Mar 21 nicklas 58 import net.sf.basedb.opengrid.OpenGridCluster;
6178 23 Mar 21 nicklas 59 import net.sf.basedb.opengrid.RemoteHost;
6178 23 Mar 21 nicklas 60 import net.sf.basedb.opengrid.RemoteSession;
6178 23 Mar 21 nicklas 61 import net.sf.basedb.opengrid.config.ConnectionInfo;
6929 02 Dec 22 nicklas 62 import net.sf.basedb.opengrid.filetransfer.FileMetaData;
6178 23 Mar 21 nicklas 63 import net.sf.basedb.opengrid.service.OpenGridService;
6178 23 Mar 21 nicklas 64 import net.sf.basedb.reggie.JsonUtil;
6178 23 Mar 21 nicklas 65 import net.sf.basedb.reggie.Reggie;
7032 10 Feb 23 nicklas 66 import net.sf.basedb.reggie.activity.ActivityDef;
6178 23 Mar 21 nicklas 67 import net.sf.basedb.reggie.counter.CounterService;
6210 14 Apr 21 nicklas 68 import net.sf.basedb.reggie.dao.Annotationtype;
6210 14 Apr 21 nicklas 69 import net.sf.basedb.reggie.dao.BiomaterialList;
6582 11 Feb 22 nicklas 70 import net.sf.basedb.reggie.dao.Case;
6215 16 Apr 21 nicklas 71 import net.sf.basedb.reggie.dao.DemuxedSequences;
6178 23 Mar 21 nicklas 72 import net.sf.basedb.reggie.dao.Fileserver;
6582 11 Feb 22 nicklas 73 import net.sf.basedb.reggie.dao.NoSpecimen;
6178 23 Mar 21 nicklas 74 import net.sf.basedb.reggie.dao.ReggieRole;
6736 10 May 22 nicklas 75 import net.sf.basedb.reggie.dao.Rna;
6495 01 Dec 21 nicklas 76 import net.sf.basedb.reggie.dao.SpecimenTube;
6582 11 Feb 22 nicklas 77 import net.sf.basedb.reggie.dao.Subtype;
6211 14 Apr 21 nicklas 78 import net.sf.basedb.reggie.grid.ImportFastqJobCreator;
6178 23 Mar 21 nicklas 79 import net.sf.basedb.reggie.grid.ScriptUtil;
6498 01 Dec 21 nicklas 80 import net.sf.basedb.reggie.plugins.ExternalSpecimenImporter;
7139 27 Apr 23 nicklas 81 import net.sf.basedb.reggie.plugins.TransportBoxImporter;
6498 01 Dec 21 nicklas 82 import net.sf.basedb.reggie.plugins.ExternalSpecimenImporter.ImportedItems;
7191 23 May 23 nicklas 83 import net.sf.basedb.reggie.plugins.TransportBoxImporter.Box;
7139 27 Apr 23 nicklas 84 import net.sf.basedb.reggie.plugins.TransportBoxImporter.SampleEntry;
6734 09 May 22 nicklas 85 import net.sf.basedb.reggie.plugins.cmd.EndPoint;
6929 02 Dec 22 nicklas 86 import net.sf.basedb.reggie.plugins.cmd.ImportContext;
6199 08 Apr 21 nicklas 87 import net.sf.basedb.reggie.plugins.cmd.JsonFile;
6341 29 Jun 21 nicklas 88 import net.sf.basedb.reggie.plugins.cmd.MainInfo;
6341 29 Jun 21 nicklas 89 import net.sf.basedb.reggie.plugins.cmd.ScanBIdRef;
6341 29 Jun 21 nicklas 90 import net.sf.basedb.reggie.plugins.cmd.ScanBIdRef.SampleIdType;
6965 10 Jan 23 nicklas 91 import net.sf.basedb.util.FileUtil;
6212 14 Apr 21 nicklas 92 import net.sf.basedb.util.Values;
6178 23 Mar 21 nicklas 93 import net.sf.basedb.util.error.ThrowableUtil;
6178 23 Mar 21 nicklas 94
6178 23 Mar 21 nicklas 95
6498 01 Dec 21 nicklas 96 public class ExternalSpecimenServlet 
6178 23 Mar 21 nicklas 97   extends HttpServlet 
6178 23 Mar 21 nicklas 98 {
6178 23 Mar 21 nicklas 99   
6178 23 Mar 21 nicklas 100   private static final long serialVersionUID = 2213869286902406649L;
6178 23 Mar 21 nicklas 101
6498 01 Dec 21 nicklas 102   public ExternalSpecimenServlet()
6178 23 Mar 21 nicklas 103   {}
6178 23 Mar 21 nicklas 104
7184 22 May 23 nicklas 105   @SuppressWarnings("unchecked")
6178 23 Mar 21 nicklas 106   @Override
6178 23 Mar 21 nicklas 107   protected void doGet(HttpServletRequest req, HttpServletResponse resp)
6178 23 Mar 21 nicklas 108     throws ServletException, IOException 
6178 23 Mar 21 nicklas 109   {
6178 23 Mar 21 nicklas 110     String cmd = req.getParameter("cmd");
6178 23 Mar 21 nicklas 111     JsonUtil.setJsonResponseHeaders(resp);
6178 23 Mar 21 nicklas 112     
6178 23 Mar 21 nicklas 113     JSONObject json = new JSONObject();
6178 23 Mar 21 nicklas 114     json.put("status", "ok");
6178 23 Mar 21 nicklas 115     
6178 23 Mar 21 nicklas 116     final SessionControl sc = Reggie.getSessionControl(req);
6178 23 Mar 21 nicklas 117     DbControl dc = null;
6178 23 Mar 21 nicklas 118     try
6178 23 Mar 21 nicklas 119     {
6178 23 Mar 21 nicklas 120
6178 23 Mar 21 nicklas 121       if ("GetImportInformation".equals(cmd))
6178 23 Mar 21 nicklas 122       {
6178 23 Mar 21 nicklas 123         JSONArray jsonImportItems = new JSONArray();
6337 16 Jun 21 nicklas 124         dc = sc.newDbControl(":Import externally processed samples");
6896 28 Nov 22 nicklas 125
6896 28 Nov 22 nicklas 126         // A single file may be requested
6896 28 Nov 22 nicklas 127         String file = Values.getStringOrNull(req.getParameter("file"));
6896 28 Nov 22 nicklas 128         int itemNo = Values.getInt(req.getParameter("itemNo"));
6899 29 Nov 22 nicklas 129         boolean validateAll = Values.getBoolean(req.getParameter("validateAll"));
6178 23 Mar 21 nicklas 130         
6582 11 Feb 22 nicklas 131         // Keep track of NoSpecimen items that have been pre-registered with ExternalSpecimenExists=Yes
6582 11 Feb 22 nicklas 132         Set<Integer> matchedNoSpecimen = new HashSet<>();
6896 28 Nov 22 nicklas 133         List<JsonFile> files = null;
6929 02 Dec 22 nicklas 134         ImportContext ctx = new ImportContext();
6896 28 Nov 22 nicklas 135         FileServer gateway = Fileserver.IMPORT_GATEWAY.load(dc);
6896 28 Nov 22 nicklas 136         if (file == null)
6896 28 Nov 22 nicklas 137         {
6898 29 Nov 22 nicklas 138           SimpleProgressReporter progress = new SimpleProgressReporter(null);
6898 29 Nov 22 nicklas 139           sc.setSessionSetting("scan-json-progress", progress);
6898 29 Nov 22 nicklas 140           progress.display(1, "Scanning for JSON files on "+gateway.getName()+":"+gateway.getRootPath()+"...");
6929 02 Dec 22 nicklas 141           files = JsonFile.findJsonFiles(dc, gateway, ctx, true, validateAll ? -1 : 30, progress);
6904 29 Nov 22 nicklas 142           progress.display(99, "Scan complete! Found " + files.size() + " JSON files on "+gateway.getName()+":"+gateway.getRootPath());
6898 29 Nov 22 nicklas 143           Thread.sleep(2000);
6896 28 Nov 22 nicklas 144         }
6896 28 Nov 22 nicklas 145         else
6896 28 Nov 22 nicklas 146         {
6896 28 Nov 22 nicklas 147           ScriptUtil.checkValidFilename(req.getParameter("file"));
6896 28 Nov 22 nicklas 148           files = Arrays.asList(JsonFile.getJsonFile(dc, gateway, file, true));
6896 28 Nov 22 nicklas 149         }
6198 07 Apr 21 nicklas 150         for (JsonFile importFile : files)
6178 23 Mar 21 nicklas 151         {
6178 23 Mar 21 nicklas 152           JSONObject jsonFile = new JSONObject();
6896 28 Nov 22 nicklas 153           if (file != null) jsonFile.put("itemNo", itemNo);
6734 09 May 22 nicklas 154           MainInfo mainInfo = importFile.getMain();
6178 23 Mar 21 nicklas 155           
6734 09 May 22 nicklas 156           if (mainInfo != null)
6178 23 Mar 21 nicklas 157           {
6734 09 May 22 nicklas 158             ScanBIdRef idRef = mainInfo.idRef;
6734 09 May 22 nicklas 159             EndPoint endPoint = mainInfo.endPoint;
6734 09 May 22 nicklas 160             if (endPoint != null)
6734 09 May 22 nicklas 161             {
6736 10 May 22 nicklas 162               jsonFile.put("endPoint", endPoint.asJSONObject());
6736 10 May 22 nicklas 163               jsonFile.put("endPointRNA", EndPoint.RNA.asJSONObject());
6734 09 May 22 nicklas 164               if (endPoint != EndPoint.DEMUX)
6734 09 May 22 nicklas 165               {
6734 09 May 22 nicklas 166                 importFile.addWarningMessage(0, "[HTML]<b>No FASTQ files exists</b>");
6734 09 May 22 nicklas 167               }
6734 09 May 22 nicklas 168             }
6341 29 Jun 21 nicklas 169             if (idRef != null)
6495 01 Dec 21 nicklas 170             {
6505 02 Dec 21 nicklas 171               if (idRef.theCase != null)
6505 02 Dec 21 nicklas 172               {
6505 02 Dec 21 nicklas 173                 jsonFile.put("currentCase", idRef.theCase.asJSONObject());
6505 02 Dec 21 nicklas 174               }
6495 01 Dec 21 nicklas 175               if (idRef.idType == SampleIdType.CASE)
6348 16 Aug 21 nicklas 176               {
7229 02 Jun 23 nicklas 177                 if (idRef.mergeWith != null)
6573 07 Feb 22 nicklas 178                 {
7229 02 Jun 23 nicklas 179                   jsonFile.put("itemType", "Specimen");
7229 02 Jun 23 nicklas 180                   jsonFile.put("mergeWithExisting", true);
7229 02 Jun 23 nicklas 181                   jsonFile.putAll(idRef.mergeWith.asJSONObject());
7229 02 Jun 23 nicklas 182                 }
7229 02 Jun 23 nicklas 183                 else if (idRef.noSpecimen != null)
7229 02 Jun 23 nicklas 184                 {
6582 11 Feb 22 nicklas 185                   matchedNoSpecimen.add(idRef.noSpecimen.getId());
6573 07 Feb 22 nicklas 186                   jsonFile.put("itemType", "NoSpecimen");
6921 02 Dec 22 nicklas 187                   jsonFile.put("convertToSpecimen", true);
6924 02 Dec 22 nicklas 188                   idRef.noSpecimen.loadAnnotations(dc, "otherPathNote", Annotationtype.OTHER_PATH_NOTE, null);
6573 07 Feb 22 nicklas 189                   jsonFile.putAll(idRef.noSpecimen.asJSONObject());
6573 07 Feb 22 nicklas 190                 }
6573 07 Feb 22 nicklas 191                 else
6573 07 Feb 22 nicklas 192                 {
6581 10 Feb 22 nicklas 193                   if (idRef.copyMissingDataFrom != null)
6581 10 Feb 22 nicklas 194                   {
6927 02 Dec 22 nicklas 195                     jsonFile.put("otherPathNote", Annotationtype.OTHER_PATH_NOTE.getAnnotationValue(dc, idRef.copyMissingDataFrom));
6583 11 Feb 22 nicklas 196                     ItemSubtype subtype = idRef.copyMissingDataFrom.getItemSubtype();
6583 11 Feb 22 nicklas 197                     String subtypeName = subtype == null ? "" : subtype.getName();
6583 11 Feb 22 nicklas 198                     boolean specimenExists = "Yes".equals(Annotationtype.EXTERNAL_SPECIMEN_EXISTS.getAnnotationValue(dc, idRef.copyMissingDataFrom));
6583 11 Feb 22 nicklas 199                     if ("NoSpecimen".equals(subtypeName) && !specimenExists)
6583 11 Feb 22 nicklas 200                     {
6583 11 Feb 22 nicklas 201                       importFile.addWarningMessage(0, "[HTML]<b>Should "+idRef.copyMissingDataFrom.getName() + " be converted to Specimen instead?</b>");
6583 11 Feb 22 nicklas 202                     }
6583 11 Feb 22 nicklas 203                     importFile.addWarningMessage(0, "[HTML]<b>Missing data is copied from "+subtypeName+": "+idRef.copyMissingDataFrom.getName()+"</b>");
6581 10 Feb 22 nicklas 204                   }
6573 07 Feb 22 nicklas 205                   jsonFile.put("itemType", "Specimen");
7000 20 Jan 23 nicklas 206                   jsonFile.put("name", SpecimenTube.getNextSpecimenName(dc, idRef.id, true));
6573 07 Feb 22 nicklas 207                 }
6495 01 Dec 21 nicklas 208               }
6495 01 Dec 21 nicklas 209               else if (idRef.idType == SampleIdType.SPECIMEN)
6341 29 Jun 21 nicklas 210               {
6341 29 Jun 21 nicklas 211                 jsonFile.put("itemType", "Specimen");
6341 29 Jun 21 nicklas 212                 if (idRef.specimen != null)
6341 29 Jun 21 nicklas 213                 {
6341 29 Jun 21 nicklas 214                   jsonFile.putAll(idRef.specimen.asJSONObject());
6341 29 Jun 21 nicklas 215                 }
6341 29 Jun 21 nicklas 216               }
6341 29 Jun 21 nicklas 217               else if (idRef.idType == SampleIdType.PRENORMALISED_RNA)
6341 29 Jun 21 nicklas 218               {
6341 29 Jun 21 nicklas 219                 jsonFile.put("itemType", "RNA");
6341 29 Jun 21 nicklas 220                 if (idRef.rna != null)
6341 29 Jun 21 nicklas 221                 {
6341 29 Jun 21 nicklas 222                   jsonFile.putAll(idRef.rna.asJSONObject());
6341 29 Jun 21 nicklas 223                 }
6341 29 Jun 21 nicklas 224               }
6341 29 Jun 21 nicklas 225             }
6178 23 Mar 21 nicklas 226           }
6341 29 Jun 21 nicklas 227           jsonFile.put("jsonFile", importFile.asJSONObject());
6178 23 Mar 21 nicklas 228           jsonImportItems.add(jsonFile);
6178 23 Mar 21 nicklas 229         }
6582 11 Feb 22 nicklas 230         
6896 28 Nov 22 nicklas 231         if (file == null)
6582 11 Feb 22 nicklas 232         {
6896 28 Nov 22 nicklas 233           // Load all NoSpecimen with ExternalSpecimenExists=Yes except those that have been matched to a JSON file
6896 28 Nov 22 nicklas 234           ItemQuery<Sample> query = Sample.getQuery();
6896 28 Nov 22 nicklas 235           Subtype.NO_SPECIMEN.addFilter(dc, query);
6896 28 Nov 22 nicklas 236           query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
6896 28 Nov 22 nicklas 237           // Must have ExternalSpecimenExists=Yes annotation
6896 28 Nov 22 nicklas 238           query.join(Annotations.innerJoin(Annotationtype.EXTERNAL_SPECIMEN_EXISTS.get(dc), "es"));
6896 28 Nov 22 nicklas 239           query.restrict(Restrictions.eq(Hql.alias("es"), Expressions.string("Yes")));
6896 28 Nov 22 nicklas 240           query.restrict(Restrictions.not(Restrictions.in(Hql.property("id"), Expressions.parameter("matched"))));
6896 28 Nov 22 nicklas 241           query.setParameter("matched", matchedNoSpecimen, Type.INT);
6896 28 Nov 22 nicklas 242           for (NoSpecimen ns : NoSpecimen.toList(query.list(dc)))
6582 11 Feb 22 nicklas 243           {
6896 28 Nov 22 nicklas 244             Case theCase = ns.getCase();
6896 28 Nov 22 nicklas 245             ns.setAnnotation("itemType", "NoSpecimen");
6896 28 Nov 22 nicklas 246             ns.loadAnnotations(dc, "liasonComment", Annotationtype.LIASON_COMMENT, null);
6924 02 Dec 22 nicklas 247             ns.loadAnnotations(dc, "otherPathNote", Annotationtype.OTHER_PATH_NOTE, null);
6896 28 Nov 22 nicklas 248             ns.loadAnnotations(dc, "externalSpecimenExists", Annotationtype.EXTERNAL_SPECIMEN_EXISTS, null);
6896 28 Nov 22 nicklas 249             ns.loadAnnotations(dc, "externalOperator", Annotationtype.EXTERNAL_OPERATOR, null);
6896 28 Nov 22 nicklas 250             ns.setAnnotation("samplingDate", Reggie.CONVERTER_DATE_TO_STRING.convert(ns.getItem().getCreationEvent().getEventDate()));
6896 28 Nov 22 nicklas 251             ns.setAnnotation("registered", Reggie.CONVERTER_DATE_TO_STRING.convert(ns.getItem().getEntryDate()));
6896 28 Nov 22 nicklas 252             if (theCase != null)
6896 28 Nov 22 nicklas 253             {
6896 28 Nov 22 nicklas 254               ns.setAnnotation("currentCase", theCase.asJSONObject());
6896 28 Nov 22 nicklas 255             }
6896 28 Nov 22 nicklas 256             jsonImportItems.add(ns.asJSONObject());
6582 11 Feb 22 nicklas 257           }
6929 02 Dec 22 nicklas 258           
6929 02 Dec 22 nicklas 259           for (String f : ctx.getFilesThatWasNeverRequested())
6929 02 Dec 22 nicklas 260           {
6929 02 Dec 22 nicklas 261             FileMetaData fdata = ctx.getFileInfo(f);
6929 02 Dec 22 nicklas 262             JSONObject jsonFastq = new JSONObject();
6929 02 Dec 22 nicklas 263             jsonFastq.put("itemType", "StrayFastq");
6929 02 Dec 22 nicklas 264             jsonFastq.put("name", f);
6929 02 Dec 22 nicklas 265             jsonFastq.put("size", fdata.getSize());
6929 02 Dec 22 nicklas 266             jsonFastq.put("lastModified", Reggie.CONVERTER_DATETIME_TO_STRING_WITH_SEPARATOR.convert(new Date(fdata.getLastModifiedTime())));
6929 02 Dec 22 nicklas 267             jsonImportItems.add(jsonFastq);
6929 02 Dec 22 nicklas 268           }
6929 02 Dec 22 nicklas 269           
6582 11 Feb 22 nicklas 270         }
6898 29 Nov 22 nicklas 271         sc.setSessionSetting("scan-json-progress", null);
6178 23 Mar 21 nicklas 272         json.put("importItems", jsonImportItems);
6178 23 Mar 21 nicklas 273       }
6208 12 Apr 21 nicklas 274       else if ("DownloadJsonFile".equals(cmd))
6208 12 Apr 21 nicklas 275       {
6208 12 Apr 21 nicklas 276         json = null; // No regular JSON output
6337 16 Jun 21 nicklas 277         dc = sc.newDbControl(":Import externally processed samples");
6208 12 Apr 21 nicklas 278         
6998 20 Jan 23 nicklas 279         int fileId = Values.getInt(req.getParameter("fileId"));
6998 20 Jan 23 nicklas 280         String file = Values.getStringOrNull(req.getParameter("file"));
6208 12 Apr 21 nicklas 281         
6998 20 Jan 23 nicklas 282         ByteArrayOutputStream jsonBytes = new ByteArrayOutputStream();
6998 20 Jan 23 nicklas 283         if (file != null)
6208 12 Apr 21 nicklas 284         {
6998 20 Jan 23 nicklas 285           ScriptUtil.checkValidFilename(file);
6998 20 Jan 23 nicklas 286           FileServer fs = Fileserver.IMPORT_GATEWAY.load(dc);
6998 20 Jan 23 nicklas 287           String rootPath = ScriptUtil.checkValidPath(fs.getRootPath(), true, false);
6998 20 Jan 23 nicklas 288           RemoteSession session = null;
6965 10 Jan 23 nicklas 289           try
6965 10 Jan 23 nicklas 290           {
6998 20 Jan 23 nicklas 291             RemoteHost host = new RemoteHost(new ConnectionInfo(fs));
6998 20 Jan 23 nicklas 292             session = host.connect(5);
6998 20 Jan 23 nicklas 293             FileUtil.copy(session.readFile(rootPath+"/"+file, null), jsonBytes);
6965 10 Jan 23 nicklas 294           }
6998 20 Jan 23 nicklas 295           finally
6965 10 Jan 23 nicklas 296           {
6998 20 Jan 23 nicklas 297             OpenGrid.close(session);
6965 10 Jan 23 nicklas 298           }
6208 12 Apr 21 nicklas 299         }
6998 20 Jan 23 nicklas 300         else
6208 12 Apr 21 nicklas 301         {
6998 20 Jan 23 nicklas 302           File f = File.getById(dc, fileId);
6998 20 Jan 23 nicklas 303           FileUtil.copy(f.getDownloadStream(0), jsonBytes);
6208 12 Apr 21 nicklas 304         }
6208 12 Apr 21 nicklas 305         
6998 20 Jan 23 nicklas 306         resp.setContentType("application/json");
6998 20 Jan 23 nicklas 307         try
6998 20 Jan 23 nicklas 308         {
6998 20 Jan 23 nicklas 309           // Try to parse as JSON
6998 20 Jan 23 nicklas 310           JSONObject jsonData = (JSONObject)new JSONParser().parse(jsonBytes.toString("UTF-8"));
6998 20 Jan 23 nicklas 311           // Move entries to an insertion-ordered map
6998 20 Jan 23 nicklas 312           Map<String, Object> ordered = new LinkedHashMap<>();
6998 20 Jan 23 nicklas 313           moveJsonObject("SCANB_ID", ordered, jsonData);
6998 20 Jan 23 nicklas 314           moveJsonObject("Specimen", ordered, jsonData);
6998 20 Jan 23 nicklas 315           moveJsonObject("Lysate", ordered, jsonData);
6998 20 Jan 23 nicklas 316           moveJsonObject("RNA", ordered, jsonData);
6998 20 Jan 23 nicklas 317           moveJsonObject("DNA", ordered, jsonData);
6998 20 Jan 23 nicklas 318           moveJsonObject("FlowThrough", ordered, jsonData);
6998 20 Jan 23 nicklas 319           moveJsonObject("Library", ordered, jsonData);
6998 20 Jan 23 nicklas 320           moveJsonObject("Pool", ordered, jsonData);
6998 20 Jan 23 nicklas 321           moveJsonObject("FlowCell", ordered, jsonData);
6998 20 Jan 23 nicklas 322           moveJsonObject("SequencingRun", ordered, jsonData);
6998 20 Jan 23 nicklas 323           moveJsonObject("DemuxedSequences", ordered, jsonData);
6998 20 Jan 23 nicklas 324           moveJsonObject("MergedSequences", ordered, jsonData);
6998 20 Jan 23 nicklas 325           moveJsonObject("fastq", ordered, jsonData);
6998 20 Jan 23 nicklas 326           // Copy remaining entries
6998 20 Jan 23 nicklas 327           ordered.putAll(jsonData);
6998 20 Jan 23 nicklas 328           JSONObject.writeJSONString(ordered, resp.getWriter());
6998 20 Jan 23 nicklas 329         }
6998 20 Jan 23 nicklas 330         catch (RuntimeException ex)
6998 20 Jan 23 nicklas 331         {
6998 20 Jan 23 nicklas 332           // If something fails when creating the re-ordered map we send the original file as is
6998 20 Jan 23 nicklas 333           FileUtil.copy(new ByteArrayInputStream(jsonBytes.toByteArray()), resp.getOutputStream());
6998 20 Jan 23 nicklas 334         }
6998 20 Jan 23 nicklas 335         
6208 12 Apr 21 nicklas 336       }
7173 17 May 23 nicklas 337       else if ("GetTransportBoxesToMove".equals(cmd))
7173 17 May 23 nicklas 338       {
7173 17 May 23 nicklas 339         dc = sc.newDbControl(":Transport box registration");
7173 17 May 23 nicklas 340         
7173 17 May 23 nicklas 341         // Find transport boxes
7173 17 May 23 nicklas 342         ItemQuery<ItemList> query = ItemList.getQuery();
7173 17 May 23 nicklas 343         query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
7173 17 May 23 nicklas 344         query.restrict(Restrictions.eq(Hql.property("externalId"), Expressions.string(TransportBoxImporter.WORK_LIST_ID)));
7187 22 May 23 nicklas 345         query.join(Annotations.leftJoin(null, Annotationtype.MOVE_DATE.load(dc), "md"));
7187 22 May 23 nicklas 346         query.restrict(Restrictions.eq(Hql.alias("md"), null));
7173 17 May 23 nicklas 347         query.order(Orders.asc(Hql.property("id")));
7173 17 May 23 nicklas 348         JSONArray jsonBoxes = new JSONArray();
7173 17 May 23 nicklas 349         for (ItemList list : query.list(dc))
7173 17 May 23 nicklas 350         {
7173 17 May 23 nicklas 351           JSONObject jsonBox = new JSONObject();
7173 17 May 23 nicklas 352           jsonBox.put("id", list.getId());
7173 17 May 23 nicklas 353           jsonBox.put("name", list.getName());
7173 17 May 23 nicklas 354           jsonBox.put("size", list.getSize());
7184 22 May 23 nicklas 355           jsonBox.put("comments", list.getDescription());
7173 17 May 23 nicklas 356           
7173 17 May 23 nicklas 357           jsonBoxes.add(jsonBox);
7173 17 May 23 nicklas 358         }
7173 17 May 23 nicklas 359         json.put("transportBoxes", jsonBoxes);
7173 17 May 23 nicklas 360       }
7173 17 May 23 nicklas 361       else if ("GetTransportBoxDetailsForMove".equals(cmd))
7173 17 May 23 nicklas 362       {
7173 17 May 23 nicklas 363         int listId = Values.getInt(req.getParameter("listId"));
7173 17 May 23 nicklas 364         dc = sc.newDbControl(":Move external samples protocol");
7173 17 May 23 nicklas 365         
7173 17 May 23 nicklas 366         ItemList transportBox = ItemList.getById(dc, listId);
7173 17 May 23 nicklas 367         JSONObject jsonTransportBox = new JSONObject();
7173 17 May 23 nicklas 368         jsonTransportBox.put("id", transportBox.getId());
7173 17 May 23 nicklas 369         jsonTransportBox.put("name", transportBox.getName());
7186 22 May 23 nicklas 370         jsonTransportBox.put("comments", transportBox.getDescription());
7173 17 May 23 nicklas 371         jsonTransportBox.put("size", transportBox.getSize());
7175 17 May 23 nicklas 372         jsonTransportBox.put("externalRef", Annotationtype.EXTERNAL_REF.getAnnotationValue(dc, transportBox));
7173 17 May 23 nicklas 373         json.put("transportBox", jsonTransportBox);
7173 17 May 23 nicklas 374         
7173 17 May 23 nicklas 375         List<String> messages = (List<String>)Annotationtype.TRANSPORT_MESSAGES.getAnnotationValues(dc, transportBox);
7173 17 May 23 nicklas 376         JSONArray jsonTransportMessages = new JSONArray();
7173 17 May 23 nicklas 377         if (messages != null && messages.size() > 0)
7173 17 May 23 nicklas 378         {
7173 17 May 23 nicklas 379           jsonTransportMessages.addAll(messages);
7173 17 May 23 nicklas 380         }
7173 17 May 23 nicklas 381         jsonTransportBox.put("messages", jsonTransportMessages);
7173 17 May 23 nicklas 382         
7184 22 May 23 nicklas 383         // We want to extract prefixes from Clarity ID. For example: cmd:ALL557A123 --> ALL557A
7184 22 May 23 nicklas 384         Pattern prefixPattern = Pattern.compile("^[a-z]*:?((\\w+?)\\d+)$");
7184 22 May 23 nicklas 385         
7173 17 May 23 nicklas 386         JSONArray jsonSamples = new JSONArray();
7184 22 May 23 nicklas 387         Set<String> prefixes = new HashSet<String>(); // Prefixes used in Clarity ID for the samples in this box
7173 17 May 23 nicklas 388         ItemQuery<MeasuredBioMaterial> query = transportBox.getMembers();
7186 22 May 23 nicklas 389         query.include(Reggie.INCLUDE_IN_CURRENT_PROJECT);
7173 17 May 23 nicklas 390         query.join(Hql.innerJoin(null, "bioWell", "bw", true));
7173 17 May 23 nicklas 391         query.join(Hql.innerJoin("bw", "bioPlate", "bp"));
7173 17 May 23 nicklas 392         query.order(Orders.asc(Hql.property("bp", "name")));
7173 17 May 23 nicklas 393         query.order(Orders.asc(Hql.property("bw", "row")));
7173 17 May 23 nicklas 394         query.order(Orders.asc(Hql.property("bw", "column")));
7173 17 May 23 nicklas 395         Set<BioPlate> storageBoxes = new LinkedHashSet<>();
7173 17 May 23 nicklas 396         ItemSubtype specimenType = Subtype.SPECIMEN.get(dc);
7173 17 May 23 nicklas 397         for (MeasuredBioMaterial bm : query.list(dc))
7173 17 May 23 nicklas 398         {
7173 17 May 23 nicklas 399           JSONObject jsonBM = new JSONObject();
7173 17 May 23 nicklas 400           jsonBM.put("id", bm.getId());
7173 17 May 23 nicklas 401           jsonBM.put("name", bm.getName());
7208 26 May 23 nicklas 402           jsonBM.put("remain", bm.getRemainingQuantity());
7208 26 May 23 nicklas 403           jsonBM.put("type", bm.getItemSubtype().getName());
7173 17 May 23 nicklas 404           
7173 17 May 23 nicklas 405           MeasuredBioMaterial parent = bm;
7173 17 May 23 nicklas 406           while (!parent.getItemSubtype().equals(specimenType))
7173 17 May 23 nicklas 407           {
7173 17 May 23 nicklas 408             parent = (MeasuredBioMaterial)parent.getParent();
7173 17 May 23 nicklas 409           }
7184 22 May 23 nicklas 410           String externalRef = (String)Annotationtype.EXTERNAL_REF.getAnnotationValue(dc, parent);
7184 22 May 23 nicklas 411           if (externalRef != null) 
7184 22 May 23 nicklas 412           {
7184 22 May 23 nicklas 413             Matcher m = prefixPattern.matcher(externalRef);
7184 22 May 23 nicklas 414             if (m.matches()) 
7184 22 May 23 nicklas 415             {
7184 22 May 23 nicklas 416               prefixes.add(m.group(2));
7184 22 May 23 nicklas 417               jsonBM.put("clarityId", m.group(1));
7184 22 May 23 nicklas 418             }
7184 22 May 23 nicklas 419           }
7173 17 May 23 nicklas 420           
7184 22 May 23 nicklas 421           jsonBM.put("externalRef", externalRef);
7173 17 May 23 nicklas 422           jsonBM.put("specimenName", parent.getName());
7173 17 May 23 nicklas 423           jsonBM.put("comment", parent.getDescription());
7173 17 May 23 nicklas 424           
7173 17 May 23 nicklas 425           BioWell well = bm.getBioWell();
7173 17 May 23 nicklas 426           BioPlate storageBox = well.getPlate();
7173 17 May 23 nicklas 427           storageBoxes.add(storageBox);
7173 17 May 23 nicklas 428           jsonBM.put("well", JsonUtil.getBioWellAsJSON(well, true));
7173 17 May 23 nicklas 429           jsonSamples.add(jsonBM);
7173 17 May 23 nicklas 430         }
7173 17 May 23 nicklas 431         json.put("samples", jsonSamples);
7184 22 May 23 nicklas 432         JSONArray jsonPrefixes = new JSONArray();
7184 22 May 23 nicklas 433         jsonPrefixes.addAll(prefixes);
7184 22 May 23 nicklas 434         json.put("prefixes", jsonPrefixes);
7173 17 May 23 nicklas 435         
7173 17 May 23 nicklas 436         JSONArray jsonStorageBoxes = new JSONArray();
7173 17 May 23 nicklas 437         for (BioPlate storageBox : storageBoxes)
7173 17 May 23 nicklas 438         {
7189 22 May 23 nicklas 439           Hardware freezer = storageBox.getFreezer();
7173 17 May 23 nicklas 440           JSONObject jsonStorageBox = new JSONObject();
7173 17 May 23 nicklas 441           jsonStorageBox.put("id", storageBox.getId());
7173 17 May 23 nicklas 442           jsonStorageBox.put("name", storageBox.getName());
7189 22 May 23 nicklas 443           if (freezer != null) jsonStorageBox.put("freezer", freezer.getName());
7173 17 May 23 nicklas 444           jsonStorageBoxes.add(jsonStorageBox);
7173 17 May 23 nicklas 445         }
7173 17 May 23 nicklas 446         json.put("storageBoxes", jsonStorageBoxes);
7173 17 May 23 nicklas 447       }
6178 23 Mar 21 nicklas 448     }
6178 23 Mar 21 nicklas 449     catch (Throwable t)
6178 23 Mar 21 nicklas 450     {
6178 23 Mar 21 nicklas 451       t.printStackTrace();
6208 12 Apr 21 nicklas 452       if (json != null)
6208 12 Apr 21 nicklas 453       {
6208 12 Apr 21 nicklas 454         json.clear();
6208 12 Apr 21 nicklas 455         json.put("status", "error");
6208 12 Apr 21 nicklas 456         json.put("message", t.getMessage());
6208 12 Apr 21 nicklas 457         json.put("stacktrace", ThrowableUtil.stackTraceToString(t));
6208 12 Apr 21 nicklas 458       }
6208 12 Apr 21 nicklas 459       else
6208 12 Apr 21 nicklas 460       {
6208 12 Apr 21 nicklas 461         resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, t.getMessage());
6208 12 Apr 21 nicklas 462       }
6178 23 Mar 21 nicklas 463     }
6178 23 Mar 21 nicklas 464     finally
6178 23 Mar 21 nicklas 465     {
6178 23 Mar 21 nicklas 466       if (dc != null) dc.close();
6208 12 Apr 21 nicklas 467       if (json != null) json.writeJSONString(resp.getWriter());
6178 23 Mar 21 nicklas 468     }
6178 23 Mar 21 nicklas 469     
6178 23 Mar 21 nicklas 470   }
6178 23 Mar 21 nicklas 471
7195 24 May 23 nicklas 472   @SuppressWarnings("unchecked")
6178 23 Mar 21 nicklas 473   @Override
6178 23 Mar 21 nicklas 474   protected void doPost(HttpServletRequest req, HttpServletResponse resp)
6178 23 Mar 21 nicklas 475     throws ServletException, IOException 
6178 23 Mar 21 nicklas 476   {
6178 23 Mar 21 nicklas 477     String cmd = req.getParameter("cmd");
6178 23 Mar 21 nicklas 478     JsonUtil.setJsonResponseHeaders(resp);
6178 23 Mar 21 nicklas 479     
6178 23 Mar 21 nicklas 480     JSONObject json = new JSONObject();
6178 23 Mar 21 nicklas 481     json.put("status", "ok");
6178 23 Mar 21 nicklas 482     JSONArray jsonMessages = new JSONArray();
6178 23 Mar 21 nicklas 483   
6178 23 Mar 21 nicklas 484     final SessionControl sc = Reggie.getSessionControl(req);
6178 23 Mar 21 nicklas 485     DbControl dc = null;
7167 12 May 23 nicklas 486     boolean forceCount = true;
6178 23 Mar 21 nicklas 487     try
6178 23 Mar 21 nicklas 488     {
6178 23 Mar 21 nicklas 489
6178 23 Mar 21 nicklas 490       if ("ImportFromJSON".equals(cmd))
6178 23 Mar 21 nicklas 491       {
6337 16 Jun 21 nicklas 492         dc = sc.newDbControl(":Import externally processed samples");
6178 23 Mar 21 nicklas 493
6178 23 Mar 21 nicklas 494         ReggieRole.checkPermission(dc, "'" + cmd + "' wizard", ReggieRole.ADMINISTRATOR);
6178 23 Mar 21 nicklas 495
6178 23 Mar 21 nicklas 496         JSONObject jsonReq = JsonUtil.parseRequest(req);
6178 23 Mar 21 nicklas 497         JSONArray jsonItems = (JSONArray)jsonReq.get("items");
6211 14 Apr 21 nicklas 498         JSONObject jsonAutoAnalyze = (JSONObject)jsonReq.get("autoAnalyze");
6212 14 Apr 21 nicklas 499         String operator = Values.getStringOrNull((String)jsonReq.get("operator"));
6914 01 Dec 22 nicklas 500         boolean getDebugMessages = Boolean.TRUE.equals(jsonReq.get("getDebugMessages"));
6178 23 Mar 21 nicklas 501
6211 14 Apr 21 nicklas 502         OpenGridCluster cluster = null;
6211 14 Apr 21 nicklas 503         if (jsonAutoAnalyze != null)
6178 23 Mar 21 nicklas 504         {
6211 14 Apr 21 nicklas 505           String clusterId = (String)jsonAutoAnalyze.get("cluster");
6211 14 Apr 21 nicklas 506           cluster = OpenGridService.getInstance().getClusterById(dc, clusterId);
6211 14 Apr 21 nicklas 507           if (cluster == null)
6211 14 Apr 21 nicklas 508           {
6211 14 Apr 21 nicklas 509             throw new ItemNotFoundException("OpenGridCluster[" + clusterId + "]");
6211 14 Apr 21 nicklas 510           }
6178 23 Mar 21 nicklas 511         }
6211 14 Apr 21 nicklas 512
6209 13 Apr 21 nicklas 513         FileServer importGateway = Fileserver.IMPORT_GATEWAY.load(dc);
6209 13 Apr 21 nicklas 514         FileServer importArchive = Fileserver.IMPORT_ARCHIVE.load(dc);
7025 08 Feb 23 nicklas 515         FastDateFormat year = FastDateFormat.getInstance("/yyyy");
6209 13 Apr 21 nicklas 516         
6209 13 Apr 21 nicklas 517         String gatewayRoot = ScriptUtil.checkValidPath(importGateway.getRootPath(), true, false);
6209 13 Apr 21 nicklas 518         String archiveRoot = ScriptUtil.checkValidPath(importArchive.getRootPath(), true, false);
6209 13 Apr 21 nicklas 519         RemoteSession gatewaySession = null;
6209 13 Apr 21 nicklas 520         RemoteSession archiveSession = null;
6193 30 Mar 21 nicklas 521         try
6193 30 Mar 21 nicklas 522         {
6209 13 Apr 21 nicklas 523           gatewaySession = new RemoteHost(new ConnectionInfo(importGateway)).connect(5);
6209 13 Apr 21 nicklas 524           archiveSession = new RemoteHost(new ConnectionInfo(importArchive)).connect(5);
6215 16 Apr 21 nicklas 525           List<DemuxedSequences> demuxedSequences = new ArrayList<>(); // Collect DemuxedSequences that has been created by the importer
6913 30 Nov 22 nicklas 526
6913 30 Nov 22 nicklas 527           SimpleProgressReporter progress = new SimpleProgressReporter(null);
6913 30 Nov 22 nicklas 528           sc.setSessionSetting("import-json-progress", progress);
6913 30 Nov 22 nicklas 529           progress.display(1, "Importing from JSON files on "+importGateway.getName()+":"+importGateway.getRootPath()+"...");
6913 30 Nov 22 nicklas 530
6913 30 Nov 22 nicklas 531           int numProcessed = 0;
6913 30 Nov 22 nicklas 532           int numImported = 0;
6913 30 Nov 22 nicklas 533           int numWithError = 0;
6913 30 Nov 22 nicklas 534           int numItems = jsonItems.size();
6193 30 Mar 21 nicklas 535           for (int itemNo = 0; itemNo < jsonItems.size(); itemNo++)
6193 30 Mar 21 nicklas 536           {
6210 14 Apr 21 nicklas 537             // We use one transaction per JSON file
6337 16 Jun 21 nicklas 538             if (dc.isClosed()) dc = sc.newDbControl(dc.getName());
6210 14 Apr 21 nicklas 539             
6736 10 May 22 nicklas 540             ItemList flaggedRNA = BiomaterialList.FLAGGED_RNA.get(dc);
6193 30 Mar 21 nicklas 541             JSONObject jsonItem = (JSONObject)jsonItems.get(itemNo);
6193 30 Mar 21 nicklas 542             Number itemId = (Number)jsonItem.get("id");
6736 10 May 22 nicklas 543             boolean flagRNA = Boolean.TRUE.equals(jsonItem.get("flagRNA"));
6201 09 Apr 21 nicklas 544             JsonFile jsonFile = new JsonFile(dc, (String)jsonItem.get("jsonFile"));
6913 30 Nov 22 nicklas 545             
6913 30 Nov 22 nicklas 546             progress.display(2+(85*itemNo)/numItems, "Importing from '"+jsonFile.getName()+"'... ("+(itemNo+1)+" of "+numItems+
6913 30 Nov 22 nicklas 547               " files on " + importGateway.getName()+":"+importGateway.getRootPath()+")");
6913 30 Nov 22 nicklas 548             //Thread.sleep(5000);
6913 30 Nov 22 nicklas 549             
6897 29 Nov 22 nicklas 550             jsonFile.downloadAndParse(gatewaySession, gatewayRoot, true, null, null);
6212 14 Apr 21 nicklas 551             if (operator != null) jsonFile.setOperator(operator);
6913 30 Nov 22 nicklas 552
6913 30 Nov 22 nicklas 553             numProcessed++;
6198 07 Apr 21 nicklas 554             if (jsonFile.hasError())
6198 07 Apr 21 nicklas 555             {
6913 30 Nov 22 nicklas 556               numWithError++;
6199 08 Apr 21 nicklas 557               jsonMessages.add("[Error]["+jsonFile.getName()+"] Import failed (see below for more information)");
6199 08 Apr 21 nicklas 558               jsonMessages.addAll(prefix("[Error]["+jsonFile.getName()+"] ", jsonFile.getErrorMessages()));
6209 13 Apr 21 nicklas 559               dc.close();
6198 07 Apr 21 nicklas 560             }
6198 07 Apr 21 nicklas 561             else
6198 07 Apr 21 nicklas 562             {
6498 01 Dec 21 nicklas 563               ExternalSpecimenImporter importer = new ExternalSpecimenImporter();
6341 29 Jun 21 nicklas 564               ImportedItems items = null;
6341 29 Jun 21 nicklas 565               MainInfo main = jsonFile.getMain();
6341 29 Jun 21 nicklas 566               ScanBIdRef idRef = main.idRef;
6495 01 Dec 21 nicklas 567               if (idRef.idType == SampleIdType.CASE || idRef.idType == SampleIdType.PRENORMALISED_RNA)
6341 29 Jun 21 nicklas 568               {
7050 17 Feb 23 nicklas 569                 items = importer.doImport(dc, jsonFile, importGateway);
6341 29 Jun 21 nicklas 570               }
6348 16 Aug 21 nicklas 571               else
6348 16 Aug 21 nicklas 572               {
6348 16 Aug 21 nicklas 573                 jsonMessages.add("[Error]["+jsonFile.getName()+"] Importing to "+idRef.idType+" is not yet supported");
6348 16 Aug 21 nicklas 574               }
6734 09 May 22 nicklas 575               if (items != null && items.importedTo != null)
6210 14 Apr 21 nicklas 576               {
6913 30 Nov 22 nicklas 577                 numImported++;
6913 30 Nov 22 nicklas 578
6734 09 May 22 nicklas 579                 String jsonCopyFolder = year.format((jsonFile.getLastModifiedDate()))+"/_NO_FASTQ";
6734 09 May 22 nicklas 580                 if (items.demux != null)
6734 09 May 22 nicklas 581                 {
6734 09 May 22 nicklas 582                   // Add to FASTQ import pipeline
6734 09 May 22 nicklas 583                   BiomaterialList.FASTQ_IMPORT_PIPELINE.get(dc).add(items.demux.getItem());
6734 09 May 22 nicklas 584                   jsonCopyFolder = (String)Annotationtype.DATA_FILES_FOLDER.getAnnotationValue(dc, items.demux.getItem());
6734 09 May 22 nicklas 585                   demuxedSequences.add(items.demux);
6734 09 May 22 nicklas 586                 }
6734 09 May 22 nicklas 587                 if (jsonCopyFolder != null)
6734 09 May 22 nicklas 588                 {
6734 09 May 22 nicklas 589                   // Save the JSON to Fileserver.IMPORT_ARCHIVE
6734 09 May 22 nicklas 590                   jsonFile.saveTo(archiveSession, archiveRoot + jsonCopyFolder);
6960 13 Dec 22 nicklas 591                   // Create a link betweem the specimen and archived JSON file
7240 07 Jun 23 nicklas 592                   importer.createJsonLink(dc, jsonFile, items.importedTo, importArchive, jsonCopyFolder);
6734 09 May 22 nicklas 593                 }
6736 10 May 22 nicklas 594                 if (flagRNA && items.rna != null)
6736 10 May 22 nicklas 595                 {
6736 10 May 22 nicklas 596                   // Flag the RNA
6736 10 May 22 nicklas 597                   flaggedRNA.add(items.rna.getExtract());
6736 10 May 22 nicklas 598                   Annotationtype.FLAG.setAnnotationValue(dc, items.rna.getExtract(), Rna.FLAG_FASTQ_IMPORT_FAILED);
6736 10 May 22 nicklas 599                 }
6736 10 May 22 nicklas 600                 String itemType = ((Subtypable)items.importedTo).getItemSubtype().getName();
7032 10 Feb 23 nicklas 601                 ActivityDef.JSON_IMPORT_COMPLETED.merge(dc, 1);
6348 16 Aug 21 nicklas 602                 dc.commit();
6914 01 Dec 22 nicklas 603                 jsonMessages.add("[HTML]"+(jsonFile.hasWarning()?"[Warning]":"")+
6914 01 Dec 22 nicklas 604                     "["+jsonFile.getName()+"] Imported data from <b>"+itemType+"</b> ("+
6914 01 Dec 22 nicklas 605                     HTML.encodeTags(items.importedTo.getName())+ ") to <b>"+main.endPoint.getName()+"</b> ("+
6914 01 Dec 22 nicklas 606                     HTML.encodeTags(main.endPoint.getEndPointItem(items).getName())+"). "+
6914 01 Dec 22 nicklas 607                     (jsonFile.hasWarning()?"<b>"+jsonFile.getWarningMessages().size()+" warnings</b>":""));
6913 30 Nov 22 nicklas 608                 
6736 10 May 22 nicklas 609                 if (flagRNA && items.rna != null)
6736 10 May 22 nicklas 610                 {
6736 10 May 22 nicklas 611                   jsonMessages.add("["+jsonFile.getName()+"] Flagged RNA: "+items.rna.getName());
6736 10 May 22 nicklas 612                 }
6734 09 May 22 nicklas 613                 if (jsonCopyFolder != null)
6734 09 May 22 nicklas 614                 {
6734 09 May 22 nicklas 615                   // Remove JSON from Filesever.IMPORT_GATEWAY
6734 09 May 22 nicklas 616                   jsonFile.deleteFrom(gatewaySession, gatewayRoot);
6734 09 May 22 nicklas 617                 }
6348 16 Aug 21 nicklas 618                 if (jsonFile.hasError())
6348 16 Aug 21 nicklas 619                 {
6348 16 Aug 21 nicklas 620                   jsonMessages.addAll(prefix("[Warning]["+jsonFile.getName()+"] ", jsonFile.getErrorMessages()));
6348 16 Aug 21 nicklas 621                 }
6210 14 Apr 21 nicklas 622               }
6734 09 May 22 nicklas 623               else 
6734 09 May 22 nicklas 624               {
6913 30 Nov 22 nicklas 625                 numWithError++;
6734 09 May 22 nicklas 626                 jsonMessages.add("[Error]["+jsonFile.getName()+"] No items created");
6913 30 Nov 22 nicklas 627                 dc.close();
6734 09 May 22 nicklas 628               }
6198 07 Apr 21 nicklas 629             }
6198 07 Apr 21 nicklas 630             
6914 01 Dec 22 nicklas 631             if (getDebugMessages)
6914 01 Dec 22 nicklas 632             {
6914 01 Dec 22 nicklas 633               jsonMessages.addAll(prefix("[Warning]["+jsonFile.getName()+"] ", jsonFile.getWarningMessages()));
6914 01 Dec 22 nicklas 634               jsonMessages.addAll(prefix("[Debug]["+jsonFile.getName()+"] ", jsonFile.getDebugMessages()));
6914 01 Dec 22 nicklas 635             }
6211 14 Apr 21 nicklas 636           }
6913 30 Nov 22 nicklas 637           
6913 30 Nov 22 nicklas 638           progress.display(90, "Import complete! Processed " + numProcessed + " JSON files; " + 
6913 30 Nov 22 nicklas 639               numImported + " successfully imported; "+numWithError+" with error.");
6913 30 Nov 22 nicklas 640           Thread.sleep(2000);
6215 16 Apr 21 nicklas 641
6348 16 Aug 21 nicklas 642           if (jsonAutoAnalyze != null && demuxedSequences.size() > 0)
6211 14 Apr 21 nicklas 643           {
6215 16 Apr 21 nicklas 644             boolean debug = Boolean.TRUE.equals(jsonAutoAnalyze.get("debug"));
6215 16 Apr 21 nicklas 645             boolean autoConfirm = Boolean.TRUE.equals(jsonAutoAnalyze.get("autoConfirm"));
6215 16 Apr 21 nicklas 646             Number priority = (Number)jsonAutoAnalyze.get("priority");
6981 17 Jan 23 nicklas 647             String partition = Values.getStringOrNull((String)jsonAutoAnalyze.get("partition"));
6215 16 Apr 21 nicklas 648             String clusterId = (String)jsonAutoAnalyze.get("cluster");
6215 16 Apr 21 nicklas 649             Number mergeSoftwareId = (Number)jsonAutoAnalyze.get("mergeSoftware");
6215 16 Apr 21 nicklas 650             Number mergeProtocolId = (Number)jsonAutoAnalyze.get("mergeProtocol");
7372 06 Oct 23 nicklas 651             String submitOptions = Values.getStringOrNull((String)jsonReq.get("submitOptionsOverride"));
6215 16 Apr 21 nicklas 652             
6913 30 Nov 22 nicklas 653             progress.display(95, "Submitting "+demuxedSequences.size()+" FASTQ import jobs to "+cluster.getConnectionInfo().getName());
6913 30 Nov 22 nicklas 654             Thread.sleep(2000);
6913 30 Nov 22 nicklas 655             
6337 16 Jun 21 nicklas 656             dc = sc.newDbControl(dc.getName());
6215 16 Apr 21 nicklas 657             try
6210 14 Apr 21 nicklas 658             {
6215 16 Apr 21 nicklas 659               ImportFastqJobCreator jobCreator = new ImportFastqJobCreator();
6215 16 Apr 21 nicklas 660               jobCreator.setAutoConfirm(autoConfirm);
6215 16 Apr 21 nicklas 661               jobCreator.setDebug(debug);
6215 16 Apr 21 nicklas 662               if (priority != null) jobCreator.setPriority(priority.intValue());
6981 17 Jan 23 nicklas 663               jobCreator.setPartition(partition);
7372 06 Oct 23 nicklas 664               jobCreator.setSubmitOptionsOverride(submitOptions);
6215 16 Apr 21 nicklas 665               jobCreator.setMergeProtocol(mergeProtocolId != null ? Protocol.getById(dc, mergeProtocolId.intValue()) : null);
6215 16 Apr 21 nicklas 666               jobCreator.setMergeSoftware(mergeSoftwareId != null ? Software.getById(dc, mergeSoftwareId.intValue()) : null);
6215 16 Apr 21 nicklas 667               
6215 16 Apr 21 nicklas 668               List<JobDefinition> jobDefs = jobCreator.createFastqImportJobs(dc, cluster, demuxedSequences);
6215 16 Apr 21 nicklas 669               List<Job> jobs = ScriptUtil.submitJobs(dc, cluster, jobDefs);
6215 16 Apr 21 nicklas 670               for (Job job : jobs)
6211 14 Apr 21 nicklas 671               {
6215 16 Apr 21 nicklas 672                 if (job.getStatus() == Job.Status.ERROR)
6215 16 Apr 21 nicklas 673                 {
6215 16 Apr 21 nicklas 674                   jsonMessages.add("[Warning]Job submission for '" + job.getName() + "' failed: " + job.getStatusMessage());
6215 16 Apr 21 nicklas 675                 }
6215 16 Apr 21 nicklas 676                 else
6215 16 Apr 21 nicklas 677                 {
6215 16 Apr 21 nicklas 678                   jsonMessages.add("Submitted "+job.getName()+" to "+cluster.getConnectionInfo().getName()+" with id "+job.getExternalId());
6215 16 Apr 21 nicklas 679                 }
6211 14 Apr 21 nicklas 680               }
6215 16 Apr 21 nicklas 681               dc.commit();
6210 14 Apr 21 nicklas 682             }
6215 16 Apr 21 nicklas 683             catch (Exception ex)
6215 16 Apr 21 nicklas 684             {
6215 16 Apr 21 nicklas 685               jsonMessages.add("[Warning]Job submission for FASTQ import failed: "+ ex.getMessage());
6215 16 Apr 21 nicklas 686             }
6193 30 Mar 21 nicklas 687           }
6913 30 Nov 22 nicklas 688           
6913 30 Nov 22 nicklas 689           sc.setSessionSetting("import-json-progress", null);
6193 30 Mar 21 nicklas 690         }
6193 30 Mar 21 nicklas 691         finally
6178 23 Mar 21 nicklas 692         {
6209 13 Apr 21 nicklas 693           OpenGrid.close(gatewaySession);
6209 13 Apr 21 nicklas 694           OpenGrid.close(archiveSession);
6178 23 Mar 21 nicklas 695         }
6178 23 Mar 21 nicklas 696       }
7139 27 Apr 23 nicklas 697       else if ("PreValidateTransportFile".equals(cmd) || "ImportFromTransportFile".equals(cmd))
7139 27 Apr 23 nicklas 698       {
7139 27 Apr 23 nicklas 699         String path = Values.getStringOrNull(req.getParameter("path"));
7139 27 Apr 23 nicklas 700         String sheet = Values.getStringOrNull(req.getParameter("sheet"));
7142 04 May 23 nicklas 701         boolean validateOnly = "PreValidateTransportFile".equals(cmd);
7167 12 May 23 nicklas 702         if (validateOnly) forceCount = false;
7139 27 Apr 23 nicklas 703         
7139 27 Apr 23 nicklas 704         dc = sc.newDbControl(":Import specimen from transport boxes");
7162 12 May 23 nicklas 705
7162 12 May 23 nicklas 706         SimpleProgressReporter progress = new SimpleProgressReporter(null);
7162 12 May 23 nicklas 707         sc.setSessionSetting("transport-box-import-progress", progress);
7161 11 May 23 nicklas 708         
7161 11 May 23 nicklas 709         TransportBoxImporter importer = new TransportBoxImporter();
7139 27 Apr 23 nicklas 710         if (!validateOnly)
7139 27 Apr 23 nicklas 711         {
7139 27 Apr 23 nicklas 712           ReggieRole.checkPermission(dc, "'" + cmd + "' wizard", ReggieRole.ADMINISTRATOR);
7161 11 May 23 nicklas 713           JSONObject jsonReq = JsonUtil.parseRequest(req);
7191 23 May 23 nicklas 714           importer.setRequestParameters(jsonReq);
7139 27 Apr 23 nicklas 715         }
7139 27 Apr 23 nicklas 716         File importFile = File.getByPath(dc, new Path(path, Path.Type.FILE), false);
7139 27 Apr 23 nicklas 717         boolean fileIsValidForImport = false;
7139 27 Apr 23 nicklas 718         List<String> sheetNames = null;
7139 27 Apr 23 nicklas 719         JSONObject jsonImportFile = new JSONObject();
7185 22 May 23 nicklas 720         
7185 22 May 23 nicklas 721         fileIsValidForImport = importer.doImport(dc, importFile, sheet, validateOnly, progress);
7185 22 May 23 nicklas 722         sheetNames = importer.getWorksheets();
7185 22 May 23 nicklas 723         String fileName = importFile.getName();
7185 22 May 23 nicklas 724         if (sheetNames != null) fileName += "/" + importer.getParsedWorksheet();
7185 22 May 23 nicklas 725         jsonImportFile.put("filename", fileName);
6178 23 Mar 21 nicklas 726
7139 27 Apr 23 nicklas 727         jsonImportFile.put("valid", fileIsValidForImport);
7141 02 May 23 nicklas 728         jsonImportFile.put("warnings", importer.getTotalWarnings());
7141 02 May 23 nicklas 729         jsonImportFile.put("errors", importer.getTotalErrors());
7143 05 May 23 nicklas 730         jsonImportFile.put("numSamples", importer.getNumSamples());
7139 27 Apr 23 nicklas 731         jsonImportFile.put("numBoxes", importer.getNumBoxes());
7143 05 May 23 nicklas 732         jsonImportFile.put("numMappedToSpecimen", importer.getMappedToSpecimen());
7143 05 May 23 nicklas 733         jsonImportFile.put("numMappedToNoSpecimen", importer.getMappedToNoSpecimen());
7143 05 May 23 nicklas 734         jsonImportFile.put("numMappedToCase", importer.getMappedToCase());
7143 05 May 23 nicklas 735         jsonImportFile.put("numMappedToBlood", importer.getMappedToBlood());
7143 05 May 23 nicklas 736         jsonImportFile.put("numMappedToNothing", importer.getMappedToNothing());
7143 05 May 23 nicklas 737         jsonImportFile.put("numNoConsent", importer.getNumNoConsent());
7143 05 May 23 nicklas 738         
7139 27 Apr 23 nicklas 739         if (sheetNames != null) jsonImportFile.put("sheetNames", sheetNames);
7139 27 Apr 23 nicklas 740         json.put("importFile", jsonImportFile);
7139 27 Apr 23 nicklas 741
7191 23 May 23 nicklas 742         JSONArray jsonBoxes = new JSONArray();
7191 23 May 23 nicklas 743         for (Box b : importer.getBoxes())
7191 23 May 23 nicklas 744         {
7191 23 May 23 nicklas 745           jsonBoxes.add(b.toJSONObject());
7191 23 May 23 nicklas 746         }
7191 23 May 23 nicklas 747         json.put("boxes", jsonBoxes);
7191 23 May 23 nicklas 748         
7139 27 Apr 23 nicklas 749         JSONArray jsonSpecimen = new JSONArray();
7139 27 Apr 23 nicklas 750         for (SampleEntry s : importer.getSpecimen())
7139 27 Apr 23 nicklas 751         {
7139 27 Apr 23 nicklas 752           jsonSpecimen.add(s.toJSONObject());
7139 27 Apr 23 nicklas 753         }
7139 27 Apr 23 nicklas 754         json.put("specimen", jsonSpecimen);
7139 27 Apr 23 nicklas 755         
7142 04 May 23 nicklas 756         if (validateOnly)
7139 27 Apr 23 nicklas 757         {
7142 04 May 23 nicklas 758           jsonMessages.addAll(importer.getMessages());
7139 27 Apr 23 nicklas 759         }
7139 27 Apr 23 nicklas 760         else
7139 27 Apr 23 nicklas 761         {
7142 04 May 23 nicklas 762           if (fileIsValidForImport)
7139 27 Apr 23 nicklas 763           {
7142 04 May 23 nicklas 764             jsonMessages.addAll(importer.getMessages());
7144 05 May 23 nicklas 765             jsonMessages.addAll(importer.getDebugMessages());
7144 05 May 23 nicklas 766             ActivityDef.TRANSPORT_BOX_IMPORT_COMPLETED.merge(dc, importer.getNumBoxes(), importer.getNumSamples());
7173 17 May 23 nicklas 767             progress.display(99, "Saving to database...");
7186 22 May 23 nicklas 768             dc.commit();
7139 27 Apr 23 nicklas 769           }
7142 04 May 23 nicklas 770           else
7142 04 May 23 nicklas 771           {
7142 04 May 23 nicklas 772             jsonMessages.add("[Error] Import failed");
7142 04 May 23 nicklas 773             jsonMessages.addAll(importer.getErrorMessages());
7142 04 May 23 nicklas 774           }
7139 27 Apr 23 nicklas 775         }
7139 27 Apr 23 nicklas 776       }
7186 22 May 23 nicklas 777       else if ("RegisterMoveComplete".equals(cmd))
7186 22 May 23 nicklas 778       {
7186 22 May 23 nicklas 779         dc = sc.newDbControl(":Move external specimen");
7186 22 May 23 nicklas 780         
7186 22 May 23 nicklas 781         ReggieRole.checkPermission(dc, "'" + cmd + "' wizard", ReggieRole.SAMPLE_PREP, ReggieRole.ADMINISTRATOR);
7186 22 May 23 nicklas 782         JSONObject jsonReq = JsonUtil.parseRequest(req);
7186 22 May 23 nicklas 783         JSONArray jsonMissing = (JSONArray)jsonReq.get("missingSamples");
7186 22 May 23 nicklas 784         Number boxId = (Number)jsonReq.get("transportBox");
7186 22 May 23 nicklas 785         Date moveDate = Reggie.CONVERTER_STRING_TO_DATE.convert((String)jsonReq.get("moveDate"));
7186 22 May 23 nicklas 786         String moveOperator = Values.getStringOrNull((String)jsonReq.get("moveOperator"));
7186 22 May 23 nicklas 787         String extraSamples = Values.getStringOrNull((String)jsonReq.get("extraSamples"));
7186 22 May 23 nicklas 788         String comments = Values.getStringOrNull((String)jsonReq.get("comments"));
7186 22 May 23 nicklas 789         
7186 22 May 23 nicklas 790         ItemList transportBox = ItemList.getById(dc, boxId.intValue());
7186 22 May 23 nicklas 791         Annotationtype.MOVE_DATE.setAnnotationValue(dc, transportBox, moveDate);
7186 22 May 23 nicklas 792         Annotationtype.MOVE_OPERATOR.setAnnotationValue(dc, transportBox, moveOperator);
7195 24 May 23 nicklas 793         List<String> transportMessages = new ArrayList<>((List<String>)Annotationtype.TRANSPORT_MESSAGES.getAnnotationValues(dc, transportBox));
7195 24 May 23 nicklas 794         int numMessages = transportMessages.size();
7195 24 May 23 nicklas 795         if (extraSamples != null) transportMessages.add("Extra samples left in the box: "+extraSamples);
7186 22 May 23 nicklas 796         transportBox.setDescription(comments);
7186 22 May 23 nicklas 797         
7195 24 May 23 nicklas 798         // Register missing sample tubes
7195 24 May 23 nicklas 799         for (int missingNo = 0; missingNo < jsonMissing.size(); missingNo++)
7186 22 May 23 nicklas 800         {
7195 24 May 23 nicklas 801           JSONObject jm = (JSONObject)jsonMissing.get(missingNo);
7195 24 May 23 nicklas 802           Number itemId = (Number)jm.get("id");
7195 24 May 23 nicklas 803           String clarityId = (String)jm.get("clarityId");
7195 24 May 23 nicklas 804           MeasuredBioMaterial missing = transportBox.getMemberType().getById(dc, itemId.intValue());
7195 24 May 23 nicklas 805           Annotationtype.FLAG.setAnnotationValue(dc, missing, SpecimenTube.FLAG_MISSING_IN_TRANSPORT_BOX);
7195 24 May 23 nicklas 806           transportMessages.add(clarityId + " ("+missing.getName()+") was missing in the transport box");
7186 22 May 23 nicklas 807         }
7186 22 May 23 nicklas 808         
7195 24 May 23 nicklas 809         // Clear the ExternalSpecimenExists annotation
7186 22 May 23 nicklas 810         ItemQuery<MeasuredBioMaterial> query = transportBox.getMembers();
7186 22 May 23 nicklas 811         query.include(Reggie.INCLUDE_IN_CURRENT_PROJECT);
7186 22 May 23 nicklas 812         for (MeasuredBioMaterial bm : query.list(dc))
7186 22 May 23 nicklas 813         {
7186 22 May 23 nicklas 814           Annotationtype.EXTERNAL_SPECIMEN_EXISTS.setAnnotationValue(dc, bm, null);
7186 22 May 23 nicklas 815         }
7195 24 May 23 nicklas 816         if (transportMessages.size() > numMessages)
7195 24 May 23 nicklas 817         {
7195 24 May 23 nicklas 818           Annotationtype.TRANSPORT_MESSAGES.setAnnotationValues(dc, transportBox, transportMessages);
7195 24 May 23 nicklas 819         }
7186 22 May 23 nicklas 820         
7195 24 May 23 nicklas 821         int movedSamples = transportBox.getSize()-jsonMissing.size();
7186 22 May 23 nicklas 822         ActivityDef.TRANSPORT_BOX_SAMPLES_MOVED.merge(dc, 1, movedSamples);
7186 22 May 23 nicklas 823         jsonMessages.add("Moved "+movedSamples+" samples from "+transportBox.getName());
7195 24 May 23 nicklas 824         if (jsonMissing.size() > 0)
7186 22 May 23 nicklas 825         {
7195 24 May 23 nicklas 826           jsonMessages.add("There was " + jsonMissing.size() + " missing sample(s)");
7186 22 May 23 nicklas 827         }
7186 22 May 23 nicklas 828         dc.commit();
7186 22 May 23 nicklas 829       }
7139 27 Apr 23 nicklas 830
6178 23 Mar 21 nicklas 831       json.put("messages", jsonMessages);
7167 12 May 23 nicklas 832       if (forceCount) CounterService.getInstance().setForceCount();
6178 23 Mar 21 nicklas 833     }
6178 23 Mar 21 nicklas 834     catch (Throwable t)
6178 23 Mar 21 nicklas 835     {
6178 23 Mar 21 nicklas 836       t.printStackTrace();
6178 23 Mar 21 nicklas 837       json.clear();
6178 23 Mar 21 nicklas 838       json.put("status", "error");
6178 23 Mar 21 nicklas 839       json.put("message", t.getMessage());
6178 23 Mar 21 nicklas 840       json.put("stacktrace", ThrowableUtil.stackTraceToString(t));
6178 23 Mar 21 nicklas 841     }
6178 23 Mar 21 nicklas 842     finally
6178 23 Mar 21 nicklas 843     {
6178 23 Mar 21 nicklas 844       if (dc != null) dc.close();
6178 23 Mar 21 nicklas 845       json.writeJSONString(resp.getWriter());
6198 07 Apr 21 nicklas 846     }    
6178 23 Mar 21 nicklas 847   }
6178 23 Mar 21 nicklas 848   
6199 08 Apr 21 nicklas 849   /**
6199 08 Apr 21 nicklas 850     Add a prefix to all messages.
6199 08 Apr 21 nicklas 851   */
6199 08 Apr 21 nicklas 852   private List<String> prefix(String prefix, List<String> messages)
6199 08 Apr 21 nicklas 853   {
6199 08 Apr 21 nicklas 854     if (messages.size() == 0) return Collections.emptyList();
6199 08 Apr 21 nicklas 855     List<String> out = new ArrayList<>(messages.size());
6199 08 Apr 21 nicklas 856     for (String m : messages)
6199 08 Apr 21 nicklas 857     {
6199 08 Apr 21 nicklas 858       out.add(prefix+m);
6199 08 Apr 21 nicklas 859     }
6199 08 Apr 21 nicklas 860     return out;
6199 08 Apr 21 nicklas 861   }
6199 08 Apr 21 nicklas 862   
6965 10 Jan 23 nicklas 863   /**
6965 10 Jan 23 nicklas 864     Move entries from one map to another. If the entry is a JSONObject
6965 10 Jan 23 nicklas 865     also sort it by key.
6965 10 Jan 23 nicklas 866   */
6965 10 Jan 23 nicklas 867   private void moveJsonObject(String key, Map<String, Object> to, Map<String, Object> from)
6965 10 Jan 23 nicklas 868   {
6965 10 Jan 23 nicklas 869     Object t = from.remove(key);
6965 10 Jan 23 nicklas 870     if (t != null) 
6965 10 Jan 23 nicklas 871     {
6965 10 Jan 23 nicklas 872       if (t instanceof JSONObject) t = new TreeMap<>((JSONObject)t);
6965 10 Jan 23 nicklas 873       to.put(key, t);
6965 10 Jan 23 nicklas 874     }
6965 10 Jan 23 nicklas 875   }
6965 10 Jan 23 nicklas 876   
6178 23 Mar 21 nicklas 877 }