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

Code
Comments
Other
Rev Date Author Line
2839 20 Oct 14 olle 1 package net.sf.basedb.reggie.servlet;
2839 20 Oct 14 olle 2
2839 20 Oct 14 olle 3 import java.io.IOException;
3427 26 Jun 15 nicklas 4 import java.net.URI;
2839 20 Oct 14 olle 5 import java.util.ArrayList;
2839 20 Oct 14 olle 6 import java.util.Date;
2839 20 Oct 14 olle 7 import java.util.HashMap;
3425 25 Jun 15 nicklas 8 import java.util.HashSet;
3388 11 Jun 15 nicklas 9 import java.util.LinkedHashSet;
2839 20 Oct 14 olle 10 import java.util.List;
3390 11 Jun 15 nicklas 11 import java.util.Map;
3337 18 May 15 olle 12 import java.util.Set;
4269 15 Dec 16 nicklas 13 import java.util.TreeSet;
2839 20 Oct 14 olle 14 import java.util.regex.Matcher;
2839 20 Oct 14 olle 15 import java.util.regex.Pattern;
2839 20 Oct 14 olle 16
2839 20 Oct 14 olle 17 import javax.servlet.ServletException;
2839 20 Oct 14 olle 18 import javax.servlet.http.HttpServlet;
2839 20 Oct 14 olle 19 import javax.servlet.http.HttpServletRequest;
2839 20 Oct 14 olle 20 import javax.servlet.http.HttpServletResponse;
2839 20 Oct 14 olle 21
7024 07 Feb 23 nicklas 22 import org.apache.commons.lang3.time.FastDateFormat;
2839 20 Oct 14 olle 23 import org.json.simple.JSONArray;
2839 20 Oct 14 olle 24 import org.json.simple.JSONObject;
2839 20 Oct 14 olle 25
4512 31 May 17 nicklas 26 import net.sf.basedb.core.Annotatable;
3374 09 Jun 15 nicklas 27 import net.sf.basedb.core.AnyToAny;
3337 18 May 15 olle 28 import net.sf.basedb.core.BasicItem;
4312 18 Jan 17 nicklas 29 import net.sf.basedb.core.BioMaterial;
2839 20 Oct 14 olle 30 import net.sf.basedb.core.BioMaterialEvent;
2839 20 Oct 14 olle 31 import net.sf.basedb.core.BioSource;
2839 20 Oct 14 olle 32 import net.sf.basedb.core.DbControl;
2839 20 Oct 14 olle 33 import net.sf.basedb.core.DerivedBioAssay;
3391 11 Jun 15 nicklas 34 import net.sf.basedb.core.Directory;
2839 20 Oct 14 olle 35 import net.sf.basedb.core.Extract;
3374 09 Jun 15 nicklas 36 import net.sf.basedb.core.File;
3427 26 Jun 15 nicklas 37 import net.sf.basedb.core.FileServer;
3387 10 Jun 15 nicklas 38 import net.sf.basedb.core.FileSetMember;
3387 10 Jun 15 nicklas 39 import net.sf.basedb.core.FileStoreEnabled;
4512 31 May 17 nicklas 40 import net.sf.basedb.core.Item;
3337 18 May 15 olle 41 import net.sf.basedb.core.ItemProxy;
2839 20 Oct 14 olle 42 import net.sf.basedb.core.ItemQuery;
2839 20 Oct 14 olle 43 import net.sf.basedb.core.ItemSubtype;
3427 26 Jun 15 nicklas 44 import net.sf.basedb.core.Location;
5644 07 Oct 19 nicklas 45 import net.sf.basedb.core.MeasuredBioMaterial;
3337 18 May 15 olle 46 import net.sf.basedb.core.Nameable;
3391 11 Jun 15 nicklas 47 import net.sf.basedb.core.Path;
2839 20 Oct 14 olle 48 import net.sf.basedb.core.Permission;
2839 20 Oct 14 olle 49 import net.sf.basedb.core.PermissionDeniedException;
2839 20 Oct 14 olle 50 import net.sf.basedb.core.PhysicalBioAssay;
3337 18 May 15 olle 51 import net.sf.basedb.core.Removable;
2839 20 Oct 14 olle 52 import net.sf.basedb.core.Sample;
2839 20 Oct 14 olle 53 import net.sf.basedb.core.SessionControl;
3386 10 Jun 15 nicklas 54 import net.sf.basedb.core.Subtypable;
3337 18 May 15 olle 55 import net.sf.basedb.core.Trashcan;
4512 31 May 17 nicklas 56 import net.sf.basedb.core.Type;
3765 23 Feb 16 nicklas 57 import net.sf.basedb.core.query.Annotations;
3765 23 Feb 16 nicklas 58 import net.sf.basedb.core.query.Expressions;
2980 25 Nov 14 nicklas 59 import net.sf.basedb.core.query.Hql;
2980 25 Nov 14 nicklas 60 import net.sf.basedb.core.query.Orders;
3765 23 Feb 16 nicklas 61 import net.sf.basedb.core.query.Restrictions;
4306 17 Jan 17 nicklas 62 import net.sf.basedb.opengrid.CmdResult;
4306 17 Jan 17 nicklas 63 import net.sf.basedb.opengrid.OpenGrid;
4306 17 Jan 17 nicklas 64 import net.sf.basedb.opengrid.RemoteHost;
4306 17 Jan 17 nicklas 65 import net.sf.basedb.opengrid.RemoteSession;
4306 17 Jan 17 nicklas 66 import net.sf.basedb.opengrid.config.ConnectionInfo;
2839 20 Oct 14 olle 67 import net.sf.basedb.reggie.JsonUtil;
2839 20 Oct 14 olle 68 import net.sf.basedb.reggie.Reggie;
2839 20 Oct 14 olle 69 import net.sf.basedb.reggie.Site;
3323 11 May 15 nicklas 70 import net.sf.basedb.reggie.converter.StringToDateConverter;
3059 19 Dec 14 nicklas 71 import net.sf.basedb.reggie.counter.CounterService;
2839 20 Oct 14 olle 72 import net.sf.basedb.reggie.dao.Annotationtype;
2839 20 Oct 14 olle 73 import net.sf.basedb.reggie.dao.Blood;
3360 29 May 15 olle 74 import net.sf.basedb.reggie.dao.BloodDna;
2839 20 Oct 14 olle 75 import net.sf.basedb.reggie.dao.CDna;
2839 20 Oct 14 olle 76 import net.sf.basedb.reggie.dao.Case;
2839 20 Oct 14 olle 77 import net.sf.basedb.reggie.dao.Consent;
2839 20 Oct 14 olle 78 import net.sf.basedb.reggie.dao.Dna;
3427 26 Jun 15 nicklas 79 import net.sf.basedb.reggie.dao.Fileserver;
2839 20 Oct 14 olle 80 import net.sf.basedb.reggie.dao.FlowCell;
2839 20 Oct 14 olle 81 import net.sf.basedb.reggie.dao.FlowThrough;
2839 20 Oct 14 olle 82 import net.sf.basedb.reggie.dao.Histology;
2839 20 Oct 14 olle 83 import net.sf.basedb.reggie.dao.Library;
2839 20 Oct 14 olle 84 import net.sf.basedb.reggie.dao.Lysate;
2839 20 Oct 14 olle 85 import net.sf.basedb.reggie.dao.MRna;
2839 20 Oct 14 olle 86 import net.sf.basedb.reggie.dao.NoSpecimen;
2839 20 Oct 14 olle 87 import net.sf.basedb.reggie.dao.Patient;
2839 20 Oct 14 olle 88 import net.sf.basedb.reggie.dao.PooledLibrary;
4312 18 Jan 17 nicklas 89 import net.sf.basedb.reggie.dao.ReggieItem;
2839 20 Oct 14 olle 90 import net.sf.basedb.reggie.dao.ReggieRole;
2839 20 Oct 14 olle 91 import net.sf.basedb.reggie.dao.Rna;
4107 15 Sep 16 nicklas 92 import net.sf.basedb.reggie.dao.RnaQc;
2839 20 Oct 14 olle 93 import net.sf.basedb.reggie.dao.SequencingRun;
2839 20 Oct 14 olle 94 import net.sf.basedb.reggie.dao.SpecimenTube;
2839 20 Oct 14 olle 95 import net.sf.basedb.reggie.dao.Subtype;
4306 17 Jan 17 nicklas 96 import net.sf.basedb.reggie.grid.ScriptUtil;
3766 23 Feb 16 nicklas 97 import net.sf.basedb.util.Values;
2839 20 Oct 14 olle 98 import net.sf.basedb.util.error.ThrowableUtil;
2839 20 Oct 14 olle 99
2839 20 Oct 14 olle 100
3323 11 May 15 nicklas 101 public class RetractionServlet 
2839 20 Oct 14 olle 102   extends HttpServlet 
2839 20 Oct 14 olle 103 {
2839 20 Oct 14 olle 104
2839 20 Oct 14 olle 105   private static final long serialVersionUID = 28308664025515890L;
2839 20 Oct 14 olle 106   
2839 20 Oct 14 olle 107   public static final String AUTO_PROCESSING_DISABLE = "Disable";
3323 11 May 15 nicklas 108   public static final String READY_FOR_DESTRUCTION = "ReadyForDestruction";
3337 18 May 15 olle 109   public static final String RETRACTION_COMPLETED = "RetractionCompleted";
5637 03 Oct 19 nicklas 110   public static final String RETRACTION_DESTROYED = "Destroyed";
2839 20 Oct 14 olle 111
3323 11 May 15 nicklas 112   public RetractionServlet()
4113 19 Sep 16 nicklas 113   {}
2839 20 Oct 14 olle 114
2839 20 Oct 14 olle 115   @Override
2839 20 Oct 14 olle 116   protected void doGet(HttpServletRequest req, HttpServletResponse resp)
2839 20 Oct 14 olle 117     throws ServletException, IOException 
2839 20 Oct 14 olle 118   {
2839 20 Oct 14 olle 119     String cmd = req.getParameter("cmd");
2839 20 Oct 14 olle 120     JsonUtil.setJsonResponseHeaders(resp);
2839 20 Oct 14 olle 121     
2839 20 Oct 14 olle 122     JSONObject json = new JSONObject();
2839 20 Oct 14 olle 123     json.put("status", "ok");
2839 20 Oct 14 olle 124   
3975 26 May 16 nicklas 125     final SessionControl sc = Reggie.getSessionControl(req);
2839 20 Oct 14 olle 126     DbControl dc = null;
2839 20 Oct 14 olle 127     try
2839 20 Oct 14 olle 128     {
2839 20 Oct 14 olle 129       if ("GetCaseInfo".equals(cmd) || "GetProtocolInfo".equals(cmd))
2839 20 Oct 14 olle 130       {
2839 20 Oct 14 olle 131         /*
2839 20 Oct 14 olle 132           Load information about a single case when given the case name/barcode
2839 20 Oct 14 olle 133           If a case is found we will load annotations, the patient it is associated with
2839 20 Oct 14 olle 134           and specimen tubes for the case. 
2839 20 Oct 14 olle 135         */
6329 14 Jun 21 nicklas 136         dc = sc.newDbControl(":Retraction wizard");
2839 20 Oct 14 olle 137         
5639 03 Oct 19 nicklas 138         String caseOrPersonalNumber = Values.getStringOrNull(req.getParameter("caseName"));
5639 03 Oct 19 nicklas 139         int patientId = Values.getInt(req.getParameter("patientId"));
5639 03 Oct 19 nicklas 140         json = fetchJsonCaseInfo(dc, patientId, caseOrPersonalNumber, json);
2839 20 Oct 14 olle 141       }
3765 23 Feb 16 nicklas 142       
3765 23 Feb 16 nicklas 143       else if ("LoadPatientsForRetraction".equals(cmd))
3765 23 Feb 16 nicklas 144       {
6329 14 Jun 21 nicklas 145         dc = sc.newDbControl(":Retraction wizard");
3765 23 Feb 16 nicklas 146         // All "Retract" and "RetroNo" biosource items with annotation 
3765 23 Feb 16 nicklas 147         // RETRACT_STATUS set to 'null' or 'ReadyForDestruction'
3765 23 Feb 16 nicklas 148         ItemQuery<BioSource> query = BioSource.getQuery();
3765 23 Feb 16 nicklas 149         query.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
3765 23 Feb 16 nicklas 150         // ...only include 'Retract' and 'RetroNo' items
3765 23 Feb 16 nicklas 151         query.restrict(
3765 23 Feb 16 nicklas 152           Restrictions.or(
3765 23 Feb 16 nicklas 153             Subtype.RETRACT.restriction(dc, null),
3765 23 Feb 16 nicklas 154             Subtype.RETRO_NO.restriction(dc, null)
3765 23 Feb 16 nicklas 155           ));
3765 23 Feb 16 nicklas 156         // Value 'null' for RETRACT_STATUS annotation
3765 23 Feb 16 nicklas 157         query.join(Annotations.leftJoin(null, Annotationtype.RETRACT_STATUS.load(dc), "rs"));
3765 23 Feb 16 nicklas 158         query.restrict(
3765 23 Feb 16 nicklas 159           Restrictions.or(
3765 23 Feb 16 nicklas 160             Restrictions.eq(Hql.alias("rs"), Expressions.string("ReadyForDestruction")),
3765 23 Feb 16 nicklas 161             Restrictions.eq(Hql.alias("rs"), null)
3765 23 Feb 16 nicklas 162           ));
3765 23 Feb 16 nicklas 163         query.order(Orders.asc(Hql.property("name")));
3765 23 Feb 16 nicklas 164         
3765 23 Feb 16 nicklas 165         List<Patient> result = Patient.toPatient(query.list(dc));
3765 23 Feb 16 nicklas 166         JSONArray jsonPatients = new JSONArray();
3765 23 Feb 16 nicklas 167         for (Patient p : result)
3765 23 Feb 16 nicklas 168         {
3765 23 Feb 16 nicklas 169           List<Case> cases = Case.findByPatient(dc, p);
3765 23 Feb 16 nicklas 170           
3765 23 Feb 16 nicklas 171           JSONArray jsonCases = new JSONArray();
3765 23 Feb 16 nicklas 172           for (Case c : cases)
3765 23 Feb 16 nicklas 173           {
3765 23 Feb 16 nicklas 174             c.loadAnnotations(dc, "laterality", Annotationtype.LATERALITY, null);
3765 23 Feb 16 nicklas 175             jsonCases.add(c.asJSONObject());
3765 23 Feb 16 nicklas 176           }
3765 23 Feb 16 nicklas 177           p.setAnnotation("cases", jsonCases);
3765 23 Feb 16 nicklas 178           
3765 23 Feb 16 nicklas 179           p.loadAnnotations(dc, "PersonalNumber", Annotationtype.PERSONAL_NUMBER, null);
3765 23 Feb 16 nicklas 180           p.loadAnnotations(dc, "RetractTxLab", Annotationtype.RETRACT_TX_LAB, Reggie.CONVERTER_DATE_TO_STRING);
3765 23 Feb 16 nicklas 181           p.loadAnnotations(dc, "RetractRxLab", Annotationtype.RETRACT_RX_LAB, Reggie.CONVERTER_DATE_TO_STRING);
3765 23 Feb 16 nicklas 182           p.loadAnnotations(dc, "RetractNaLab", Annotationtype.RETRACT_NA_LAB, null);
3765 23 Feb 16 nicklas 183           p.loadAnnotations(dc, "RetractTxBb", Annotationtype.RETRACT_TX_BB, Reggie.CONVERTER_DATE_TO_STRING);
3765 23 Feb 16 nicklas 184           p.loadAnnotations(dc, "RetractRxBb", Annotationtype.RETRACT_RX_BB, Reggie.CONVERTER_DATE_TO_STRING);
3765 23 Feb 16 nicklas 185           p.loadAnnotations(dc, "RetractNaBb", Annotationtype.RETRACT_NA_BB, null);
3765 23 Feb 16 nicklas 186           p.loadAnnotations(dc, "RetractTxFrozen", Annotationtype.RETRACT_TX_FROZEN, Reggie.CONVERTER_DATE_TO_STRING);
3765 23 Feb 16 nicklas 187           p.loadAnnotations(dc, "RetractRxFrozen", Annotationtype.RETRACT_RX_FROZEN, Reggie.CONVERTER_DATE_TO_STRING);
3765 23 Feb 16 nicklas 188           p.loadAnnotations(dc, "RetractNaFrozen", Annotationtype.RETRACT_NA_FROZEN, null);
3765 23 Feb 16 nicklas 189           p.loadAnnotations(dc, "RetractTxRccSyd", Annotationtype.RETRACT_TX_RCC_SYD, Reggie.CONVERTER_DATE_TO_STRING);
3765 23 Feb 16 nicklas 190           p.loadAnnotations(dc, "RetractNaRccSyd", Annotationtype.RETRACT_NA_RCC_SYD, null);
3765 23 Feb 16 nicklas 191           p.loadAnnotations(dc, "RetractStatus", Annotationtype.RETRACT_STATUS, null);
3765 23 Feb 16 nicklas 192           
3765 23 Feb 16 nicklas 193           jsonPatients.add(p.asJSONObject());
3765 23 Feb 16 nicklas 194         }
3765 23 Feb 16 nicklas 195         
3765 23 Feb 16 nicklas 196         json.put("patients", jsonPatients);
3765 23 Feb 16 nicklas 197       }
3765 23 Feb 16 nicklas 198       
3337 18 May 15 olle 199       else if ("GetCaseInfoBeforeDestruction".equals(cmd))
3337 18 May 15 olle 200       {
6329 14 Jun 21 nicklas 201         dc = sc.newDbControl(":Retraction wizard");
3337 18 May 15 olle 202         
3766 23 Feb 16 nicklas 203         int patientId = Values.getInt(req.getParameter("patientId"));
3766 23 Feb 16 nicklas 204         json = fetchJsonCaseInfoBeforeDestruction(dc, patientId, json);
3337 18 May 15 olle 205       }
2839 20 Oct 14 olle 206     }
2839 20 Oct 14 olle 207     catch (Throwable t)
2839 20 Oct 14 olle 208     {
2839 20 Oct 14 olle 209       t.printStackTrace();
2839 20 Oct 14 olle 210       json.clear();
2839 20 Oct 14 olle 211       json.put("status", "error");
2839 20 Oct 14 olle 212       json.put("message", t.getMessage());
2839 20 Oct 14 olle 213       json.put("stacktrace", ThrowableUtil.stackTraceToString(t));
2839 20 Oct 14 olle 214     }
2839 20 Oct 14 olle 215     finally
2839 20 Oct 14 olle 216     {
2839 20 Oct 14 olle 217       if (dc != null) dc.close();
2839 20 Oct 14 olle 218       json.writeJSONString(resp.getWriter());
2839 20 Oct 14 olle 219     }
2839 20 Oct 14 olle 220   }
2839 20 Oct 14 olle 221
2839 20 Oct 14 olle 222
2839 20 Oct 14 olle 223   /**
2839 20 Oct 14 olle 224    * Returns an input JSONObject updated with case info data.
2839 20 Oct 14 olle 225    * 
2839 20 Oct 14 olle 226    * @param dc DbControl The DbControl to use.
2839 20 Oct 14 olle 227    * @param caseOrPersonalNumber String Case name or personal number.
2839 20 Oct 14 olle 228    * @param json JSONObject JSONObject to add case info data to.
2839 20 Oct 14 olle 229    * @return JSONObject Input JSONObject updated with case info data.
2839 20 Oct 14 olle 230    */
5639 03 Oct 19 nicklas 231   private JSONObject fetchJsonCaseInfo(DbControl dc, int patientId, String caseOrPersonalNumber, JSONObject json)
2839 20 Oct 14 olle 232   {
5639 03 Oct 19 nicklas 233     ReggieItem<? extends BioMaterial> patientOrCase = fetchPatientOrCase(dc, patientId, caseOrPersonalNumber);
4312 18 Jan 17 nicklas 234     if (patientOrCase == null) return json;
4103 15 Sep 16 nicklas 235     
4104 15 Sep 16 nicklas 236     Set<BasicItem> childItems = new LinkedHashSet<BasicItem>();
4312 18 Jan 17 nicklas 237     collectAllChildItems(dc, patientOrCase.getItem(), childItems);
4312 18 Jan 17 nicklas 238     childItems.add(patientOrCase.getItem());
4104 15 Sep 16 nicklas 239     
4105 15 Sep 16 nicklas 240     // Load all the item subtypes that we are interested in
4104 15 Sep 16 nicklas 241     ItemSubtype caseType = Subtype.CASE.get(dc);
4104 15 Sep 16 nicklas 242     ItemSubtype bloodType = Subtype.BLOOD.get(dc);
4108 15 Sep 16 nicklas 243     ItemSubtype bloodDnaType = Subtype.BLOOD_DNA.get(dc);
4105 15 Sep 16 nicklas 244     ItemSubtype specimenType = Subtype.SPECIMEN.get(dc);
4105 15 Sep 16 nicklas 245     ItemSubtype noSpecimenType = Subtype.NO_SPECIMEN.get(dc);
4104 15 Sep 16 nicklas 246     
4109 15 Sep 16 nicklas 247     ItemSubtype histologyType = Subtype.HISTOLOGY.get(dc);
4109 15 Sep 16 nicklas 248     ItemSubtype stainedType = Subtype.STAINED.get(dc);
4109 15 Sep 16 nicklas 249     
4106 15 Sep 16 nicklas 250     ItemSubtype lysateType = Subtype.LYSATE.get(dc);
4106 15 Sep 16 nicklas 251     ItemSubtype rnaType = Subtype.RNA.get(dc);
4107 15 Sep 16 nicklas 252     ItemSubtype rnaQcType = Subtype.RNAQC.get(dc);
4106 15 Sep 16 nicklas 253     ItemSubtype dnaType = Subtype.DNA.get(dc);
4106 15 Sep 16 nicklas 254     ItemSubtype ftType = Subtype.FLOW_THROUGH.get(dc);
4106 15 Sep 16 nicklas 255     
4108 15 Sep 16 nicklas 256     ItemSubtype mRnaType = Subtype.MRNA.get(dc);
4108 15 Sep 16 nicklas 257     ItemSubtype cDnaType = Subtype.CDNA.get(dc);
4110 15 Sep 16 nicklas 258     ItemSubtype libType = Subtype.LIBRARY.get(dc);
4115 19 Sep 16 nicklas 259     ItemSubtype poolType = Subtype.POOLED_LIBRARY.get(dc);
4108 15 Sep 16 nicklas 260     
4269 15 Dec 16 nicklas 261     // Prepare JSON arrays, etc. for holding information about the various subtypes
4269 15 Dec 16 nicklas 262     Set<String> allCaseNames = new TreeSet<String>();
4312 18 Jan 17 nicklas 263     JSONObject jsonPatient = new JSONObject();
4104 15 Sep 16 nicklas 264     JSONArray jsonCases = new JSONArray();
4104 15 Sep 16 nicklas 265     JSONArray jsonBlood = new JSONArray();
4108 15 Sep 16 nicklas 266     JSONArray jsonBloodDna = new JSONArray();
4105 15 Sep 16 nicklas 267     JSONArray jsonSpecimen = new JSONArray();
4105 15 Sep 16 nicklas 268     JSONArray jsonNoSpecimen = new JSONArray();
4108 15 Sep 16 nicklas 269     
4109 15 Sep 16 nicklas 270     JSONArray jsonHistology = new JSONArray();
4109 15 Sep 16 nicklas 271     JSONArray jsonStained = new JSONArray();
4109 15 Sep 16 nicklas 272
4106 15 Sep 16 nicklas 273     JSONArray jsonLysate = new JSONArray();
4106 15 Sep 16 nicklas 274     JSONArray jsonRna = new JSONArray();
4107 15 Sep 16 nicklas 275     JSONArray jsonRnaQc = new JSONArray();
4106 15 Sep 16 nicklas 276     JSONArray jsonDna = new JSONArray();
4106 15 Sep 16 nicklas 277     JSONArray jsonFt = new JSONArray();
4105 15 Sep 16 nicklas 278     
4108 15 Sep 16 nicklas 279     JSONArray jsonMRna = new JSONArray();
4108 15 Sep 16 nicklas 280     JSONArray jsonCDna = new JSONArray();
4110 15 Sep 16 nicklas 281     JSONArray jsonLib = new JSONArray();
4115 19 Sep 16 nicklas 282     JSONArray jsonPools = new JSONArray();
4112 19 Sep 16 nicklas 283     JSONArray jsonSeqRuns = new JSONArray();
4108 15 Sep 16 nicklas 284     
4104 15 Sep 16 nicklas 285     for (BasicItem item : childItems)
4104 15 Sep 16 nicklas 286     {
4104 15 Sep 16 nicklas 287       int itemId = item.getId();
4104 15 Sep 16 nicklas 288       ItemSubtype subtype = item instanceof Subtypable ? ((Subtypable)item).getItemSubtype() : null;
4269 15 Dec 16 nicklas 289       if (item instanceof Nameable)
4269 15 Dec 16 nicklas 290       {
4269 15 Dec 16 nicklas 291         String name = ((Nameable)item).getName();
4269 15 Dec 16 nicklas 292         String caseName = name.substring(0, 7);
4269 15 Dec 16 nicklas 293         if (caseName.matches("\\d+")) allCaseNames.add(caseName);
4269 15 Dec 16 nicklas 294       }
4312 18 Jan 17 nicklas 295       if (item instanceof BioSource)
4104 15 Sep 16 nicklas 296       {
4312 18 Jan 17 nicklas 297         // We treat all biosource items as Patient items here
4312 18 Jan 17 nicklas 298         // even if they have already been converted to 'Retract' or 'RetroNo' item.
4312 18 Jan 17 nicklas 299         Patient p = Patient.getById(dc, itemId);
4312 18 Jan 17 nicklas 300         loadPatientInfo(dc, p);
4312 18 Jan 17 nicklas 301         jsonPatient = p.asJSONObject();
4312 18 Jan 17 nicklas 302       }
4312 18 Jan 17 nicklas 303       else if (caseType.equals(subtype))
4312 18 Jan 17 nicklas 304       {
4104 15 Sep 16 nicklas 305         Case c = Case.getById(dc, itemId);
4104 15 Sep 16 nicklas 306         loadCaseInfo(dc, c);
4104 15 Sep 16 nicklas 307         jsonCases.add(c.asJSONObject());
4104 15 Sep 16 nicklas 308       }
4105 15 Sep 16 nicklas 309       else if (bloodType.equals(subtype))
4104 15 Sep 16 nicklas 310       {
4104 15 Sep 16 nicklas 311         Blood b = Blood.getById(dc, itemId);
4104 15 Sep 16 nicklas 312         loadBloodInfo(dc, b);
4104 15 Sep 16 nicklas 313         jsonBlood.add(b.asJSONObject());
4104 15 Sep 16 nicklas 314       }
4108 15 Sep 16 nicklas 315       else if (bloodDnaType.equals(subtype))
4108 15 Sep 16 nicklas 316       {
4108 15 Sep 16 nicklas 317         BloodDna b = BloodDna.getById(dc, itemId);
4108 15 Sep 16 nicklas 318         loadBloodDnaInfo(dc, b);
4108 15 Sep 16 nicklas 319         jsonBloodDna.add(b.asJSONObject());
4108 15 Sep 16 nicklas 320       }
4105 15 Sep 16 nicklas 321       else if (specimenType.equals(subtype))
4105 15 Sep 16 nicklas 322       {
4105 15 Sep 16 nicklas 323         SpecimenTube sp = SpecimenTube.getById(dc, itemId);
4105 15 Sep 16 nicklas 324         loadSpecimenInfo(dc, sp);
4105 15 Sep 16 nicklas 325         jsonSpecimen.add(sp.asJSONObject());
4105 15 Sep 16 nicklas 326       }
4105 15 Sep 16 nicklas 327       else if (noSpecimenType.equals(subtype))
4105 15 Sep 16 nicklas 328       {
4105 15 Sep 16 nicklas 329         NoSpecimen ns = NoSpecimen.getById(dc, itemId);
4105 15 Sep 16 nicklas 330         loadNoSpecimenInfo(dc, ns);
4105 15 Sep 16 nicklas 331         jsonNoSpecimen.add(ns.asJSONObject());
4105 15 Sep 16 nicklas 332       }
4109 15 Sep 16 nicklas 333       else if (histologyType.equals(subtype))
4109 15 Sep 16 nicklas 334       {
4109 15 Sep 16 nicklas 335         Histology h = Histology.getById(dc, itemId);
4109 15 Sep 16 nicklas 336         loadHistologyInfo(dc, h);
4109 15 Sep 16 nicklas 337         jsonHistology.add(h.asJSONObject());
4109 15 Sep 16 nicklas 338       }
4109 15 Sep 16 nicklas 339       else if (stainedType.equals(subtype))
4109 15 Sep 16 nicklas 340       {
4109 15 Sep 16 nicklas 341         Sample stained = Sample.getById(dc, itemId);
4109 15 Sep 16 nicklas 342         JSONObject jsonSample = loadStainedInfo(dc, stained);
4109 15 Sep 16 nicklas 343         jsonStained.add(jsonSample);
4109 15 Sep 16 nicklas 344       }
4106 15 Sep 16 nicklas 345       else if (lysateType.equals(subtype))
4106 15 Sep 16 nicklas 346       {
4106 15 Sep 16 nicklas 347         Lysate lys = Lysate.getById(dc, itemId);
4106 15 Sep 16 nicklas 348         loadLysateInfo(dc, lys);
4106 15 Sep 16 nicklas 349         jsonLysate.add(lys.asJSONObject());
4106 15 Sep 16 nicklas 350       }
4106 15 Sep 16 nicklas 351       else if (rnaType.equals(subtype))
4106 15 Sep 16 nicklas 352       {
4106 15 Sep 16 nicklas 353         Rna rna = Rna.getById(dc, itemId);
4106 15 Sep 16 nicklas 354         loadRnaInfo(dc, rna);
4106 15 Sep 16 nicklas 355         jsonRna.add(rna.asJSONObject());
4106 15 Sep 16 nicklas 356       }
4107 15 Sep 16 nicklas 357       else if (rnaQcType.equals(subtype))
4107 15 Sep 16 nicklas 358       {
4107 15 Sep 16 nicklas 359         RnaQc qc = RnaQc.getById(dc, itemId);
4107 15 Sep 16 nicklas 360         loadRnaQcInfo(dc, qc);
4107 15 Sep 16 nicklas 361         jsonRnaQc.add(qc.asJSONObject());
4107 15 Sep 16 nicklas 362       }
4106 15 Sep 16 nicklas 363       else if (dnaType.equals(subtype))
4106 15 Sep 16 nicklas 364       {
4106 15 Sep 16 nicklas 365         Dna dna = Dna.getById(dc, itemId);
4106 15 Sep 16 nicklas 366         loadDnaInfo(dc, dna);
4106 15 Sep 16 nicklas 367         jsonDna.add(dna.asJSONObject());
4106 15 Sep 16 nicklas 368       }
4106 15 Sep 16 nicklas 369       else if (ftType.equals(subtype))
4106 15 Sep 16 nicklas 370       {
4106 15 Sep 16 nicklas 371         FlowThrough ft = FlowThrough.getById(dc, itemId);
4106 15 Sep 16 nicklas 372         loadFlowThroughInfo(dc, ft);
4106 15 Sep 16 nicklas 373         jsonFt.add(ft.asJSONObject());
4106 15 Sep 16 nicklas 374       }
4108 15 Sep 16 nicklas 375       else if (mRnaType.equals(subtype))
4108 15 Sep 16 nicklas 376       {
4108 15 Sep 16 nicklas 377         MRna mrna = MRna.getById(dc, itemId);
4108 15 Sep 16 nicklas 378         loadMRnaInfo(dc, mrna);
4108 15 Sep 16 nicklas 379         jsonMRna.add(mrna.asJSONObject());
4108 15 Sep 16 nicklas 380       }
4108 15 Sep 16 nicklas 381       else if (cDnaType.equals(subtype))
4108 15 Sep 16 nicklas 382       {
4108 15 Sep 16 nicklas 383         CDna cdna = CDna.getById(dc, itemId);
4108 15 Sep 16 nicklas 384         loadCDnaInfo(dc, cdna);
4108 15 Sep 16 nicklas 385         jsonCDna.add(cdna.asJSONObject());
4108 15 Sep 16 nicklas 386       }
4110 15 Sep 16 nicklas 387       else if (libType.equals(subtype))
4110 15 Sep 16 nicklas 388       {
4110 15 Sep 16 nicklas 389         Library lib = Library.getById(dc, itemId);
4110 15 Sep 16 nicklas 390         // Ignore *.dil items with '0' remaining quantity
4886 04 Jul 18 nicklas 391         if (lib.getName().indexOf(".dil") == -1 || lib.getExtract().getRemainingQuantity() > 0)
4110 15 Sep 16 nicklas 392         {
4110 15 Sep 16 nicklas 393           loadLibraryInfo(dc, lib);
4110 15 Sep 16 nicklas 394           jsonLib.add(lib.asJSONObject());
4112 19 Sep 16 nicklas 395           for (SequencingRun sr : SequencingRun.findByLibrary(dc, lib))
4112 19 Sep 16 nicklas 396           {
4112 19 Sep 16 nicklas 397             loadSequencingRunInfo(dc, sr);
4112 19 Sep 16 nicklas 398             sr.setAnnotation("caseName", lib.getName().substring(0, 7));
4112 19 Sep 16 nicklas 399             jsonSeqRuns.add(sr.asJSONObject());
4112 19 Sep 16 nicklas 400           }
4110 15 Sep 16 nicklas 401         }
4110 15 Sep 16 nicklas 402       }
4115 19 Sep 16 nicklas 403       else if (poolType.equals(subtype))
4115 19 Sep 16 nicklas 404       {
4115 19 Sep 16 nicklas 405         PooledLibrary pool = PooledLibrary.getById(dc, itemId);
4115 19 Sep 16 nicklas 406         loadPooledLibraryInfo(dc, pool);
4115 19 Sep 16 nicklas 407         jsonPools.add(pool.asJSONObject());
4115 19 Sep 16 nicklas 408       }
4104 15 Sep 16 nicklas 409     }
4269 15 Dec 16 nicklas 410     
4312 18 Jan 17 nicklas 411     JSONArray jsonAllCaseNames = new JSONArray();
4312 18 Jan 17 nicklas 412     jsonAllCaseNames.addAll(allCaseNames);
4312 18 Jan 17 nicklas 413     json.put("allCaseNames", jsonAllCaseNames);
4312 18 Jan 17 nicklas 414     
4312 18 Jan 17 nicklas 415     if (jsonPatient.size() > 0) json.put("patient", jsonPatient);
4104 15 Sep 16 nicklas 416     if (jsonCases.size() > 0) json.put("caseInfo", jsonCases);
4104 15 Sep 16 nicklas 417     if (jsonBlood.size() > 0) json.put("blood", jsonBlood);
4108 15 Sep 16 nicklas 418     if (jsonBloodDna.size() > 0) json.put("bloodDna", jsonBloodDna);
4105 15 Sep 16 nicklas 419     if (jsonSpecimen.size() > 0) json.put("specimen", jsonSpecimen);
4105 15 Sep 16 nicklas 420     if (jsonNoSpecimen.size() > 0) json.put("noSpecimen", jsonNoSpecimen);
4109 15 Sep 16 nicklas 421
4109 15 Sep 16 nicklas 422     if (jsonHistology.size() > 0) json.put("histology", jsonHistology);
4109 15 Sep 16 nicklas 423     if (jsonStained.size() > 0) json.put("stained", jsonStained);
4104 15 Sep 16 nicklas 424     
4106 15 Sep 16 nicklas 425     if (jsonLysate.size() > 0) json.put("lysate", jsonLysate);
4106 15 Sep 16 nicklas 426     if (jsonRna.size() > 0) json.put("rna", jsonRna);
4107 15 Sep 16 nicklas 427     if (jsonRnaQc.size() > 0) json.put("rnaQc", jsonRnaQc);
4106 15 Sep 16 nicklas 428     if (jsonDna.size() > 0) json.put("dna", jsonDna);
4106 15 Sep 16 nicklas 429     if (jsonFt.size() > 0) json.put("flowThrough", jsonFt);
4106 15 Sep 16 nicklas 430
4108 15 Sep 16 nicklas 431     if (jsonMRna.size() > 0) json.put("mrna", jsonMRna);
4108 15 Sep 16 nicklas 432     if (jsonCDna.size() > 0) json.put("cdna", jsonCDna);
4110 15 Sep 16 nicklas 433     if (jsonLib.size() > 0) json.put("lib", jsonLib);
4115 19 Sep 16 nicklas 434     if (jsonPools.size() > 0) json.put("pooledlib", jsonPools);
4112 19 Sep 16 nicklas 435     if (jsonSeqRuns.size() > 0) json.put("sequencingRun", jsonSeqRuns);
2839 20 Oct 14 olle 436     
2839 20 Oct 14 olle 437     return json;
2839 20 Oct 14 olle 438   }
2839 20 Oct 14 olle 439
2839 20 Oct 14 olle 440   /**
5637 03 Oct 19 nicklas 441     Get the item subtypes that we track storage locations for.
5637 03 Oct 19 nicklas 442   */
5637 03 Oct 19 nicklas 443   private Set<ItemSubtype> getStoredSubtypes(DbControl dc)
5637 03 Oct 19 nicklas 444   {
5637 03 Oct 19 nicklas 445     Set<ItemSubtype> subtypes = new HashSet<>();
5637 03 Oct 19 nicklas 446     subtypes.add(Subtype.SPECIMEN.get(dc));
5637 03 Oct 19 nicklas 447     subtypes.add(Subtype.LYSATE.get(dc));
5637 03 Oct 19 nicklas 448     subtypes.add(Subtype.RNA.get(dc));
5637 03 Oct 19 nicklas 449     subtypes.add(Subtype.DNA.get(dc));
5637 03 Oct 19 nicklas 450     subtypes.add(Subtype.FLOW_THROUGH.get(dc));
5640 04 Oct 19 nicklas 451     subtypes.add(Subtype.BLOOD_DNA.get(dc));
5637 03 Oct 19 nicklas 452     return subtypes;
5637 03 Oct 19 nicklas 453   }
5637 03 Oct 19 nicklas 454   
5637 03 Oct 19 nicklas 455   /**
3337 18 May 15 olle 456    * Returns an input JSONObject updated with case info data
3337 18 May 15 olle 457    * obtained by recursion using getUsingItems() method on
3337 18 May 15 olle 458    * patient item.
3337 18 May 15 olle 459    * 
3337 18 May 15 olle 460    * @param dc DbControl The DbControl to use.
3337 18 May 15 olle 461    * @param caseOrPersonalNumber String Case name or personal number.
3337 18 May 15 olle 462    * @param json JSONObject JSONObject to add case info data to.
3337 18 May 15 olle 463    * @return JSONObject Input JSONObject updated with case info data.
3337 18 May 15 olle 464    */
3766 23 Feb 16 nicklas 465   private JSONObject fetchJsonCaseInfoBeforeDestruction(DbControl dc, int patientId, JSONObject json)
3337 18 May 15 olle 466   {
3766 23 Feb 16 nicklas 467     Patient patient = Patient.getById(dc, patientId);
3363 01 Jun 15 olle 468     
3425 25 Jun 15 nicklas 469     loadPatientInfo(dc, patient);
3425 25 Jun 15 nicklas 470     json.put("patient", patient.asJSONObject());
3337 18 May 15 olle 471
3388 11 Jun 15 nicklas 472     Set<BasicItem> patientItemList = new LinkedHashSet<BasicItem>();
7049 15 Feb 23 nicklas 473     Map<FileServer, Set<ExternalPath>> externalPaths = new HashMap<>();
3427 26 Jun 15 nicklas 474     
3425 25 Jun 15 nicklas 475     patientItemList.add(patient.getItem());
3388 11 Jun 15 nicklas 476     collectAllChildItems(dc, patient.getItem(), patientItemList);
3391 11 Jun 15 nicklas 477     collectDirectories(dc, patientItemList);
3427 26 Jun 15 nicklas 478     collectExternalPaths(dc, patientItemList, externalPaths);
3427 26 Jun 15 nicklas 479     
3390 11 Jun 15 nicklas 480     Map<String,List<Extract>> pooledLibNameParentListHM = fetchPooledLibraryNameParentExtractListHashMap(dc, patientItemList);
3425 25 Jun 15 nicklas 481     JSONArray jsonItems = new JSONArray();
3425 25 Jun 15 nicklas 482
3425 25 Jun 15 nicklas 483     ItemSubtype caseType = Subtype.CASE.get(dc);
5637 03 Oct 19 nicklas 484     Set<ItemSubtype> storedSubtypes = getStoredSubtypes(dc);
3390 11 Jun 15 nicklas 485     ItemSubtype pooledLibraryType = Subtype.POOLED_LIBRARY.get(dc);
3390 11 Jun 15 nicklas 486     
3337 18 May 15 olle 487     for (BasicItem basicItem: patientItemList)
3337 18 May 15 olle 488     {
3427 26 Jun 15 nicklas 489       boolean hasDeletePermission = basicItem.hasPermission(Permission.DELETE);
3337 18 May 15 olle 490       String itemName = basicItem.toString();
3390 11 Jun 15 nicklas 491       ItemSubtype subtype = null;
4512 31 May 17 nicklas 492       String liasonComment = null;
3387 10 Jun 15 nicklas 493       if (basicItem instanceof File)
3337 18 May 15 olle 494       {
3427 26 Jun 15 nicklas 495         File f = (File)basicItem;
3427 26 Jun 15 nicklas 496         itemName = f.getPath().toString();
3427 26 Jun 15 nicklas 497         // If the file is write protected it can't be deleted
3427 26 Jun 15 nicklas 498         // but if we have WRITE permission we can clear the flag
3427 26 Jun 15 nicklas 499         // and get delete permission
3427 26 Jun 15 nicklas 500         if (!hasDeletePermission && f.isWriteProtected())
3427 26 Jun 15 nicklas 501         {
3427 26 Jun 15 nicklas 502           hasDeletePermission = f.hasPermission(Permission.WRITE);
3427 26 Jun 15 nicklas 503         }
3387 10 Jun 15 nicklas 504       }
3393 11 Jun 15 nicklas 505       else if (basicItem instanceof Directory)
3391 11 Jun 15 nicklas 506       {
3391 11 Jun 15 nicklas 507         itemName = ((Directory)basicItem).getPath().toString();
3391 11 Jun 15 nicklas 508       }
3387 10 Jun 15 nicklas 509       else if (basicItem instanceof Nameable)
3387 10 Jun 15 nicklas 510       {
3337 18 May 15 olle 511         itemName = ((Nameable)basicItem).getName();
3337 18 May 15 olle 512       }
3390 11 Jun 15 nicklas 513       if (basicItem instanceof Subtypable)
3390 11 Jun 15 nicklas 514       {
3390 11 Jun 15 nicklas 515         subtype = ((Subtypable)basicItem).getItemSubtype();
3390 11 Jun 15 nicklas 516       }
4512 31 May 17 nicklas 517       if (basicItem instanceof Annotatable)
4512 31 May 17 nicklas 518       {
4512 31 May 17 nicklas 519         liasonComment = (String)Annotationtype.LIASON_COMMENT.getAnnotationValue(dc, (Annotatable)basicItem);
4512 31 May 17 nicklas 520       }
3390 11 Jun 15 nicklas 521
5637 03 Oct 19 nicklas 522       String comment = null;
3425 25 Jun 15 nicklas 523       if (caseType.equals(subtype) || basicItem instanceof BioSource)
3337 18 May 15 olle 524       {
3425 25 Jun 15 nicklas 525         comment = "To be replaced by a copy with the same name";
3425 25 Jun 15 nicklas 526       }
3425 25 Jun 15 nicklas 527       else if (pooledLibraryType.equals(subtype))
3425 25 Jun 15 nicklas 528       {
3425 25 Jun 15 nicklas 529         List<Extract> pooledLibParentsList = pooledLibNameParentListHM.get(itemName);
3425 25 Jun 15 nicklas 530         if (pooledLibParentsList != null)
3337 18 May 15 olle 531         {
3425 25 Jun 15 nicklas 532           String parentExtractsStr = "";
3425 25 Jun 15 nicklas 533           String pluralSuffix = "";
3425 25 Jun 15 nicklas 534           for (Extract e: pooledLibParentsList)
3337 18 May 15 olle 535           {
3425 25 Jun 15 nicklas 536             if (!parentExtractsStr.equals(""))
3337 18 May 15 olle 537             {
3425 25 Jun 15 nicklas 538               parentExtractsStr += ", ";
3425 25 Jun 15 nicklas 539               pluralSuffix = "s";
3337 18 May 15 olle 540             }
3425 25 Jun 15 nicklas 541             parentExtractsStr += e.getName();
3337 18 May 15 olle 542           }
3425 25 Jun 15 nicklas 543           comment = "Retained, but extract" + pluralSuffix + " " + parentExtractsStr + " to be removed from parent list.";
3337 18 May 15 olle 544         }
3425 25 Jun 15 nicklas 545         else
3425 25 Jun 15 nicklas 546         {
3425 25 Jun 15 nicklas 547           comment = "No change";
3425 25 Jun 15 nicklas 548         }
3425 25 Jun 15 nicklas 549       }
5637 03 Oct 19 nicklas 550       if (storedSubtypes.contains(subtype))
5637 03 Oct 19 nicklas 551       {
5637 03 Oct 19 nicklas 552         String retractStatus = (String)Annotationtype.RETRACT_STATUS.getAnnotationValue(dc, (Annotatable)basicItem);
5637 03 Oct 19 nicklas 553         if (!RETRACTION_DESTROYED.equals(retractStatus))
5637 03 Oct 19 nicklas 554         {
5637 03 Oct 19 nicklas 555           comment = "Not registered as destroyed";
5637 03 Oct 19 nicklas 556           hasDeletePermission = false;
5637 03 Oct 19 nicklas 557         }
5637 03 Oct 19 nicklas 558       }
5637 03 Oct 19 nicklas 559
5637 03 Oct 19 nicklas 560       if (comment == null) comment = hasDeletePermission ? "To be deleted" : "No delete permission";
3427 26 Jun 15 nicklas 561       
3389 11 Jun 15 nicklas 562         
3425 25 Jun 15 nicklas 563       JSONObject jsonItem = new JSONObject();
3425 25 Jun 15 nicklas 564       jsonItem.put("itemId", basicItem.getId());
3425 25 Jun 15 nicklas 565       jsonItem.put("name", itemName);
3425 25 Jun 15 nicklas 566       jsonItem.put("type", basicItem.getType().toString() + (subtype == null ? "" : " (" + subtype.getName() + ")"));
3425 25 Jun 15 nicklas 567       jsonItem.put("comment", comment);
4512 31 May 17 nicklas 568       if (liasonComment != null) jsonItem.put("liasonComment", liasonComment);
3427 26 Jun 15 nicklas 569       jsonItem.put("deletePermission", hasDeletePermission);
3425 25 Jun 15 nicklas 570       jsonItems.add(jsonItem);
3337 18 May 15 olle 571     }
3425 25 Jun 15 nicklas 572     
7049 15 Feb 23 nicklas 573     for (Map.Entry<FileServer, Set<ExternalPath>> entry : externalPaths.entrySet())
3427 26 Jun 15 nicklas 574     {
3427 26 Jun 15 nicklas 575       FileServer server = entry.getKey();
3427 26 Jun 15 nicklas 576       // We need WRITE permission in order to access the
3427 26 Jun 15 nicklas 577       // password for logging into the remote server
3427 26 Jun 15 nicklas 578       boolean hasPermission = server.hasPermission(Permission.WRITE);
3427 26 Jun 15 nicklas 579       
7049 15 Feb 23 nicklas 580       for (ExternalPath externalPath : entry.getValue())
3427 26 Jun 15 nicklas 581       {
3427 26 Jun 15 nicklas 582         JSONObject jsonItem = new JSONObject();
7049 15 Feb 23 nicklas 583         jsonItem.put("name", externalPath.path);
7049 15 Feb 23 nicklas 584         jsonItem.put("type", "External "+(externalPath.isFolder?"folder":"file")+" ("+server.getName()+")");
3427 26 Jun 15 nicklas 585         jsonItem.put("comment", "To be deleted");
3427 26 Jun 15 nicklas 586         jsonItem.put("deletePermission", hasPermission);
3427 26 Jun 15 nicklas 587         jsonItems.add(jsonItem);
3427 26 Jun 15 nicklas 588       }
3427 26 Jun 15 nicklas 589     }
3427 26 Jun 15 nicklas 590     
3425 25 Jun 15 nicklas 591     json.put("items", jsonItems);
3337 18 May 15 olle 592     return json;
3337 18 May 15 olle 593   }
3337 18 May 15 olle 594
3337 18 May 15 olle 595
3337 18 May 15 olle 596   /**
4312 18 Jan 17 nicklas 597     Returns the patient or case related to a case name or personal number.
4312 18 Jan 17 nicklas 598      If a patient exists, that item is returned, othwise the case item.
4312 18 Jan 17 nicklas 599    
4312 18 Jan 17 nicklas 600     @param dc DbControl The DbControl to use.
4312 18 Jan 17 nicklas 601     @param caseOrPersonalNumber String Case name or personal number.
4312 18 Jan 17 nicklas 602     @return Patient The patient or case found, if any, for the potential case name or personal number.
2839 20 Oct 14 olle 603    */
5639 03 Oct 19 nicklas 604   private ReggieItem<? extends BioMaterial> fetchPatientOrCase(DbControl dc, int patientId, String caseOrPersonalNumber)
5639 03 Oct 19 nicklas 605   {
2839 20 Oct 14 olle 606     Patient patient = null;
4312 18 Jan 17 nicklas 607     Case theCase = null;
5639 03 Oct 19 nicklas 608     if (patientId > 0)
2839 20 Oct 14 olle 609     {
5639 03 Oct 19 nicklas 610       patient = Patient.getById(dc, patientId);
2839 20 Oct 14 olle 611     }
2839 20 Oct 14 olle 612     else
2839 20 Oct 14 olle 613     {
5639 03 Oct 19 nicklas 614       boolean validCaseName = caseNameIsValid(caseOrPersonalNumber, true);
5639 03 Oct 19 nicklas 615       if (validCaseName)
2839 20 Oct 14 olle 616       {
5639 03 Oct 19 nicklas 617         String caseName = caseOrPersonalNumber;
5639 03 Oct 19 nicklas 618         theCase = Case.findByName(dc, caseName);
5639 03 Oct 19 nicklas 619         if (theCase != null)
5639 03 Oct 19 nicklas 620         {
5639 03 Oct 19 nicklas 621           patient = Patient.findByCase(dc, theCase);
5639 03 Oct 19 nicklas 622         }
2839 20 Oct 14 olle 623       }
5639 03 Oct 19 nicklas 624       else
2839 20 Oct 14 olle 625       {
5639 03 Oct 19 nicklas 626         // Input 'caseName' may be personal number
5639 03 Oct 19 nicklas 627         String potentialPnr = caseOrPersonalNumber;
5639 03 Oct 19 nicklas 628         // Find cases by personal number if user has permission to do so
5639 03 Oct 19 nicklas 629         try
5639 03 Oct 19 nicklas 630         {
5639 03 Oct 19 nicklas 631           patient = Patient.findByPersonalNumber(dc, potentialPnr, false);
5639 03 Oct 19 nicklas 632         }
5639 03 Oct 19 nicklas 633         catch (PermissionDeniedException e)
5639 03 Oct 19 nicklas 634         {
5639 03 Oct 19 nicklas 635           System.out.println("RetractionServlet::fetchPatient(): PermissionDeniedException: " + e);
5639 03 Oct 19 nicklas 636         }
2839 20 Oct 14 olle 637       }
2839 20 Oct 14 olle 638     }
4312 18 Jan 17 nicklas 639     if (patient == null && theCase == null)
3361 01 Jun 15 olle 640     {
3361 01 Jun 15 olle 641       // Input 'caseName' may refer to blood-only item
3361 01 Jun 15 olle 642       List<Blood> bloodList = Blood.findAllByCaseName(dc, caseOrPersonalNumber);
3361 01 Jun 15 olle 643       if (bloodList.size() > 0)
3361 01 Jun 15 olle 644       {
3361 01 Jun 15 olle 645         patient = Patient.findByBlood(dc, bloodList.get(0));
3361 01 Jun 15 olle 646       }
3361 01 Jun 15 olle 647     }
4312 18 Jan 17 nicklas 648     return patient != null ? patient : theCase;
2839 20 Oct 14 olle 649   }
2839 20 Oct 14 olle 650
2839 20 Oct 14 olle 651
2839 20 Oct 14 olle 652
2839 20 Oct 14 olle 653
3334 13 May 15 olle 654   /**
2839 20 Oct 14 olle 655     Verify that the 'case' name is a 7-digit value + optional 'C' suffix.
2839 20 Oct 14 olle 656   
2839 20 Oct 14 olle 657     @param caseName String Input case name to check.
2839 20 Oct 14 olle 658     @param allowSuffix boolean Flag indicating if optional 'C' suffix is allowed.
3334 13 May 15 olle 659     @return boolean Returns `true` if potential case name (not necessarily in database), `false` otherwise.
2839 20 Oct 14 olle 660    */
2839 20 Oct 14 olle 661   private boolean caseNameIsValid(String caseName, boolean allowSuffix)
2839 20 Oct 14 olle 662   {
2839 20 Oct 14 olle 663     boolean isValid = false;
2839 20 Oct 14 olle 664     if (caseName != null)
2839 20 Oct 14 olle 665     {
2839 20 Oct 14 olle 666       String regex = allowSuffix ? "^\\d{7}C?$" : "^\\d{7}$";
2839 20 Oct 14 olle 667       Pattern pattern = Pattern.compile(regex);
2839 20 Oct 14 olle 668       Matcher matcher = pattern.matcher(caseName);
2839 20 Oct 14 olle 669       isValid = matcher.matches();
2839 20 Oct 14 olle 670     }
2839 20 Oct 14 olle 671     return isValid;
2839 20 Oct 14 olle 672   }
2839 20 Oct 14 olle 673
2839 20 Oct 14 olle 674   private void loadCaseInfo(DbControl dc, Case theCase)
2839 20 Oct 14 olle 675   {
2839 20 Oct 14 olle 676     Sample s = theCase.getItem();
2839 20 Oct 14 olle 677     // Properties
2839 20 Oct 14 olle 678     theCase.setAnnotation("registrationDate", Reggie.CONVERTER_DATE_TO_STRING.convert(s.getEntryDate()));
2839 20 Oct 14 olle 679     theCase.setAnnotation("editable", s.hasPermission(Permission.WRITE));
2839 20 Oct 14 olle 680     
2839 20 Oct 14 olle 681     // Annotations and consent
2839 20 Oct 14 olle 682     Consent.loadConsentAnnotations(dc, theCase);
2839 20 Oct 14 olle 683     theCase.loadAnnotations(dc, "laterality", Annotationtype.LATERALITY, null);
2839 20 Oct 14 olle 684     theCase.loadAnnotations(dc, "flag", Annotationtype.FLAG, null);
2839 20 Oct 14 olle 685     theCase.setAnnotation("comment", s.getDescription());
4102 15 Sep 16 nicklas 686     
4260 06 Dec 16 nicklas 687     theCase.setAnnotation("site", Site.findByCaseName(s.getName()).asJSONObject());
2839 20 Oct 14 olle 688   }
2839 20 Oct 14 olle 689   
2839 20 Oct 14 olle 690   private void loadBloodInfo(DbControl dc, Blood blood)
2839 20 Oct 14 olle 691   {
2839 20 Oct 14 olle 692     Sample s = blood.getItem();
2839 20 Oct 14 olle 693     
2839 20 Oct 14 olle 694     blood.setAnnotation("registrationDate", Reggie.CONVERTER_DATE_TO_STRING.convert(s.getEntryDate()));
2839 20 Oct 14 olle 695     blood.setAnnotation("editable", s.hasPermission(Permission.WRITE));
2839 20 Oct 14 olle 696     
2839 20 Oct 14 olle 697     Consent.loadConsentAnnotations(dc, blood);
5642 04 Oct 19 nicklas 698     blood.loadAnnotations(dc, "RetractStatus", Annotationtype.RETRACT_STATUS, null);
2839 20 Oct 14 olle 699     blood.loadAnnotations(dc, "samplingDate", Annotationtype.BLOOD_SAMPLING_DATETIME, Reggie.CONVERTER_DATETIME_TO_STRING);
2839 20 Oct 14 olle 700     blood.loadAnnotations(dc, "freezerDate", Annotationtype.BLOOD_FREEZER_DATETIME, Reggie.CONVERTER_DATETIME_TO_STRING);
2839 20 Oct 14 olle 701     blood.loadAnnotations(dc, "serum", Annotationtype.BLOOD_SERUM, null);
2839 20 Oct 14 olle 702     blood.loadAnnotations(dc, "bloodSample", Annotationtype.BLOOD_SAMPLE, null);
2839 20 Oct 14 olle 703     blood.loadAnnotations(dc, "bloodRccidNumber", Annotationtype.BLOOD_RCCIDNUMBER, null);
2839 20 Oct 14 olle 704     blood.loadAnnotations(dc, "flag", Annotationtype.FLAG, null);
2839 20 Oct 14 olle 705     blood.setAnnotation("comment", s.getDescription());
2839 20 Oct 14 olle 706   }
2839 20 Oct 14 olle 707   
2839 20 Oct 14 olle 708   private void loadPatientInfo(DbControl dc, Patient patient)
2839 20 Oct 14 olle 709   {
2839 20 Oct 14 olle 710     BioSource b = patient.getBioSource();
2839 20 Oct 14 olle 711     
2839 20 Oct 14 olle 712     patient.setAnnotation("registrationDate", Reggie.CONVERTER_DATE_TO_STRING.convert(b.getEntryDate()));
2839 20 Oct 14 olle 713     patient.setAnnotation("editable", b.hasPermission(Permission.WRITE));
3425 25 Jun 15 nicklas 714     patient.setAnnotation("subtype", b.getItemSubtype().getName());
2839 20 Oct 14 olle 715     
2839 20 Oct 14 olle 716     patient.loadDefaultAnnotations(dc);
3756 18 Feb 16 olle 717     patient.loadAnnotations(dc, "labDateNa", Annotationtype.RETRACT_NA_LAB, null);
3323 11 May 15 nicklas 718     patient.loadAnnotations(dc, "labSentDate", Annotationtype.RETRACT_TX_LAB, Reggie.CONVERTER_DATE_TO_STRING);
3323 11 May 15 nicklas 719     patient.loadAnnotations(dc, "labReceivedDate", Annotationtype.RETRACT_RX_LAB, Reggie.CONVERTER_DATE_TO_STRING);
3756 18 Feb 16 olle 720     patient.loadAnnotations(dc, "bloodDateNa", Annotationtype.RETRACT_NA_BB, null);
3323 11 May 15 nicklas 721     patient.loadAnnotations(dc, "bloodSentDate", Annotationtype.RETRACT_TX_BB, Reggie.CONVERTER_DATE_TO_STRING);
3323 11 May 15 nicklas 722     patient.loadAnnotations(dc, "bloodReceivedDate", Annotationtype.RETRACT_RX_BB, Reggie.CONVERTER_DATE_TO_STRING);
3756 18 Feb 16 olle 723     patient.loadAnnotations(dc, "frozenDateNa", Annotationtype.RETRACT_NA_FROZEN, null);
3323 11 May 15 nicklas 724     patient.loadAnnotations(dc, "frozenSentDate", Annotationtype.RETRACT_TX_FROZEN, Reggie.CONVERTER_DATE_TO_STRING);
3323 11 May 15 nicklas 725     patient.loadAnnotations(dc, "frozenReceivedDate", Annotationtype.RETRACT_RX_FROZEN, Reggie.CONVERTER_DATE_TO_STRING);
3756 18 Feb 16 olle 726     patient.loadAnnotations(dc, "rccSydDateNa", Annotationtype.RETRACT_NA_RCC_SYD, null);
3323 11 May 15 nicklas 727     patient.loadAnnotations(dc, "rccSydSentDate", Annotationtype.RETRACT_TX_RCC_SYD, Reggie.CONVERTER_DATE_TO_STRING);
3323 11 May 15 nicklas 728     patient.loadAnnotations(dc, "retractStatus", Annotationtype.RETRACT_STATUS, null);
2839 20 Oct 14 olle 729   }
2839 20 Oct 14 olle 730   
2839 20 Oct 14 olle 731   private void loadSpecimenInfo(DbControl dc, SpecimenTube specimen)
2839 20 Oct 14 olle 732   {
2839 20 Oct 14 olle 733     Sample s = specimen.getSample();
2839 20 Oct 14 olle 734     specimen.loadBioPlateLocation();
6731 05 May 22 nicklas 735     specimen.loadAnnotations(dc, "label", Annotationtype.TUBE_LABEL, null);
5642 04 Oct 19 nicklas 736     specimen.loadAnnotations(dc, "RetractStatus", Annotationtype.RETRACT_STATUS, null);
2839 20 Oct 14 olle 737     specimen.setAnnotation("registrationDate", Reggie.CONVERTER_DATE_TO_STRING.convert(s.getEntryDate()));
2839 20 Oct 14 olle 738     specimen.setAnnotation("editable", s.hasPermission(Permission.WRITE));
2839 20 Oct 14 olle 739     
2839 20 Oct 14 olle 740     specimen.loadAnnotations(dc, "laterality", Annotationtype.LATERALITY, null);
2839 20 Oct 14 olle 741     specimen.loadAnnotations(dc, "pad", Annotationtype.PAD, null);
2839 20 Oct 14 olle 742     specimen.loadAnnotations(dc, "samplingDate", Annotationtype.SAMPLING_DATETIME,  Reggie.CONVERTER_DATETIME_TO_STRING);
2839 20 Oct 14 olle 743     specimen.setAnnotation("comment", s.getDescription());
2839 20 Oct 14 olle 744   }
6155 01 Mar 21 nicklas 745
2839 20 Oct 14 olle 746   private void loadNoSpecimenInfo(DbControl dc, NoSpecimen noSpecimen)
2839 20 Oct 14 olle 747   {
2839 20 Oct 14 olle 748     Sample s = noSpecimen.getSample();
2839 20 Oct 14 olle 749     noSpecimen.setAnnotation("registrationDate", Reggie.CONVERTER_DATE_TO_STRING.convert(s.getEntryDate()));
2839 20 Oct 14 olle 750     noSpecimen.setAnnotation("editable", s.hasPermission(Permission.WRITE));
2839 20 Oct 14 olle 751     
2839 20 Oct 14 olle 752     noSpecimen.loadAnnotations(dc, "laterality", Annotationtype.LATERALITY, null);
2839 20 Oct 14 olle 753     noSpecimen.loadAnnotations(dc, "pad", Annotationtype.PAD, null);
2839 20 Oct 14 olle 754     noSpecimen.loadAnnotations(dc, "samplingDate", Annotationtype.SAMPLING_DATETIME,  Reggie.CONVERTER_DATE_TO_STRING);
2839 20 Oct 14 olle 755     noSpecimen.setAnnotation("comment", s.getDescription());
2839 20 Oct 14 olle 756   }
2839 20 Oct 14 olle 757
2839 20 Oct 14 olle 758   private void loadHistologyInfo(DbControl dc, Histology his)
2839 20 Oct 14 olle 759   {
2839 20 Oct 14 olle 760     Sample s = his.getSample();
2839 20 Oct 14 olle 761     
2839 20 Oct 14 olle 762     his.loadBioPlateLocation();
2839 20 Oct 14 olle 763     his.setAnnotation("registrationDate", Reggie.CONVERTER_DATE_TO_STRING.convert(s.getEntryDate()));
2839 20 Oct 14 olle 764     his.setAnnotation("editable", s.hasPermission(Permission.WRITE));
2839 20 Oct 14 olle 765     
2839 20 Oct 14 olle 766     his.loadAnnotations(dc, "partitionDate", Annotationtype.PARTITION_DATE, Reggie.CONVERTER_DATE_TO_STRING);
4109 15 Sep 16 nicklas 767     his.loadAnnotations(dc, "flag", Annotationtype.FLAG, null);
4109 15 Sep 16 nicklas 768     his.loadAnnotations(dc, "autoProcessing", Annotationtype.AUTO_PROCESSING, null);
2839 20 Oct 14 olle 769   }
2839 20 Oct 14 olle 770   
4109 15 Sep 16 nicklas 771   private JSONObject loadStainedInfo(DbControl dc, Sample stained)
4109 15 Sep 16 nicklas 772   {
4109 15 Sep 16 nicklas 773     JSONObject jsonStain = new JSONObject();
4109 15 Sep 16 nicklas 774     jsonStain.put("id", stained.getId());
4109 15 Sep 16 nicklas 775     jsonStain.put("name", stained.getName());
4109 15 Sep 16 nicklas 776     jsonStain.put("bioWell", JsonUtil.getBioWellAsJSON(stained.getBioWell(), true));
4109 15 Sep 16 nicklas 777     jsonStain.put("comments", stained.getDescription());
4109 15 Sep 16 nicklas 778     jsonStain.put("flag", (String) Annotationtype.FLAG.getAnnotationValue(dc, stained));
4109 15 Sep 16 nicklas 779     return jsonStain;
4109 15 Sep 16 nicklas 780   }
4109 15 Sep 16 nicklas 781
2839 20 Oct 14 olle 782   private void loadLysateInfo(DbControl dc, Lysate lys)
2839 20 Oct 14 olle 783   {
2839 20 Oct 14 olle 784     Extract e = lys.getExtract();
2839 20 Oct 14 olle 785     BioMaterialEvent created = e.getCreationEvent();
2839 20 Oct 14 olle 786     
2839 20 Oct 14 olle 787     lys.loadBioPlateLocation();
6731 05 May 22 nicklas 788     lys.loadAnnotations(dc, "label", Annotationtype.TUBE_LABEL, null);
5642 04 Oct 19 nicklas 789     lys.loadAnnotations(dc, "RetractStatus", Annotationtype.RETRACT_STATUS, null);
2839 20 Oct 14 olle 790     lys.setAnnotation("registrationDate", Reggie.CONVERTER_DATE_TO_STRING.convert(e.getEntryDate()));
2839 20 Oct 14 olle 791     lys.setAnnotation("editable", e.hasPermission(Permission.WRITE));  
2839 20 Oct 14 olle 792     lys.loadAnnotations(dc, "partitionDate", Annotationtype.PARTITION_DATE, Reggie.CONVERTER_DATE_TO_STRING);
2839 20 Oct 14 olle 793     lys.setAnnotation("comment", e.getDescription());
2839 20 Oct 14 olle 794     
2839 20 Oct 14 olle 795     if (created.getEventDate() != null)
2839 20 Oct 14 olle 796     {
2839 20 Oct 14 olle 797       lys.setAnnotation("lysisDate", Reggie.CONVERTER_DATE_TO_STRING.convert(created.getEventDate()));
2839 20 Oct 14 olle 798     }
2839 20 Oct 14 olle 799     
2839 20 Oct 14 olle 800   }
2839 20 Oct 14 olle 801
2839 20 Oct 14 olle 802   private void loadRnaInfo(DbControl dc, Rna rna)
2839 20 Oct 14 olle 803   {
2839 20 Oct 14 olle 804     Extract e = rna.getExtract();
2839 20 Oct 14 olle 805     
2839 20 Oct 14 olle 806     rna.loadBioPlateLocation();
6731 05 May 22 nicklas 807     rna.loadAnnotations(dc, "label", Annotationtype.TUBE_LABEL, null);
5642 04 Oct 19 nicklas 808     rna.loadAnnotations(dc, "RetractStatus", Annotationtype.RETRACT_STATUS, null);
2839 20 Oct 14 olle 809     rna.setAnnotation("registrationDate", Reggie.CONVERTER_DATE_TO_STRING.convert(e.getEntryDate()));
2839 20 Oct 14 olle 810     rna.setAnnotation("autoProcessing", (String) Annotationtype.AUTO_PROCESSING.getAnnotationValue(dc, e));
2839 20 Oct 14 olle 811     rna.setAnnotation("flag", (String) Annotationtype.FLAG.getAnnotationValue(dc, e));
2839 20 Oct 14 olle 812     rna.setAnnotation("editable", e.hasPermission(Permission.WRITE));  
2839 20 Oct 14 olle 813     rna.setAnnotation("comment", e.getDescription());
2839 20 Oct 14 olle 814   }
4107 15 Sep 16 nicklas 815   
4107 15 Sep 16 nicklas 816   private void loadRnaQcInfo(DbControl dc, RnaQc qc)
4107 15 Sep 16 nicklas 817   {
4107 15 Sep 16 nicklas 818     Extract e = qc.getExtract();
4107 15 Sep 16 nicklas 819     qc.setAnnotation("bioWell", JsonUtil.getBioWellAsJSON(e.getBioWell(), true));
4107 15 Sep 16 nicklas 820     qc.setAnnotation("comments", e.getDescription());
4107 15 Sep 16 nicklas 821     qc.loadAnnotations(dc, "flag", Annotationtype.FLAG, null);
4107 15 Sep 16 nicklas 822   }
4107 15 Sep 16 nicklas 823   
2839 20 Oct 14 olle 824   private void loadDnaInfo(DbControl dc, Dna dna)
2839 20 Oct 14 olle 825   {
2839 20 Oct 14 olle 826     Extract e = dna.getExtract();
2839 20 Oct 14 olle 827     
2839 20 Oct 14 olle 828     dna.loadBioPlateLocation();
6731 05 May 22 nicklas 829     dna.loadAnnotations(dc, "label", Annotationtype.TUBE_LABEL, null);
5642 04 Oct 19 nicklas 830     dna.loadAnnotations(dc, "RetractStatus", Annotationtype.RETRACT_STATUS, null);
2839 20 Oct 14 olle 831     dna.setAnnotation("registrationDate", Reggie.CONVERTER_DATE_TO_STRING.convert(e.getEntryDate()));
2839 20 Oct 14 olle 832     dna.setAnnotation("editable", e.hasPermission(Permission.WRITE));  
2839 20 Oct 14 olle 833     dna.setAnnotation("comment", e.getDescription());
2839 20 Oct 14 olle 834   }
2839 20 Oct 14 olle 835
3360 29 May 15 olle 836   private void loadBloodDnaInfo(DbControl dc, BloodDna dna)
3360 29 May 15 olle 837   {
3360 29 May 15 olle 838     Extract e = dna.getExtract();
3360 29 May 15 olle 839     
3360 29 May 15 olle 840     dna.loadBioPlateLocation();
6731 05 May 22 nicklas 841     dna.loadAnnotations(dc, "label", Annotationtype.TUBE_LABEL, null);
5642 04 Oct 19 nicklas 842     dna.loadAnnotations(dc, "RetractStatus", Annotationtype.RETRACT_STATUS, null);
3360 29 May 15 olle 843     dna.setAnnotation("registrationDate", Reggie.CONVERTER_DATE_TO_STRING.convert(e.getEntryDate()));
3360 29 May 15 olle 844     dna.setAnnotation("editable", e.hasPermission(Permission.WRITE));  
3360 29 May 15 olle 845     dna.setAnnotation("comment", e.getDescription());
3360 29 May 15 olle 846   }
3360 29 May 15 olle 847
2839 20 Oct 14 olle 848   private void loadFlowThroughInfo(DbControl dc, FlowThrough ft)
2839 20 Oct 14 olle 849   {
2839 20 Oct 14 olle 850     Extract e = ft.getExtract();
2839 20 Oct 14 olle 851     
2839 20 Oct 14 olle 852     ft.loadBioPlateLocation();
6731 05 May 22 nicklas 853     ft.loadAnnotations(dc, "label", Annotationtype.TUBE_LABEL, null);
5642 04 Oct 19 nicklas 854     ft.loadAnnotations(dc, "RetractStatus", Annotationtype.RETRACT_STATUS, null);
2839 20 Oct 14 olle 855     ft.setAnnotation("registrationDate", Reggie.CONVERTER_DATE_TO_STRING.convert(e.getEntryDate()));
2839 20 Oct 14 olle 856     ft.setAnnotation("editable", e.hasPermission(Permission.WRITE));  
2839 20 Oct 14 olle 857     ft.setAnnotation("comment", e.getDescription());
2839 20 Oct 14 olle 858   }
2839 20 Oct 14 olle 859
2839 20 Oct 14 olle 860   private void loadMRnaInfo(DbControl dc, MRna mrna)
2839 20 Oct 14 olle 861   {
2839 20 Oct 14 olle 862     Extract e = mrna.getExtract();
2839 20 Oct 14 olle 863     
2839 20 Oct 14 olle 864     mrna.loadBioPlateLocation();
2839 20 Oct 14 olle 865     mrna.setAnnotation("registrationDate", Reggie.CONVERTER_DATE_TO_STRING.convert(e.getEntryDate()));
2839 20 Oct 14 olle 866     mrna.setAnnotation("editable", e.hasPermission(Permission.WRITE));  
2839 20 Oct 14 olle 867     mrna.setAnnotation("comment", e.getDescription());
2839 20 Oct 14 olle 868   }
2839 20 Oct 14 olle 869
2839 20 Oct 14 olle 870   private void loadCDnaInfo(DbControl dc, CDna cdna)
2839 20 Oct 14 olle 871   {
2839 20 Oct 14 olle 872     Extract e = cdna.getExtract();
2839 20 Oct 14 olle 873     
2839 20 Oct 14 olle 874     cdna.loadBioPlateLocation();
2839 20 Oct 14 olle 875     cdna.setAnnotation("registrationDate", Reggie.CONVERTER_DATE_TO_STRING.convert(e.getEntryDate()));
2839 20 Oct 14 olle 876     cdna.setAnnotation("editable", e.hasPermission(Permission.WRITE));  
2839 20 Oct 14 olle 877     cdna.setAnnotation("comment", e.getDescription());
2839 20 Oct 14 olle 878   }
2839 20 Oct 14 olle 879
2839 20 Oct 14 olle 880   private void loadLibraryInfo(DbControl dc, Library lib)
2839 20 Oct 14 olle 881   {
2839 20 Oct 14 olle 882     Extract e = lib.getExtract();
2839 20 Oct 14 olle 883     
2839 20 Oct 14 olle 884     lib.loadBioPlateLocation();
2839 20 Oct 14 olle 885     lib.setAnnotation("registrationDate", Reggie.CONVERTER_DATE_TO_STRING.convert(e.getEntryDate()));
2839 20 Oct 14 olle 886     lib.setAnnotation("editable", e.hasPermission(Permission.WRITE));  
2839 20 Oct 14 olle 887     lib.setAnnotation("comment", e.getDescription());
2839 20 Oct 14 olle 888   }
2839 20 Oct 14 olle 889
2839 20 Oct 14 olle 890   private void loadPooledLibraryInfo(DbControl dc, PooledLibrary lib)
2839 20 Oct 14 olle 891   {
2839 20 Oct 14 olle 892     Extract e = lib.getExtract();
2839 20 Oct 14 olle 893     BioMaterialEvent created = e.getCreationEvent();
2839 20 Oct 14 olle 894     
2839 20 Oct 14 olle 895     lib.setAnnotation("registrationDate", Reggie.CONVERTER_DATE_TO_STRING.convert(e.getEntryDate()));
2839 20 Oct 14 olle 896     lib.setAnnotation("editable", e.hasPermission(Permission.WRITE));  
2839 20 Oct 14 olle 897     lib.setAnnotation("poolDate", Reggie.CONVERTER_DATE_TO_STRING.convert(created.getEventDate()));
2839 20 Oct 14 olle 898     lib.setAnnotation("comment", e.getDescription());
2839 20 Oct 14 olle 899   }
2839 20 Oct 14 olle 900   
2839 20 Oct 14 olle 901   private void loadSequencingRunInfo(DbControl dc, SequencingRun sr)
2839 20 Oct 14 olle 902   {
2839 20 Oct 14 olle 903     DerivedBioAssay dba = sr.getDerivedBioAssay();
2839 20 Oct 14 olle 904     
2839 20 Oct 14 olle 905     sr.setAnnotation("editable", dba.hasPermission(Permission.WRITE));
2839 20 Oct 14 olle 906     sr.loadAnnotations(dc, "startDate", Annotationtype.SEQUENCING_START, Reggie.CONVERTER_DATE_TO_STRING);
2839 20 Oct 14 olle 907     sr.loadAnnotations(dc, "endDate", Annotationtype.SEQUENCING_END, Reggie.CONVERTER_DATE_TO_STRING);
2839 20 Oct 14 olle 908     sr.loadAnnotations(dc, "result", Annotationtype.SEQUENCING_RESULT, null);
2839 20 Oct 14 olle 909     sr.setAnnotation("comment", dba.getDescription());
2839 20 Oct 14 olle 910     
2839 20 Oct 14 olle 911     FlowCell fc = FlowCell.getBySequencingRun(dc, sr);
2839 20 Oct 14 olle 912     PhysicalBioAssay pba = fc.getPhysicalBioAssay();
2839 20 Oct 14 olle 913     
2839 20 Oct 14 olle 914     fc.setAnnotation("editable", pba.hasPermission(Permission.WRITE));
2839 20 Oct 14 olle 915     fc.loadAnnotations(dc, "clusterDate", Annotationtype.CLUSTER_START, Reggie.CONVERTER_DATE_TO_STRING);
2839 20 Oct 14 olle 916     sr.setAnnotation("flowCell", fc.asJSONObject());
2839 20 Oct 14 olle 917   }
2839 20 Oct 14 olle 918   
2839 20 Oct 14 olle 919   @SuppressWarnings("unchecked")
2839 20 Oct 14 olle 920   @Override
2839 20 Oct 14 olle 921   protected void doPost(HttpServletRequest req, HttpServletResponse resp)
2839 20 Oct 14 olle 922     throws ServletException, IOException 
2839 20 Oct 14 olle 923   {
2839 20 Oct 14 olle 924     String cmd = req.getParameter("cmd");
2839 20 Oct 14 olle 925     JsonUtil.setJsonResponseHeaders(resp);
2839 20 Oct 14 olle 926     
2839 20 Oct 14 olle 927     JSONObject json = new JSONObject();
2839 20 Oct 14 olle 928     json.put("status", "ok");
2839 20 Oct 14 olle 929     
2839 20 Oct 14 olle 930     JSONArray jsonMessages = new JSONArray();
2839 20 Oct 14 olle 931   
3975 26 May 16 nicklas 932     final SessionControl sc = Reggie.getSessionControl(req);
2839 20 Oct 14 olle 933     DbControl dc = null;
2839 20 Oct 14 olle 934     try
2839 20 Oct 14 olle 935     {
2839 20 Oct 14 olle 936       if ("RegisterRetraction".equals(cmd))
2839 20 Oct 14 olle 937       {
6329 14 Jun 21 nicklas 938         dc = sc.newDbControl(":Retraction wizard - retract");
2839 20 Oct 14 olle 939
2839 20 Oct 14 olle 940         ReggieRole.checkPermission(dc, "'" + cmd + "' wizard", ReggieRole.PATIENT_CURATOR, ReggieRole.ADMINISTRATOR);
2839 20 Oct 14 olle 941
3752 17 Feb 16 nicklas 942         JSONObject jsonReq = JsonUtil.parseRequest(req);
2839 20 Oct 14 olle 943         JSONObject jsonRetractedInfo = (JSONObject)jsonReq.get("retractionInfo");
2839 20 Oct 14 olle 944         List<String> selectedSamples = (List<String>) jsonRetractedInfo.get("selectedSamples");
2839 20 Oct 14 olle 945         boolean forceResetWhenUnchecked = false;
2839 20 Oct 14 olle 946         Boolean forceResetWhenUncheckedInput = (Boolean) jsonRetractedInfo.get("forceResetWhenUnchecked");
2839 20 Oct 14 olle 947         if (forceResetWhenUncheckedInput != null && forceResetWhenUncheckedInput)
2839 20 Oct 14 olle 948         {
2839 20 Oct 14 olle 949           forceResetWhenUnchecked = true;
2839 20 Oct 14 olle 950         }
2839 20 Oct 14 olle 951         // Set annotations for Flag and AutoProcessing
2839 20 Oct 14 olle 952         int numAnnotationsModified = 0;
2839 20 Oct 14 olle 953         List<String> itemTypePlusIdList = new ArrayList<String>();
2839 20 Oct 14 olle 954         if (selectedSamples != null)
2839 20 Oct 14 olle 955         {
2839 20 Oct 14 olle 956           for (String checkboxName: selectedSamples)
2839 20 Oct 14 olle 957           {
2839 20 Oct 14 olle 958             if (checkboxName != null && !checkboxName.equals(""))
2839 20 Oct 14 olle 959             {
2839 20 Oct 14 olle 960               boolean checked = true;
2839 20 Oct 14 olle 961               if (checkboxName.endsWith("_unchecked"))
2839 20 Oct 14 olle 962               {
2839 20 Oct 14 olle 963                 checked = false;
2839 20 Oct 14 olle 964                 // Remove unchecked suffix
2839 20 Oct 14 olle 965                 int unCheckSuffixIndex = checkboxName.indexOf("_unchecked");
2839 20 Oct 14 olle 966                 checkboxName = checkboxName.substring(0, unCheckSuffixIndex);
2839 20 Oct 14 olle 967               }
2839 20 Oct 14 olle 968               int dotIndex = checkboxName.indexOf(".");
2839 20 Oct 14 olle 969               // Get substring before first dot
2839 20 Oct 14 olle 970               String itemTypeStr = checkboxName.substring(0, dotIndex);
2839 20 Oct 14 olle 971               int lastDotIndex = checkboxName.lastIndexOf(".");
2839 20 Oct 14 olle 972               // Get substring after last dot
2839 20 Oct 14 olle 973               String itemIdStr = checkboxName.substring(lastDotIndex + 1);
2839 20 Oct 14 olle 974               int itemId = 0;
2839 20 Oct 14 olle 975               try
2839 20 Oct 14 olle 976               {
2839 20 Oct 14 olle 977                 itemId = Integer.parseInt(itemIdStr);
2839 20 Oct 14 olle 978               }
2839 20 Oct 14 olle 979               catch (NumberFormatException e)
2839 20 Oct 14 olle 980               {}
2839 20 Oct 14 olle 981               // Get substring between first and last dot
2839 20 Oct 14 olle 982               // Step A: Get substring before last dot
2839 20 Oct 14 olle 983               String checkboxVarName = checkboxName.substring(0, lastDotIndex);
2839 20 Oct 14 olle 984               // Step B: Get substring after first dot of previous string
2839 20 Oct 14 olle 985               checkboxVarName = checkboxVarName.substring(dotIndex + 1);
2839 20 Oct 14 olle 986               if (itemTypeStr != null && !itemTypeStr.equals("") && itemId > 0)
2839 20 Oct 14 olle 987               {
2839 20 Oct 14 olle 988                 boolean annotationModified = false;
2839 20 Oct 14 olle 989                 if (itemTypeStr.equals("histology"))
2839 20 Oct 14 olle 990                 {
2839 20 Oct 14 olle 991                   Histology his = Histology.getById(dc, itemId);
2839 20 Oct 14 olle 992                   if (checkboxVarName.equals("retracted"))
2839 20 Oct 14 olle 993                   {
2839 20 Oct 14 olle 994                     String flagValue = (String) Annotationtype.FLAG.getAnnotationValue(dc, his.getSample());
2839 20 Oct 14 olle 995                     if (checked && (flagValue == null || !flagValue.equals(Consent.FLAG_RETRACTED)))
2839 20 Oct 14 olle 996                     {
2839 20 Oct 14 olle 997                       Annotationtype.FLAG.setAnnotationValue(dc, his.getSample(), Consent.FLAG_RETRACTED);
2839 20 Oct 14 olle 998                       annotationModified = true;
2839 20 Oct 14 olle 999                     }
2839 20 Oct 14 olle 1000                     else if (!checked && forceResetWhenUnchecked && flagValue != null)
2839 20 Oct 14 olle 1001                     {
2839 20 Oct 14 olle 1002                       Annotationtype.FLAG.setAnnotationValue(dc, his.getSample(), null);
2839 20 Oct 14 olle 1003                       annotationModified = true;
2839 20 Oct 14 olle 1004                     }
2839 20 Oct 14 olle 1005                   }
2839 20 Oct 14 olle 1006                   else if (checkboxVarName.equals("autoProcessingDisable"))
2839 20 Oct 14 olle 1007                   {
2839 20 Oct 14 olle 1008                     String autoProcessingValue = (String) Annotationtype.AUTO_PROCESSING.getAnnotationValue(dc, his.getSample());
2839 20 Oct 14 olle 1009                     if (checked && (autoProcessingValue == null || !autoProcessingValue.equals(AUTO_PROCESSING_DISABLE)))
2839 20 Oct 14 olle 1010                     {
2839 20 Oct 14 olle 1011                       Annotationtype.AUTO_PROCESSING.setAnnotationValue(dc, his.getSample(), AUTO_PROCESSING_DISABLE);
2839 20 Oct 14 olle 1012                       annotationModified = true;
2839 20 Oct 14 olle 1013                     }
2839 20 Oct 14 olle 1014                     else if (!checked && forceResetWhenUnchecked && autoProcessingValue != null)
2839 20 Oct 14 olle 1015                     {
2839 20 Oct 14 olle 1016                       Annotationtype.AUTO_PROCESSING.setAnnotationValue(dc, his.getSample(), null);
2839 20 Oct 14 olle 1017                       annotationModified = true;
2839 20 Oct 14 olle 1018                     }
2839 20 Oct 14 olle 1019                   }
2839 20 Oct 14 olle 1020                 }
2839 20 Oct 14 olle 1021                 else if (itemTypeStr.equals("rna"))
2839 20 Oct 14 olle 1022                 {
2839 20 Oct 14 olle 1023                   Extract rna = Extract.getById(dc, itemId);
2839 20 Oct 14 olle 1024                   rna.setItemSubtype(Subtype.RNA.load(dc));
2839 20 Oct 14 olle 1025                   if (checkboxVarName.equals("retracted"))
2839 20 Oct 14 olle 1026                   {
2839 20 Oct 14 olle 1027                     String flagValue = (String) Annotationtype.FLAG.getAnnotationValue(dc, rna);
2839 20 Oct 14 olle 1028                     if (checked && (flagValue == null || !flagValue.equals(Consent.FLAG_RETRACTED)))
2839 20 Oct 14 olle 1029                     {
2839 20 Oct 14 olle 1030                       Annotationtype.FLAG.setAnnotationValue(dc, rna, Consent.FLAG_RETRACTED);
2839 20 Oct 14 olle 1031                       annotationModified = true;
2839 20 Oct 14 olle 1032                     }
2839 20 Oct 14 olle 1033                     else if (!checked && forceResetWhenUnchecked && flagValue != null)
2839 20 Oct 14 olle 1034                     {
2839 20 Oct 14 olle 1035                       Annotationtype.FLAG.setAnnotationValue(dc, rna, null);
2839 20 Oct 14 olle 1036                       annotationModified = true;
2839 20 Oct 14 olle 1037                     }
2839 20 Oct 14 olle 1038                   }
2839 20 Oct 14 olle 1039                   else if (checkboxVarName.equals("autoProcessingDisable"))
2839 20 Oct 14 olle 1040                   {
2839 20 Oct 14 olle 1041                     String autoProcessingValue = (String) Annotationtype.AUTO_PROCESSING.getAnnotationValue(dc, rna);
2839 20 Oct 14 olle 1042                     if (checked && (autoProcessingValue == null || !autoProcessingValue.equals(AUTO_PROCESSING_DISABLE)))
2839 20 Oct 14 olle 1043                     {
2839 20 Oct 14 olle 1044                       Annotationtype.AUTO_PROCESSING.setAnnotationValue(dc, rna, AUTO_PROCESSING_DISABLE);
2839 20 Oct 14 olle 1045                       annotationModified = true;
2839 20 Oct 14 olle 1046                     }
2839 20 Oct 14 olle 1047                     else if (!checked && forceResetWhenUnchecked && autoProcessingValue != null)
2839 20 Oct 14 olle 1048                     {
2839 20 Oct 14 olle 1049                       Annotationtype.AUTO_PROCESSING.setAnnotationValue(dc, rna, null);
2839 20 Oct 14 olle 1050                       annotationModified = true;
2839 20 Oct 14 olle 1051                     }
2839 20 Oct 14 olle 1052                   }
2839 20 Oct 14 olle 1053                 }
2839 20 Oct 14 olle 1054                 if (annotationModified)
2839 20 Oct 14 olle 1055                 {
2839 20 Oct 14 olle 1056                   numAnnotationsModified++;
2839 20 Oct 14 olle 1057                   // Update list of affected items, if item not already listed for other annotation
2839 20 Oct 14 olle 1058                   String itemTypePlusId = itemTypeStr + "_" + itemId;
2839 20 Oct 14 olle 1059                   if (!itemTypePlusIdList.contains(itemTypePlusId))
2839 20 Oct 14 olle 1060                   {
2839 20 Oct 14 olle 1061                     itemTypePlusIdList.add(itemTypePlusId);
2839 20 Oct 14 olle 1062                   }
2839 20 Oct 14 olle 1063                 }
2839 20 Oct 14 olle 1064               }
2839 20 Oct 14 olle 1065             }
2839 20 Oct 14 olle 1066           }
2839 20 Oct 14 olle 1067         }
2839 20 Oct 14 olle 1068         if (numAnnotationsModified > 0)
2839 20 Oct 14 olle 1069         {
2839 20 Oct 14 olle 1070           int numItemsAffected = itemTypePlusIdList.size();
2839 20 Oct 14 olle 1071           jsonMessages.add(numAnnotationsModified + " annotations modified for " + numItemsAffected + " items.");
2839 20 Oct 14 olle 1072         }
2839 20 Oct 14 olle 1073         else
2839 20 Oct 14 olle 1074         {
2839 20 Oct 14 olle 1075           jsonMessages.add("No annotations modified.");
2839 20 Oct 14 olle 1076         }
2839 20 Oct 14 olle 1077         // Modify BioSource type from Patient to Retract or RetroNo and name from "PAT*" to Retract or RetroNo + 6-figure consecutive serial number
2839 20 Oct 14 olle 1078         // Get existing BioSource type and name
2839 20 Oct 14 olle 1079         String caseName = (String) jsonRetractedInfo.get("caseName");
5639 03 Oct 19 nicklas 1080         ReggieItem<? extends BioMaterial> patientOrCase = fetchPatientOrCase(dc, 0, caseName);
4312 18 Jan 17 nicklas 1081         BioSource bioSource = null; // This should be the Patient (or Retract/RetroNo item)
4312 18 Jan 17 nicklas 1082         
4312 18 Jan 17 nicklas 1083         if (patientOrCase instanceof Case)
2839 20 Oct 14 olle 1084         {
4312 18 Jan 17 nicklas 1085           // We have no Patient information here for this case
4312 18 Jan 17 nicklas 1086           // Create a new biosource item, name and subtype is set below
4312 18 Jan 17 nicklas 1087           bioSource = BioSource.getNew(dc);
4312 18 Jan 17 nicklas 1088           Sample theCase = (Sample)patientOrCase.getItem();
4312 18 Jan 17 nicklas 1089           theCase.getCreationEvent().setSource(bioSource);
4312 18 Jan 17 nicklas 1090           dc.saveItem(bioSource);
4496 10 May 17 nicklas 1091           
4496 10 May 17 nicklas 1092           // Set consent to "No"
4496 10 May 17 nicklas 1093           if (Annotationtype.CONSENT.setAnnotationValue(dc, theCase, "No"))
4496 10 May 17 nicklas 1094           {
4496 10 May 17 nicklas 1095             jsonMessages.add("Consent set to No on case " + theCase.getName());
4496 10 May 17 nicklas 1096           }
2839 20 Oct 14 olle 1097         }
4312 18 Jan 17 nicklas 1098         else
4312 18 Jan 17 nicklas 1099         {
4312 18 Jan 17 nicklas 1100           bioSource = (BioSource)patientOrCase.getItem();
4496 10 May 17 nicklas 1101           
4496 10 May 17 nicklas 1102           // Find all child+blood items and set consent to "No"
4496 10 May 17 nicklas 1103           ItemQuery<Sample> childQuery = Sample.getQuery();
4496 10 May 17 nicklas 1104           childQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
4496 10 May 17 nicklas 1105           childQuery.restrict(Restrictions.or(
4496 10 May 17 nicklas 1106             Subtype.CASE.restriction(dc, null),
4496 10 May 17 nicklas 1107             Subtype.BLOOD.restriction(dc, null)
4496 10 May 17 nicklas 1108             ));
4496 10 May 17 nicklas 1109           childQuery.restrict(Restrictions.eq(Hql.property("parent"), Hql.entity(bioSource)));
4496 10 May 17 nicklas 1110           for (Sample child: childQuery.list(dc))
4496 10 May 17 nicklas 1111           {
4496 10 May 17 nicklas 1112             if (Annotationtype.CONSENT.setAnnotationValue(dc, child, "No"))
4496 10 May 17 nicklas 1113             {
4496 10 May 17 nicklas 1114               jsonMessages.add("Consent set to No on " + child.getItemSubtype().getName() + " " + child.getName());
4496 10 May 17 nicklas 1115             }
4496 10 May 17 nicklas 1116           }
4312 18 Jan 17 nicklas 1117         }
4312 18 Jan 17 nicklas 1118         
2839 20 Oct 14 olle 1119         // Get BioSource type to set
4312 18 Jan 17 nicklas 1120         Subtype bioSourceTypeToSet = Subtype.getByCName((String)jsonRetractedInfo.get("bioSourceType"));
4312 18 Jan 17 nicklas 1121         ItemSubtype currentBioSourceType = bioSource.getItemSubtype();
4312 18 Jan 17 nicklas 1122         
4312 18 Jan 17 nicklas 1123         // Change the type and name if needed
4312 18 Jan 17 nicklas 1124         if (!bioSourceTypeToSet.get(dc).equals(currentBioSourceType))
2839 20 Oct 14 olle 1125         {
4894 09 Jul 18 nicklas 1126           String nextBioSourceName = Patient.getNextName(dc, bioSourceTypeToSet, true);
4312 18 Jan 17 nicklas 1127           bioSource.setItemSubtype(bioSourceTypeToSet.get(dc));
4312 18 Jan 17 nicklas 1128           if (bioSource.isInDatabase())
2839 20 Oct 14 olle 1129           {
4312 18 Jan 17 nicklas 1130             jsonMessages.add("BioSource type modified from " + currentBioSourceType.getName() + " to " + bioSourceTypeToSet.getName() + " and name from " + bioSource.getName() + " to " + nextBioSourceName + ".");
2839 20 Oct 14 olle 1131           }
4312 18 Jan 17 nicklas 1132           else
2839 20 Oct 14 olle 1133           {
4312 18 Jan 17 nicklas 1134             jsonMessages.add("BioSource '" + nextBioSourceName + "' created and linked with case " + patientOrCase.getName() + ".");
2839 20 Oct 14 olle 1135           }
4894 09 Jul 18 nicklas 1136           bioSource.setName(nextBioSourceName);
5088 13 Nov 18 nicklas 1137           bioSource.setExternalId(Patient.getNextExternalId(dc, bioSourceTypeToSet));
2839 20 Oct 14 olle 1138         }
2839 20 Oct 14 olle 1139         else
2839 20 Oct 14 olle 1140         {
2839 20 Oct 14 olle 1141           jsonMessages.add("No modification of BioSource type and name.");
2839 20 Oct 14 olle 1142         }
4312 18 Jan 17 nicklas 1143
2839 20 Oct 14 olle 1144         dc.commit();
2839 20 Oct 14 olle 1145       }
3323 11 May 15 nicklas 1146       else if ("RegisterFollowUp".equals(cmd))
3323 11 May 15 nicklas 1147       {
6329 14 Jun 21 nicklas 1148         dc = sc.newDbControl(":Retraction wizard - follow up");
3323 11 May 15 nicklas 1149
3323 11 May 15 nicklas 1150         ReggieRole.checkPermission(dc, "'" + cmd + "' wizard", ReggieRole.PATIENT_CURATOR, ReggieRole.ADMINISTRATOR);
3323 11 May 15 nicklas 1151
3752 17 Feb 16 nicklas 1152         JSONObject jsonReq = JsonUtil.parseRequest(req);
3323 11 May 15 nicklas 1153         JSONObject jsonRetractedInfo = (JSONObject)jsonReq.get("retractionInfo");
5643 07 Oct 19 nicklas 1154         JSONArray jsonDestructInfo = (JSONArray)jsonReq.get("destructInfo");
5643 07 Oct 19 nicklas 1155         
3323 11 May 15 nicklas 1156         // Get retraction request and response dates
3765 23 Feb 16 nicklas 1157         Number patientId = (Number)jsonRetractedInfo.get("patientId");
3756 18 Feb 16 olle 1158         // Lab
3756 18 Feb 16 olle 1159         Boolean labDateNa = (Boolean) jsonRetractedInfo.get("labDateNa");
3323 11 May 15 nicklas 1160         String labSentDateString = (String) jsonRetractedInfo.get("labSentDate");
3323 11 May 15 nicklas 1161         String labReceivedDateString = (String) jsonRetractedInfo.get("labReceivedDate");
3756 18 Feb 16 olle 1162         // Blood
3756 18 Feb 16 olle 1163         Boolean bloodDateNa = (Boolean) jsonRetractedInfo.get("bloodDateNa");
3323 11 May 15 nicklas 1164         String bloodSentDateString = (String) jsonRetractedInfo.get("bloodSentDate");
3323 11 May 15 nicklas 1165         String bloodReceivedDateString = (String) jsonRetractedInfo.get("bloodReceivedDate");
3756 18 Feb 16 olle 1166         // Frozen
3756 18 Feb 16 olle 1167         Boolean frozenDateNa = (Boolean) jsonRetractedInfo.get("frozenDateNa");
3323 11 May 15 nicklas 1168         String frozenSentDateString = (String) jsonRetractedInfo.get("frozenSentDate");
3323 11 May 15 nicklas 1169         String frozenReceivedDateString = (String) jsonRetractedInfo.get("frozenReceivedDate");
3756 18 Feb 16 olle 1170         // RCC Syd
3756 18 Feb 16 olle 1171         Boolean rccSydDateNa = (Boolean) jsonRetractedInfo.get("rccSydDateNa");
3323 11 May 15 nicklas 1172         String rccSydSentDateString = (String) jsonRetractedInfo.get("rccSydSentDate");
3323 11 May 15 nicklas 1173
3323 11 May 15 nicklas 1174         // Convert to date format
7024 07 Feb 23 nicklas 1175         StringToDateConverter dateConverter = new StringToDateConverter(FastDateFormat.getInstance("yyyyMMdd"));        
3323 11 May 15 nicklas 1176         Date labSentDate = dateConverter.convert(labSentDateString);
3323 11 May 15 nicklas 1177         Date labReceivedDate = dateConverter.convert(labReceivedDateString);
3323 11 May 15 nicklas 1178         Date bloodSentDate = dateConverter.convert(bloodSentDateString);
3323 11 May 15 nicklas 1179         Date bloodReceivedDate = dateConverter.convert(bloodReceivedDateString);
3323 11 May 15 nicklas 1180         Date frozenSentDate = dateConverter.convert(frozenSentDateString);
3323 11 May 15 nicklas 1181         Date frozenReceivedDate = dateConverter.convert(frozenReceivedDateString);
3323 11 May 15 nicklas 1182         Date rccSydSentDate = dateConverter.convert(rccSydSentDateString);
3323 11 May 15 nicklas 1183         int numAnnotationsModified = 0;
3765 23 Feb 16 nicklas 1184         
3765 23 Feb 16 nicklas 1185         BioSource patient = BioSource.getById(dc, patientId.intValue());
3765 23 Feb 16 nicklas 1186         
3765 23 Feb 16 nicklas 1187         // Update annotations to new values
5643 07 Oct 19 nicklas 1188         Annotationtype.RETRACT_NA_LAB.setAnnotationValue(dc, patient, labDateNa);
5643 07 Oct 19 nicklas 1189         if (Annotationtype.RETRACT_TX_LAB.setAnnotationValue(dc, patient, labSentDate)) numAnnotationsModified++;
5643 07 Oct 19 nicklas 1190         if (Annotationtype.RETRACT_RX_LAB.setAnnotationValue(dc, patient, labReceivedDate)) numAnnotationsModified++;
5643 07 Oct 19 nicklas 1191         
5643 07 Oct 19 nicklas 1192         Annotationtype.RETRACT_NA_BB.setAnnotationValue(dc, patient, bloodDateNa);
5643 07 Oct 19 nicklas 1193         if (Annotationtype.RETRACT_TX_BB.setAnnotationValue(dc, patient, bloodSentDate)) numAnnotationsModified++;
5643 07 Oct 19 nicklas 1194         if (Annotationtype.RETRACT_RX_BB.setAnnotationValue(dc, patient, bloodReceivedDate)) numAnnotationsModified++;
5643 07 Oct 19 nicklas 1195         
5643 07 Oct 19 nicklas 1196         Annotationtype.RETRACT_NA_FROZEN.setAnnotationValue(dc, patient, frozenDateNa);
5643 07 Oct 19 nicklas 1197         if (Annotationtype.RETRACT_TX_FROZEN.setAnnotationValue(dc, patient, frozenSentDate)) numAnnotationsModified++;
5643 07 Oct 19 nicklas 1198         if (Annotationtype.RETRACT_RX_FROZEN.setAnnotationValue(dc, patient, frozenReceivedDate)) numAnnotationsModified++;
5643 07 Oct 19 nicklas 1199         
5643 07 Oct 19 nicklas 1200         if (Annotationtype.RETRACT_NA_RCC_SYD.setAnnotationValue(dc, patient, rccSydDateNa)) numAnnotationsModified++;
5643 07 Oct 19 nicklas 1201         if (Annotationtype.RETRACT_TX_RCC_SYD.setAnnotationValue(dc, patient, rccSydSentDate)) numAnnotationsModified++;
5643 07 Oct 19 nicklas 1202         
5643 07 Oct 19 nicklas 1203         boolean allItemsDestructed = true;
5643 07 Oct 19 nicklas 1204         int numItemsDestructed = 0;
5643 07 Oct 19 nicklas 1205         for (int itemNo = 0; itemNo < jsonDestructInfo.size(); itemNo++)
3323 11 May 15 nicklas 1206         {
5643 07 Oct 19 nicklas 1207           JSONObject jsonItem = (JSONObject)jsonDestructInfo.get(itemNo);
5643 07 Oct 19 nicklas 1208           
5643 07 Oct 19 nicklas 1209           Item itemType = Item.valueOf((String)jsonItem.get("itemType"));
5643 07 Oct 19 nicklas 1210           Number itemId = (Number)jsonItem.get("id");
5643 07 Oct 19 nicklas 1211           boolean destructed = Boolean.TRUE.equals(jsonItem.get("destructed"));
5643 07 Oct 19 nicklas 1212           allItemsDestructed &= destructed;
5643 07 Oct 19 nicklas 1213           
5644 07 Oct 19 nicklas 1214           MeasuredBioMaterial item = itemType.getById(dc, itemId.intValue());
5644 07 Oct 19 nicklas 1215           if (Annotationtype.RETRACT_STATUS.setAnnotationValue(dc, item, destructed ? RETRACTION_DESTROYED :  null))
5643 07 Oct 19 nicklas 1216           {
5644 07 Oct 19 nicklas 1217             if (destructed) 
5644 07 Oct 19 nicklas 1218             {
5644 07 Oct 19 nicklas 1219               numItemsDestructed++;
5644 07 Oct 19 nicklas 1220               Float remainingQantity = item.getRemainingQuantity();
5644 07 Oct 19 nicklas 1221               if (remainingQantity != null && remainingQantity > 0)
5644 07 Oct 19 nicklas 1222               {
5644 07 Oct 19 nicklas 1223                 BioMaterialEvent destructEvent = BioMaterialEvent.getNew(dc, item);
5644 07 Oct 19 nicklas 1224                 destructEvent.setUsedQuantity(remainingQantity);
5644 07 Oct 19 nicklas 1225                 destructEvent.setComment("Destructed due to retraction of consent");
5644 07 Oct 19 nicklas 1226                 dc.saveItem(destructEvent);
5644 07 Oct 19 nicklas 1227               }
5644 07 Oct 19 nicklas 1228             }
5643 07 Oct 19 nicklas 1229           }
3323 11 May 15 nicklas 1230         }
5643 07 Oct 19 nicklas 1231         
3765 23 Feb 16 nicklas 1232         // Update "ReadyForDestruction" flag
3765 23 Feb 16 nicklas 1233         boolean labDateOk = (labDateNa != null && labDateNa) ||
3765 23 Feb 16 nicklas 1234             (labSentDate != null && labReceivedDate != null);
3765 23 Feb 16 nicklas 1235         boolean bloodDateOk = (bloodDateNa != null && bloodDateNa) ||
3765 23 Feb 16 nicklas 1236             (bloodSentDate != null && bloodReceivedDate != null);
3765 23 Feb 16 nicklas 1237         boolean frozenDateOk = (frozenDateNa != null && frozenDateNa) ||
3765 23 Feb 16 nicklas 1238             (frozenSentDate != null && frozenReceivedDate != null);
3765 23 Feb 16 nicklas 1239         boolean rccSydDateOk = (rccSydDateNa != null && rccSydDateNa) ||
3765 23 Feb 16 nicklas 1240             (rccSydSentDate != null);
3765 23 Feb 16 nicklas 1241         
5643 07 Oct 19 nicklas 1242         boolean readyForDestruction = labDateOk && bloodDateOk && frozenDateOk &&
5973 24 Jun 20 nicklas 1243           rccSydDateOk && allItemsDestructed;
5643 07 Oct 19 nicklas 1244         
5643 07 Oct 19 nicklas 1245         // Get current annotation values in order to count number of changed annotations
5643 07 Oct 19 nicklas 1246         String retractStatusOrig = (String) Annotationtype.RETRACT_STATUS.getAnnotationValue(dc, patient);
5643 07 Oct 19 nicklas 1247         String retractStatus = readyForDestruction ? READY_FOR_DESTRUCTION : null;
5643 07 Oct 19 nicklas 1248
3323 11 May 15 nicklas 1249         if (numAnnotationsModified > 0)
3323 11 May 15 nicklas 1250         {
3323 11 May 15 nicklas 1251           jsonMessages.add(numAnnotationsModified + " retract date annotations modified.");
3323 11 May 15 nicklas 1252         }
3323 11 May 15 nicklas 1253         else
3323 11 May 15 nicklas 1254         {
3323 11 May 15 nicklas 1255           jsonMessages.add("No retract date annotations modified.");
3323 11 May 15 nicklas 1256         }
5643 07 Oct 19 nicklas 1257         
5643 07 Oct 19 nicklas 1258         if (numItemsDestructed > 0)
3323 11 May 15 nicklas 1259         {
5643 07 Oct 19 nicklas 1260           jsonMessages.add(numItemsDestructed + " items registered as destroyed.");
3323 11 May 15 nicklas 1261         }
5643 07 Oct 19 nicklas 1262
5643 07 Oct 19 nicklas 1263         if (Annotationtype.RETRACT_STATUS.setAnnotationValue(dc, patient, retractStatus))
5643 07 Oct 19 nicklas 1264         {
5643 07 Oct 19 nicklas 1265           jsonMessages.add("\"RetractStatus\" annotation modified from " + retractStatusOrig + 
5643 07 Oct 19 nicklas 1266             " to " + retractStatus + ".");
5643 07 Oct 19 nicklas 1267         }
3323 11 May 15 nicklas 1268         else
3323 11 May 15 nicklas 1269         {
5643 07 Oct 19 nicklas 1270           jsonMessages.add("No modification of \"RetractStatus\" annotation.");
3323 11 May 15 nicklas 1271         }
3323 11 May 15 nicklas 1272         dc.commit();
3323 11 May 15 nicklas 1273       }
3337 18 May 15 olle 1274       else if ("RegisterDestruction".equals(cmd))
3337 18 May 15 olle 1275       {
6329 14 Jun 21 nicklas 1276         dc = sc.newDbControl(":Retraction wizard - destruct");
3323 11 May 15 nicklas 1277
3337 18 May 15 olle 1278         ReggieRole.checkPermission(dc, "'" + cmd + "' wizard", ReggieRole.PATIENT_CURATOR, ReggieRole.ADMINISTRATOR);
3337 18 May 15 olle 1279
3752 17 Feb 16 nicklas 1280         JSONObject jsonReq = JsonUtil.parseRequest(req);
3337 18 May 15 olle 1281         JSONObject jsonRetractedInfo = (JSONObject)jsonReq.get("retractionInfo");
4512 31 May 17 nicklas 1282         JSONArray jsonKeepLiasonComments = (JSONArray)jsonRetractedInfo.get("keepLiasonComments");
3337 18 May 15 olle 1283
4512 31 May 17 nicklas 1284         // If we want to keep liason comments we need to find out which case they belong to
4512 31 May 17 nicklas 1285         // We will only get comments on case/blood/specimen/nospecimen here
4512 31 May 17 nicklas 1286         // and map them to the case: case name -> list of comments
4512 31 May 17 nicklas 1287         // Liason comments on the patient item is handled when we create the patient copy
4512 31 May 17 nicklas 1288         Map<String, List<String>> liasonCommentsToKeep = new HashMap<>();
4512 31 May 17 nicklas 1289         if (jsonKeepLiasonComments.size() > 0)
4512 31 May 17 nicklas 1290         {
4512 31 May 17 nicklas 1291           
4512 31 May 17 nicklas 1292           ItemQuery<Sample> liasonQuery = Sample.getQuery();
4512 31 May 17 nicklas 1293           liasonQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
4512 31 May 17 nicklas 1294           liasonQuery.restrict(Restrictions.in(Hql.property("name"), Expressions.parameter("names")));
4512 31 May 17 nicklas 1295           liasonQuery.setParameter("names", jsonKeepLiasonComments, Type.STRING);
4512 31 May 17 nicklas 1296           for (Sample s : liasonQuery.list(dc))
4512 31 May 17 nicklas 1297           {
4512 31 May 17 nicklas 1298             String liasonComment = (String)Annotationtype.LIASON_COMMENT.getAnnotationValue(dc, s);
4512 31 May 17 nicklas 1299             if (liasonComment != null)
4512 31 May 17 nicklas 1300             {
4512 31 May 17 nicklas 1301               // Move up until we are just below the patient, this will be the item that is copied 
4512 31 May 17 nicklas 1302               // after destruction that should have the copy of the liason comment
4512 31 May 17 nicklas 1303               while (s.getParentType() != Item.BIOSOURCE)
4512 31 May 17 nicklas 1304               {
4512 31 May 17 nicklas 1305                 s = (Sample)s.getParent();
4512 31 May 17 nicklas 1306               }
4512 31 May 17 nicklas 1307               
4512 31 May 17 nicklas 1308               String caseName = s.getName();
4512 31 May 17 nicklas 1309               // Get rid of the '.b' suffix on blood items
4512 31 May 17 nicklas 1310               if (caseName.matches("\\d{7}\\.b.*"))
4512 31 May 17 nicklas 1311               {
4512 31 May 17 nicklas 1312                 caseName = caseName.substring(0, 7);
4512 31 May 17 nicklas 1313               }
4512 31 May 17 nicklas 1314               
4512 31 May 17 nicklas 1315               List<String> comments = liasonCommentsToKeep.get(caseName);
4512 31 May 17 nicklas 1316               if (comments == null)
4512 31 May 17 nicklas 1317               {
4512 31 May 17 nicklas 1318                 comments = new ArrayList<>();
4512 31 May 17 nicklas 1319                 liasonCommentsToKeep.put(caseName, comments);
4512 31 May 17 nicklas 1320               }
4512 31 May 17 nicklas 1321               comments.add(liasonComment);
4512 31 May 17 nicklas 1322             }
4512 31 May 17 nicklas 1323           }
4512 31 May 17 nicklas 1324         }
4512 31 May 17 nicklas 1325         
3766 23 Feb 16 nicklas 1326         // Get existing BioSource 
3766 23 Feb 16 nicklas 1327         Number patientId = (Number) jsonRetractedInfo.get("patientId");
5088 13 Nov 18 nicklas 1328         BioSource patient = BioSource.getById(dc, patientId.intValue());
3337 18 May 15 olle 1329         
3425 25 Jun 15 nicklas 1330         // Create a copy of patient item with same name
3425 25 Jun 15 nicklas 1331         BioSource patientCopy = BioSource.getNew(dc);
5088 13 Nov 18 nicklas 1332         patientCopy.setItemSubtype(patient.getItemSubtype());
5088 13 Nov 18 nicklas 1333         patientCopy.setExternalId(patient.getExternalId());
3425 25 Jun 15 nicklas 1334         patientCopy.setName(patient.getName());
3337 18 May 15 olle 1335         
3425 25 Jun 15 nicklas 1336         // Set patient copy RETRACT_STATUS annotation value to "RetractionCompleted"
3425 25 Jun 15 nicklas 1337         //String retractStatus = (String) Annotationtype.RETRACT_STATUS.getAnnotationValue(dc, patient.getBioSource());
3425 25 Jun 15 nicklas 1338         Annotationtype.RETRACT_STATUS.setAnnotationValue(dc, patientCopy, RETRACTION_COMPLETED);
4512 31 May 17 nicklas 1339         if (jsonKeepLiasonComments.indexOf(patientCopy.getName()) >= 0)
4512 31 May 17 nicklas 1340         {
5088 13 Nov 18 nicklas 1341           String liasonComment = (String)Annotationtype.LIASON_COMMENT.getAnnotationValue(dc, patient);
4512 31 May 17 nicklas 1342           if (liasonComment != null)
4512 31 May 17 nicklas 1343           {
4512 31 May 17 nicklas 1344             Annotationtype.LIASON_COMMENT.setAnnotationValue(dc, patientCopy, liasonComment);
4512 31 May 17 nicklas 1345           }
4512 31 May 17 nicklas 1346         }
3425 25 Jun 15 nicklas 1347         dc.saveItem(patientCopy);
3425 25 Jun 15 nicklas 1348         jsonMessages.add("Patient " + patient.getName() + " replaced by copy.");
3337 18 May 15 olle 1349
3388 11 Jun 15 nicklas 1350         Set<BasicItem> patientItemList = new LinkedHashSet<BasicItem>();
7049 15 Feb 23 nicklas 1351         Map<FileServer, Set<ExternalPath>> externalPaths = new HashMap<>();
3427 26 Jun 15 nicklas 1352         
5088 13 Nov 18 nicklas 1353         patientItemList.add(patient);
5088 13 Nov 18 nicklas 1354         collectAllChildItems(dc, patient, patientItemList);
3391 11 Jun 15 nicklas 1355         collectDirectories(dc, patientItemList);
3427 26 Jun 15 nicklas 1356         collectExternalPaths(dc, patientItemList, externalPaths);
3427 26 Jun 15 nicklas 1357         
3390 11 Jun 15 nicklas 1358         Map<String,List<Extract>> pooledLibNameParentListHM = fetchPooledLibraryNameParentExtractListHashMap(dc, patientItemList);
3390 11 Jun 15 nicklas 1359         ItemSubtype pooledLibraryType = Subtype.POOLED_LIBRARY.get(dc);
3425 25 Jun 15 nicklas 1360         ItemSubtype caseType = Subtype.CASE.get(dc);
3425 25 Jun 15 nicklas 1361         ItemSubtype bloodType = Subtype.BLOOD.get(dc);
5637 03 Oct 19 nicklas 1362         Set<ItemSubtype> storedSubtypes = getStoredSubtypes(dc);
3390 11 Jun 15 nicklas 1363
3425 25 Jun 15 nicklas 1364         List<BasicItem> deleteItemList = new ArrayList<BasicItem>();
3425 25 Jun 15 nicklas 1365         Set<String> caseCopies = new HashSet<String>();
4496 10 May 17 nicklas 1366         Date today = new Date();
3337 18 May 15 olle 1367         for (BasicItem basicItem: patientItemList)
3337 18 May 15 olle 1368         {
3337 18 May 15 olle 1369           String itemName = basicItem.toString();
3390 11 Jun 15 nicklas 1370           ItemSubtype subtype = null;
3337 18 May 15 olle 1371           if (basicItem instanceof Nameable)
3337 18 May 15 olle 1372           {
3337 18 May 15 olle 1373             itemName = ((Nameable)basicItem).getName();
3337 18 May 15 olle 1374           }
3390 11 Jun 15 nicklas 1375           if (basicItem instanceof Subtypable)
3390 11 Jun 15 nicklas 1376           {
3390 11 Jun 15 nicklas 1377             subtype = ((Subtypable)basicItem).getItemSubtype();
3390 11 Jun 15 nicklas 1378           }
3390 11 Jun 15 nicklas 1379
3425 25 Jun 15 nicklas 1380           if (caseType.equals(subtype))
3337 18 May 15 olle 1381           {
3425 25 Jun 15 nicklas 1382             if (caseCopies.add(itemName))
3337 18 May 15 olle 1383             {
3425 25 Jun 15 nicklas 1384               // Create copy of case
3425 25 Jun 15 nicklas 1385               Sample caseCopy = Sample.getNew(dc);
3425 25 Jun 15 nicklas 1386               caseCopy.setItemSubtype(caseType);
3425 25 Jun 15 nicklas 1387               caseCopy.setName(itemName);
3769 24 Feb 16 nicklas 1388               Annotationtype.CONSENT.setAnnotationValue(dc, caseCopy, "No");
4496 10 May 17 nicklas 1389               Annotationtype.CONSENT_DATE.setAnnotationValue(dc, caseCopy, today);
4512 31 May 17 nicklas 1390               if (liasonCommentsToKeep.containsKey(itemName))
4512 31 May 17 nicklas 1391               {
4512 31 May 17 nicklas 1392                 List<String> liasonComments = liasonCommentsToKeep.get(itemName);
4512 31 May 17 nicklas 1393                 Annotationtype.LIASON_COMMENT.setAnnotationValue(dc, caseCopy, Values.getString(liasonComments, "\n", true));
4512 31 May 17 nicklas 1394               }
3425 25 Jun 15 nicklas 1395   
3425 25 Jun 15 nicklas 1396               BioMaterialEvent creationEvent = caseCopy.getCreationEvent();
3425 25 Jun 15 nicklas 1397               creationEvent.setSource(patientCopy);
3425 25 Jun 15 nicklas 1398               dc.saveItem(caseCopy);
3425 25 Jun 15 nicklas 1399               jsonMessages.add("Case " + itemName + " replaced by copy.");
3425 25 Jun 15 nicklas 1400             }
3425 25 Jun 15 nicklas 1401           }
3425 25 Jun 15 nicklas 1402           else if (bloodType.equals(subtype))
3425 25 Jun 15 nicklas 1403           {
3425 25 Jun 15 nicklas 1404             // Check to if blood name is based on case name
3425 25 Jun 15 nicklas 1405             // (if not it is a followup blood)
3425 25 Jun 15 nicklas 1406             if (itemName.matches("\\d{7}\\.b.*"))
3425 25 Jun 15 nicklas 1407             {
3425 25 Jun 15 nicklas 1408               String caseName = itemName.substring(0, 7);
3425 25 Jun 15 nicklas 1409               if (caseCopies.add(caseName))
3337 18 May 15 olle 1410               {
3425 25 Jun 15 nicklas 1411                 // Create a case copy
3425 25 Jun 15 nicklas 1412                 Sample caseCopy = Sample.getNew(dc);
3425 25 Jun 15 nicklas 1413                 caseCopy.setItemSubtype(caseType);
3425 25 Jun 15 nicklas 1414                 caseCopy.setName(caseName);
3769 24 Feb 16 nicklas 1415                 Annotationtype.CONSENT.setAnnotationValue(dc, caseCopy, "No");
4496 10 May 17 nicklas 1416                 Annotationtype.CONSENT_DATE.setAnnotationValue(dc, caseCopy, today);
4512 31 May 17 nicklas 1417                 if (liasonCommentsToKeep.containsKey(caseName))
4512 31 May 17 nicklas 1418                 {
4512 31 May 17 nicklas 1419                   List<String> liasonComments = liasonCommentsToKeep.get(caseName);
4512 31 May 17 nicklas 1420                   Annotationtype.LIASON_COMMENT.setAnnotationValue(dc, caseCopy, Values.getString(liasonComments, "\n", true));
4512 31 May 17 nicklas 1421                 }
4496 10 May 17 nicklas 1422                 
3425 25 Jun 15 nicklas 1423                 BioMaterialEvent creationEvent = caseCopy.getCreationEvent();
3425 25 Jun 15 nicklas 1424                 creationEvent.setSource(patientCopy);
3425 25 Jun 15 nicklas 1425                 dc.saveItem(caseCopy);
3425 25 Jun 15 nicklas 1426                 jsonMessages.add("Blood " + itemName + " replaced by case copy.");
3425 25 Jun 15 nicklas 1427               }
3425 25 Jun 15 nicklas 1428             }
3425 25 Jun 15 nicklas 1429           }
3425 25 Jun 15 nicklas 1430           
5637 03 Oct 19 nicklas 1431           if (storedSubtypes.contains(subtype))
5637 03 Oct 19 nicklas 1432           {
5637 03 Oct 19 nicklas 1433             String retractStatus = (String)Annotationtype.RETRACT_STATUS.getAnnotationValue(dc, (Annotatable)basicItem);
5637 03 Oct 19 nicklas 1434             if (!RETRACTION_DESTROYED.equals(retractStatus))
5637 03 Oct 19 nicklas 1435             {
5637 03 Oct 19 nicklas 1436               throw new PermissionDeniedException(Permission.DELETE, 
5637 03 Oct 19 nicklas 1437                   itemName + " (" + subtype.getName() + ") is not registered as destroyed");
5637 03 Oct 19 nicklas 1438             }
5637 03 Oct 19 nicklas 1439           }
5637 03 Oct 19 nicklas 1440           
3425 25 Jun 15 nicklas 1441           if (pooledLibraryType.equals(subtype))
3425 25 Jun 15 nicklas 1442           {
3425 25 Jun 15 nicklas 1443             // Remove extracts to be removed from pooled library parent list
3425 25 Jun 15 nicklas 1444             String comment = " retained.";
3425 25 Jun 15 nicklas 1445             List<Extract> pooledLibParentsList = pooledLibNameParentListHM.get(itemName);
3425 25 Jun 15 nicklas 1446             if (pooledLibParentsList != null)
3425 25 Jun 15 nicklas 1447             {
3425 25 Jun 15 nicklas 1448               BioMaterialEvent created = ((Extract)basicItem).getCreationEvent();
3425 25 Jun 15 nicklas 1449               String parentExtractsStr = "";
3425 25 Jun 15 nicklas 1450               String pluralSuffix = "";
3425 25 Jun 15 nicklas 1451               for (Extract e: pooledLibParentsList)
3425 25 Jun 15 nicklas 1452               {
3425 25 Jun 15 nicklas 1453                 if (!parentExtractsStr.equals(""))
3337 18 May 15 olle 1454                 {
3425 25 Jun 15 nicklas 1455                   parentExtractsStr += ", ";
3425 25 Jun 15 nicklas 1456                   pluralSuffix = "s";
3337 18 May 15 olle 1457                 }
3425 25 Jun 15 nicklas 1458                 parentExtractsStr += e.getName();
3425 25 Jun 15 nicklas 1459                 // Remove extract to be removed from pooled library parent list
3425 25 Jun 15 nicklas 1460                 created.removeSource(e);
3337 18 May 15 olle 1461               }
3425 25 Jun 15 nicklas 1462               comment = " retained, but extract" + pluralSuffix + " " + parentExtractsStr + " removed from parent list.";
3337 18 May 15 olle 1463             }
3425 25 Jun 15 nicklas 1464             jsonMessages.add(itemName + comment);
3337 18 May 15 olle 1465           }
3425 25 Jun 15 nicklas 1466           else
3425 25 Jun 15 nicklas 1467           {
3425 25 Jun 15 nicklas 1468             // Add item to list of items to delete
3425 25 Jun 15 nicklas 1469             deleteItemList.add(basicItem);
3425 25 Jun 15 nicklas 1470           }
3337 18 May 15 olle 1471         }
3337 18 May 15 olle 1472
3337 18 May 15 olle 1473         for (int i = 0; i < deleteItemList.size(); i++)
3337 18 May 15 olle 1474         {
5415 09 May 19 nicklas 1475           BasicItem deleteItem = deleteItemList.get(i);
3337 18 May 15 olle 1476           String itemName = deleteItem.toString();
3337 18 May 15 olle 1477           if (deleteItem instanceof Nameable)
3337 18 May 15 olle 1478           {
3337 18 May 15 olle 1479             itemName = ((Nameable)deleteItem).getName();
3337 18 May 15 olle 1480           }
3374 09 Jun 15 nicklas 1481           if (deleteItem instanceof File)
3374 09 Jun 15 nicklas 1482           {
3374 09 Jun 15 nicklas 1483             File f = (File)deleteItem;
3390 11 Jun 15 nicklas 1484             itemName = f.getPath().toString();
3374 09 Jun 15 nicklas 1485             if (f.isWriteProtected())
3374 09 Jun 15 nicklas 1486             {
3374 09 Jun 15 nicklas 1487               f.setWriteProtected(false);
3374 09 Jun 15 nicklas 1488               dc.reattachItem(f, true); // Needed since DELETE permissions is not granted otherwise
3374 09 Jun 15 nicklas 1489             }
3374 09 Jun 15 nicklas 1490           }
3391 11 Jun 15 nicklas 1491           else if (deleteItem instanceof Directory)
3391 11 Jun 15 nicklas 1492           {
3391 11 Jun 15 nicklas 1493             Directory d = (Directory)deleteItem;
3391 11 Jun 15 nicklas 1494             itemName = d.getPath().toString();
3391 11 Jun 15 nicklas 1495           }
3337 18 May 15 olle 1496           if (deleteItem instanceof Removable)
3337 18 May 15 olle 1497           {
3337 18 May 15 olle 1498             ((Removable)deleteItem).setRemoved(true);
3427 26 Jun 15 nicklas 1499             //jsonMessages.add(itemName + " marked for removal.");
3337 18 May 15 olle 1500           }
3337 18 May 15 olle 1501         }
3337 18 May 15 olle 1502         jsonMessages.add(deleteItemList.size() + " items marked for removal.");
3427 26 Jun 15 nicklas 1503         dc.commit();
7049 15 Feb 23 nicklas 1504         //dc.close();
3427 26 Jun 15 nicklas 1505         
3427 26 Jun 15 nicklas 1506         int numDeletedItems = Trashcan.delete(sc, deleteItemList, true, null);
3427 26 Jun 15 nicklas 1507         //int numDeletedItems = deleteItemList.size();
3337 18 May 15 olle 1508         jsonMessages.add(numDeletedItems + " items were deleted.");
7049 15 Feb 23 nicklas 1509         for (Map.Entry<FileServer, Set<ExternalPath>> entry : externalPaths.entrySet())
3427 26 Jun 15 nicklas 1510         {
3427 26 Jun 15 nicklas 1511           FileServer server = entry.getKey();
7049 15 Feb 23 nicklas 1512           Set<ExternalPath> paths = entry.getValue();
5645 07 Oct 19 nicklas 1513           if (paths.size() == 0) continue;
3427 26 Jun 15 nicklas 1514           
4306 17 Jan 17 nicklas 1515           RemoteHost host = new RemoteHost(new ConnectionInfo(server));
4306 17 Jan 17 nicklas 1516           RemoteSession session = null;
3427 26 Jun 15 nicklas 1517           try
3427 26 Jun 15 nicklas 1518           {
4306 17 Jan 17 nicklas 1519             session = host.connect(5);
7049 15 Feb 23 nicklas 1520             for (ExternalPath xPath : paths)
3427 26 Jun 15 nicklas 1521             {
7049 15 Feb 23 nicklas 1522               URI uri = new URI(xPath.path);
7049 15 Feb 23 nicklas 1523               String path = uri.getPath();
7049 15 Feb 23 nicklas 1524               String rmCmd = "rm "+(xPath.isFolder ? "-rfv " : "-fv ");
7049 15 Feb 23 nicklas 1525               String rm = rmCmd+server.getRootPath()+path;
3427 26 Jun 15 nicklas 1526               try
3427 26 Jun 15 nicklas 1527               {
7049 15 Feb 23 nicklas 1528                 String rmChecked = rmCmd+server.getRootPath()+ScriptUtil.checkValidPath(path, true, false);
4306 17 Jan 17 nicklas 1529                 CmdResult<String> result = session.executeCmd(rmChecked, 30000);
3427 26 Jun 15 nicklas 1530                 if (result.getExitStatus() == 0)
3427 26 Jun 15 nicklas 1531                 {
3427 26 Jun 15 nicklas 1532                   String[] lines = result.getStdout().split("\\n");
3427 26 Jun 15 nicklas 1533                   jsonMessages.add(rm + ": " + lines.length + " files/directories deleted");
3427 26 Jun 15 nicklas 1534                 }
3427 26 Jun 15 nicklas 1535                 else
3427 26 Jun 15 nicklas 1536                 {
3427 26 Jun 15 nicklas 1537                   jsonMessages.add("[Error]" + result.toString());
3427 26 Jun 15 nicklas 1538                 }
3427 26 Jun 15 nicklas 1539               }
3427 26 Jun 15 nicklas 1540               catch (RuntimeException ex)
3427 26 Jun 15 nicklas 1541               {
3427 26 Jun 15 nicklas 1542                 jsonMessages.add("[Error]" + rm + ": " + ex.getMessage());
3427 26 Jun 15 nicklas 1543               }
3427 26 Jun 15 nicklas 1544             }
3427 26 Jun 15 nicklas 1545           }
3427 26 Jun 15 nicklas 1546           catch (RuntimeException ex)
3427 26 Jun 15 nicklas 1547           {
3427 26 Jun 15 nicklas 1548             jsonMessages.add("[Error]" + server.getName() + ": " + ex.getMessage());
3427 26 Jun 15 nicklas 1549           }
3427 26 Jun 15 nicklas 1550           finally
3427 26 Jun 15 nicklas 1551           {
4306 17 Jan 17 nicklas 1552             OpenGrid.close(session);
3427 26 Jun 15 nicklas 1553           }
3427 26 Jun 15 nicklas 1554           
3427 26 Jun 15 nicklas 1555         }
3337 18 May 15 olle 1556       }
3337 18 May 15 olle 1557
3059 19 Dec 14 nicklas 1558       json.put("messages", jsonMessages);
3059 19 Dec 14 nicklas 1559       CounterService.getInstance().setForceCount();
2839 20 Oct 14 olle 1560     }
2839 20 Oct 14 olle 1561     catch (Throwable t)
2839 20 Oct 14 olle 1562     {
2839 20 Oct 14 olle 1563       t.printStackTrace();
2839 20 Oct 14 olle 1564       json.clear();
2839 20 Oct 14 olle 1565       json.put("status", "error");
2839 20 Oct 14 olle 1566       json.put("message", t.getMessage());
2839 20 Oct 14 olle 1567       json.put("stacktrace", ThrowableUtil.stackTraceToString(t));
2839 20 Oct 14 olle 1568     }
2839 20 Oct 14 olle 1569     finally
2839 20 Oct 14 olle 1570     {
2839 20 Oct 14 olle 1571       if (dc != null) dc.close();
2839 20 Oct 14 olle 1572       json.writeJSONString(resp.getWriter());
2839 20 Oct 14 olle 1573     }
2839 20 Oct 14 olle 1574     
2839 20 Oct 14 olle 1575   }
3334 13 May 15 olle 1576
3337 18 May 15 olle 1577   /**
3337 18 May 15 olle 1578    * Returns a hashmap with pooled library names as keys
3337 18 May 15 olle 1579    * and parent extract list as value for an input list
3337 18 May 15 olle 1580    * of basicitems.
3337 18 May 15 olle 1581    * 
3337 18 May 15 olle 1582    * @param dc DbControl The DbControl to use.
3571 30 Oct 15 nicklas 1583    * @param items List<BasicItem> The basicItem list to search for parents to pooled libraries.
3337 18 May 15 olle 1584    * @return HashMap<String,List<Extract>> The hashmap with pooled library names as keys and parent extract list as value.
3337 18 May 15 olle 1585    */
3388 11 Jun 15 nicklas 1586   private HashMap<String,List<Extract>> fetchPooledLibraryNameParentExtractListHashMap(DbControl dc, Set<BasicItem> items)
3337 18 May 15 olle 1587   {
3337 18 May 15 olle 1588     HashMap<String,List<Extract>> hashMap = new HashMap<String,List<Extract>>();
3390 11 Jun 15 nicklas 1589     ItemSubtype pooledLibType = Subtype.POOLED_LIBRARY.get(dc);
3388 11 Jun 15 nicklas 1590     for (BasicItem basicItem: items)
3337 18 May 15 olle 1591     {
3337 18 May 15 olle 1592       if (basicItem instanceof Extract)
3337 18 May 15 olle 1593       {
3390 11 Jun 15 nicklas 1594         Extract e = (Extract)basicItem;
3390 11 Jun 15 nicklas 1595         if (pooledLibType.equals(e.getItemSubtype()))
3337 18 May 15 olle 1596         {
3390 11 Jun 15 nicklas 1597           // Find parent extracts that are also in the list of items to delete
5363 16 Apr 19 nicklas 1598           ItemQuery<Extract> parentQuery = e.getCreationEvent().getSources();
3390 11 Jun 15 nicklas 1599           parentQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
3390 11 Jun 15 nicklas 1600           List<Extract> parentsToDelete = new ArrayList<Extract>();
3390 11 Jun 15 nicklas 1601           for (Extract parent : parentQuery.list(dc))
3337 18 May 15 olle 1602           {
3390 11 Jun 15 nicklas 1603             if (items.contains(parent)) parentsToDelete.add(parent);
3337 18 May 15 olle 1604           }
3390 11 Jun 15 nicklas 1605           hashMap.put(e.getName(), parentsToDelete);
3337 18 May 15 olle 1606         }
3337 18 May 15 olle 1607       }
3390 11 Jun 15 nicklas 1608       
3337 18 May 15 olle 1609     }
3337 18 May 15 olle 1610     return hashMap;
3337 18 May 15 olle 1611   }
3337 18 May 15 olle 1612
3337 18 May 15 olle 1613   /**
3337 18 May 15 olle 1614    * Finds all sub-items to a basicItem using method Set<ItemProxy> getUsingItems()
3337 18 May 15 olle 1615    * and recursion.
3337 18 May 15 olle 1616    * 
3337 18 May 15 olle 1617    * @param dc DbControl The DbControl to use.
3337 18 May 15 olle 1618    * @param basicItem BasicItem The basicItem to find sub-items for.
3571 30 Oct 15 nicklas 1619    * @param allChildItems The list to store the sub-items in.
3337 18 May 15 olle 1620    */
3388 11 Jun 15 nicklas 1621   private void collectAllChildItems(DbControl dc, BasicItem basicItem, Set<BasicItem> allChildItems)
3337 18 May 15 olle 1622   {
3337 18 May 15 olle 1623     Set<ItemProxy> itemProxySet = basicItem.getUsingItems();
3337 18 May 15 olle 1624     // Recursion to find all sub-items
3337 18 May 15 olle 1625     for (ItemProxy ip: itemProxySet)
3337 18 May 15 olle 1626     {
3374 09 Jun 15 nicklas 1627       BasicItem item = ip.getItem(dc);
3388 11 Jun 15 nicklas 1628       if (allChildItems.add(item))
3337 18 May 15 olle 1629       {
3386 10 Jun 15 nicklas 1630         if (item instanceof Subtypable)
3386 10 Jun 15 nicklas 1631         {
3386 10 Jun 15 nicklas 1632           // Check subtype and do not continue if the item is a pooled library
3386 10 Jun 15 nicklas 1633           ItemSubtype subtype = ((Subtypable)item).getItemSubtype();
3386 10 Jun 15 nicklas 1634           if (Subtype.POOLED_LIBRARY.get(dc).equals(subtype)) continue;
3386 10 Jun 15 nicklas 1635         }
3386 10 Jun 15 nicklas 1636         
3387 10 Jun 15 nicklas 1637         // Linked files via FileSets
3387 10 Jun 15 nicklas 1638         if (item instanceof FileStoreEnabled)
3387 10 Jun 15 nicklas 1639         {
3387 10 Jun 15 nicklas 1640           FileStoreEnabled fs = (FileStoreEnabled)item;
3387 10 Jun 15 nicklas 1641           if (fs.hasFileSet())
3387 10 Jun 15 nicklas 1642           {
3387 10 Jun 15 nicklas 1643             ItemQuery<FileSetMember> fileQuery = fs.getFileSet().getMembers();
3387 10 Jun 15 nicklas 1644             for (FileSetMember file : fileQuery.list(dc))
3387 10 Jun 15 nicklas 1645             {
3387 10 Jun 15 nicklas 1646               File f = file.getFile();
3388 11 Jun 15 nicklas 1647               if (allChildItems.add(f))
3388 11 Jun 15 nicklas 1648               {
3388 11 Jun 15 nicklas 1649                 collectAllChildItems(dc, f, allChildItems);
3388 11 Jun 15 nicklas 1650               }
3387 10 Jun 15 nicklas 1651             }
3387 10 Jun 15 nicklas 1652           }
3387 10 Jun 15 nicklas 1653         }
3387 10 Jun 15 nicklas 1654         
3387 10 Jun 15 nicklas 1655         // Other linked items
3374 09 Jun 15 nicklas 1656         ItemQuery<AnyToAny> linkQuery = AnyToAny.getLinksFrom(item);
3374 09 Jun 15 nicklas 1657         for (AnyToAny link : linkQuery.list(dc))
3374 09 Jun 15 nicklas 1658         {
3374 09 Jun 15 nicklas 1659           BasicItem to = link.getTo();
3388 11 Jun 15 nicklas 1660           if (allChildItems.add(to))
3388 11 Jun 15 nicklas 1661           {
3388 11 Jun 15 nicklas 1662             collectAllChildItems(dc, to, allChildItems);
3388 11 Jun 15 nicklas 1663           }
3374 09 Jun 15 nicklas 1664         }
3388 11 Jun 15 nicklas 1665         collectAllChildItems(dc, item, allChildItems);
3337 18 May 15 olle 1666       }
3337 18 May 15 olle 1667     }
3337 18 May 15 olle 1668   }
3391 11 Jun 15 nicklas 1669   
3391 11 Jun 15 nicklas 1670   /**
3391 11 Jun 15 nicklas 1671     Find directories that also should be deleted. Typically, we are
3391 11 Jun 15 nicklas 1672     interested in the top-level secondary analysis directory for
3391 11 Jun 15 nicklas 1673     the sample(s). This will also find extra files that we have not
3391 11 Jun 15 nicklas 1674     found by following links from the derived and raw bioassays.
3391 11 Jun 15 nicklas 1675   */
3391 11 Jun 15 nicklas 1676   private void collectDirectories(DbControl dc, Set<BasicItem> allChildItems)
3391 11 Jun 15 nicklas 1677   {
3391 11 Jun 15 nicklas 1678     // Make copy so we can iterate and add to the child items
3391 11 Jun 15 nicklas 1679     Set<BasicItem> copy = new LinkedHashSet<BasicItem>(allChildItems);
3391 11 Jun 15 nicklas 1680     
3391 11 Jun 15 nicklas 1681     // We look for the directory that has CCCCCCC.N pattern were CCCCCCC is the case number and N a digit
3427 26 Jun 15 nicklas 1682     Pattern findTopDirInSecondaryAnalysis = Pattern.compile("(" + Reggie.SECONDARY_ANALYSIS_DIR + ".*?/(\\d{7}\\.\\d+))/(.*)");
3391 11 Jun 15 nicklas 1683     
3391 11 Jun 15 nicklas 1684     for (BasicItem item : copy)
3391 11 Jun 15 nicklas 1685     {
3391 11 Jun 15 nicklas 1686       if (item instanceof File)
3391 11 Jun 15 nicklas 1687       {
3427 26 Jun 15 nicklas 1688         File file = (File)item;
3427 26 Jun 15 nicklas 1689         String path = file.getPath().toString();
3427 26 Jun 15 nicklas 1690         
3391 11 Jun 15 nicklas 1691         // Secondary analysis directory structure should be deleted
3391 11 Jun 15 nicklas 1692         if (path.startsWith(Reggie.SECONDARY_ANALYSIS_DIR))
3391 11 Jun 15 nicklas 1693         {
3391 11 Jun 15 nicklas 1694           // Find top level directory for this sample
3391 11 Jun 15 nicklas 1695           Matcher m = findTopDirInSecondaryAnalysis.matcher(path);
3391 11 Jun 15 nicklas 1696           if (m.matches())
3391 11 Jun 15 nicklas 1697           {
3391 11 Jun 15 nicklas 1698             Path dir = new Path(m.group(1), Path.Type.DIRECTORY);
3391 11 Jun 15 nicklas 1699             Directory d = Directory.getByPath(dc, dir);
3391 11 Jun 15 nicklas 1700             if (allChildItems.add(d))
3391 11 Jun 15 nicklas 1701             {
3391 11 Jun 15 nicklas 1702               collectAllChildItems(dc, d, allChildItems);
3391 11 Jun 15 nicklas 1703             }
3391 11 Jun 15 nicklas 1704           }
3391 11 Jun 15 nicklas 1705         }
3391 11 Jun 15 nicklas 1706       }
3391 11 Jun 15 nicklas 1707     }
3427 26 Jun 15 nicklas 1708   }
3427 26 Jun 15 nicklas 1709   
3427 26 Jun 15 nicklas 1710   /**
3427 26 Jun 15 nicklas 1711     Find files that are located on external servers that we know
7048 15 Feb 23 nicklas 1712     about (eg. {@link Fileserver#PROJECT_ARCHIVE} and {@link Fileserver#PROJECT_ARCHIVE_DNA})
7048 15 Feb 23 nicklas 1713     and collect top-level directories that should be deleted.
3427 26 Jun 15 nicklas 1714   */
7049 15 Feb 23 nicklas 1715   private void collectExternalPaths(DbControl dc, Set<BasicItem> allChildItems, Map<FileServer, Set<ExternalPath>> externalServerPaths)
3427 26 Jun 15 nicklas 1716   {
7049 15 Feb 23 nicklas 1717     externalServerPaths.put(Fileserver.PROJECT_ARCHIVE.load(dc), new HashSet<ExternalPath>());
7049 15 Feb 23 nicklas 1718     externalServerPaths.put(Fileserver.PROJECT_ARCHIVE_DNA.load(dc), new HashSet<ExternalPath>());
7050 17 Feb 23 nicklas 1719     externalServerPaths.put(Fileserver.IMPORT_GATEWAY.load(dc), new HashSet<ExternalPath>());
7049 15 Feb 23 nicklas 1720     externalServerPaths.put(Fileserver.IMPORT_ARCHIVE.load(dc), new HashSet<ExternalPath>());
3391 11 Jun 15 nicklas 1721     
3427 26 Jun 15 nicklas 1722     // We look for the directory that has CCCCCCC.N pattern were CCCCCCC is the case number and N a digit
3427 26 Jun 15 nicklas 1723     Pattern findTopSampleDir = Pattern.compile("(.*?/(\\d{7}\\.\\d+))/(.*)");
3427 26 Jun 15 nicklas 1724     
3427 26 Jun 15 nicklas 1725     for (BasicItem item : allChildItems)
3427 26 Jun 15 nicklas 1726     {
3427 26 Jun 15 nicklas 1727       if (!(item instanceof File)) continue;
3427 26 Jun 15 nicklas 1728       File file = (File)item;
3427 26 Jun 15 nicklas 1729       
3427 26 Jun 15 nicklas 1730       // Ignore files not on external server
3427 26 Jun 15 nicklas 1731       if (file.getLocation() != Location.EXTERNAL) continue;
3427 26 Jun 15 nicklas 1732
3427 26 Jun 15 nicklas 1733       // Check if this is a server we care about
3427 26 Jun 15 nicklas 1734       FileServer server = file.getFileServer();
3427 26 Jun 15 nicklas 1735       if (!externalServerPaths.containsKey(server)) continue;
3427 26 Jun 15 nicklas 1736       
7049 15 Feb 23 nicklas 1737       // Test if path matches a top-level sample directory
7049 15 Feb 23 nicklas 1738       Set<ExternalPath> externalPaths = externalServerPaths.get(server);
3427 26 Jun 15 nicklas 1739       String path = file.getUrl();
7049 15 Feb 23 nicklas 1740       boolean isFolder = false;
3427 26 Jun 15 nicklas 1741       Matcher m = findTopSampleDir.matcher(path);
7049 15 Feb 23 nicklas 1742       if (m.matches()) 
7049 15 Feb 23 nicklas 1743       {
7049 15 Feb 23 nicklas 1744         path = path.substring(0, m.end(1));
7049 15 Feb 23 nicklas 1745         isFolder = true;
7049 15 Feb 23 nicklas 1746       }
7049 15 Feb 23 nicklas 1747
7049 15 Feb 23 nicklas 1748       externalPaths.add(new ExternalPath(path, isFolder));
3427 26 Jun 15 nicklas 1749     }
3391 11 Jun 15 nicklas 1750   }
7049 15 Feb 23 nicklas 1751   
7049 15 Feb 23 nicklas 1752   /**
7049 15 Feb 23 nicklas 1753     A path to an external file or folder.
7049 15 Feb 23 nicklas 1754   */
7049 15 Feb 23 nicklas 1755   static class ExternalPath
7049 15 Feb 23 nicklas 1756   {
7049 15 Feb 23 nicklas 1757     final String path;
7049 15 Feb 23 nicklas 1758     final boolean isFolder;
7049 15 Feb 23 nicklas 1759     
7049 15 Feb 23 nicklas 1760     ExternalPath(String path, boolean isFolder)
7049 15 Feb 23 nicklas 1761     {
7049 15 Feb 23 nicklas 1762       this.path = path;
7049 15 Feb 23 nicklas 1763       this.isFolder = isFolder;
7049 15 Feb 23 nicklas 1764     }
7049 15 Feb 23 nicklas 1765
7049 15 Feb 23 nicklas 1766     @Override
7049 15 Feb 23 nicklas 1767     public int hashCode() 
7049 15 Feb 23 nicklas 1768     {
7049 15 Feb 23 nicklas 1769       return path.hashCode();
7049 15 Feb 23 nicklas 1770     }
7049 15 Feb 23 nicklas 1771
7049 15 Feb 23 nicklas 1772     @Override
7049 15 Feb 23 nicklas 1773     public boolean equals(Object obj)
7049 15 Feb 23 nicklas 1774     {
7049 15 Feb 23 nicklas 1775       if (!(obj instanceof ExternalPath)) return false;
7049 15 Feb 23 nicklas 1776       ExternalPath other = (ExternalPath)obj;
7049 15 Feb 23 nicklas 1777       return path.equals(other.path) && isFolder == other.isFolder;
7049 15 Feb 23 nicklas 1778     }
7049 15 Feb 23 nicklas 1779
7049 15 Feb 23 nicklas 1780     @Override
7049 15 Feb 23 nicklas 1781     public String toString() 
7049 15 Feb 23 nicklas 1782     {
7049 15 Feb 23 nicklas 1783       return path;
7049 15 Feb 23 nicklas 1784     }
7049 15 Feb 23 nicklas 1785     
7049 15 Feb 23 nicklas 1786   }
2839 20 Oct 14 olle 1787 }
7049 15 Feb 23 nicklas 1788
7049 15 Feb 23 nicklas 1789
7049 15 Feb 23 nicklas 1790